Change Case

Dec 27, 2010 at 4:03pm
hello can u see what the wrong in my code
the program reads a string.Then passes it to a function ChangeCase . The function should change the case of each letter.
• Examples: School ... sCHOOL
Requirements are
Use functions: tolower(ch), toupper(ch), islower(ch) and isupper(ch).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
#include <stdio.h>
#include <ctype.h>
using namespace std;
int ChangeCase(char s[]){
	int i=0;
  char c;
  while (s[i])
  {
    c=s[i];
	if (islower(c)) {c=toupper(c);putchar (c);}
	else (isupper(c)){c=tolower(c);putchar (c);}

    i++;}
  return 0;}
int main(){
	char s[];
cout<<"welcome"<<endl;
cout<<"Enter your word";
cin>>s[];
ChangeCase(s[]);

return 0;
}
Dec 27, 2010 at 4:27pm
I don't think you should be printing anything in your ChangeCase() function. It should only change the case of the characters in the array.

Also, your function only prints when you change the case of something. I think you probably want to print everything.

Finally, you need to have space to store the string you get from the user. What you have on line 17 does not declare an array with space to store things.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <cctype>     // not <ctype.h> -- you're using C++
#include <iostream>
using namespace std;  // that's it -- you don't need anything from <cstdio>!

void ChangeCase( char* s )
{
  /* your code to change case ('X' to 'x' and 'x' to 'X') goes here */
}

int main()
{
  // Here is where we will keep the string the user gives us
  char s[ 100 ];

  // Ask for and get the string from the user. Remember, we only have room for 100 characters!
  cout << "Enter your word: ";
  cin.getline( s, 100 );

  // The function will change the case of letters: modifying the string in s
  ChangeCase( s );

  // Print the changed string
  cout << s << endl;

  return 0;
}

Hope this helps.
Dec 27, 2010 at 7:30pm
You could also use a for loop instead of a while loop; it makes the code a little easier to understand.
Instead of checking for i to be in bounds you check if the character is there.
Checking if the character is upper after you already know it is not lower is a little useless, so I left that out.

1
2
3
4
5
6
void ChangeCase(char* s)
{
	for(int i=0;s[i];i++) 
		if (islower(s[i])) s[i] = toupper(s[i]); 
		else s[i] = tolower(s[i]);
}


You could also go with character codes. Could be faster:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
void ChangeCase(char* s)
{
	for(int i=0;s[i];i++) 
	{
		if((s[i] > 64)&&(s[i] < 91)) //check if in range of upper case characters
		{
			s[i] += 32; //is upper, offset 32 to make lower
		}
		else if((s[i] > 96)&&(s[i] < 123)) //check if in range of lower case characters
		{
			s[i] -= 32; //is lower, offset -32 to make upper
		}
	}
}


Why the 32? Because to change A (65) to a (97) you have to offset with +32 :P

Usage of both functions:
1
2
3
4
5
6
7
8
9
10
int main()
{
	char c[] = "School";
	cout << "Old text:\n";
	cout << c << "\n" << "\n";
	ChangeCase(c);
	cout << "New text:\n";
	cout << c << "\n";
	return 0;
}


I used the following site as reference to see the character ranges:
http://www.asciitable.com/
Last edited on Dec 27, 2010 at 7:43pm
Dec 27, 2010 at 7:46pm
@bergerkiller,
The whole point of the ctype library is to eliminate constructs like (s[i] > 64)&&(s[i] < 91)

All toupper() and tolower() do is this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/** 
 * \brief	Convert c to lower case
 * \param c	Character to convert
 * \return	Returns c if the conversion was not possible, or the uppercase
 *		character if it was.
 */
int tolower(int c)
{
	if (!isupper(c))
		return c;
	return ((c - 'A') + 'a');
}

/** 
 * \brief	Convert c to upper case
 * \param c	Character to convert
 * \return	Returns c if the conversion was not possible, or the lowercase
 *		character if it was.
 */
int toupper(int c)
{
	if (!islower(c))
		return c;
	return ((c - 'a') + 'A');
}
Last edited on Dec 27, 2010 at 7:47pm
Dec 27, 2010 at 7:52pm
thank u so much

but in your code i can add the condition
1
2
if (islower(c)) {c=toupper(c);putchar (c);}
	else (isupper(c)){c=tolower(c);putchar (c);}


or not important
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
void ChangeCase(char* s)
{
	for(int i=0;s[i];i++) 
	{
		if((s[i] > 64)&&(s[i] < 91)) //check if in range of upper case characters
		{
			s[i] += 32; //is upper, offset 32 to make lower
		}
		else if((s[i] > 96)&&(s[i] < 123)) //check if in range of lower case characters
		{
			s[i] -= 32; //is lower, offset -32 to make upper
		}
	}
}
 


Dec 27, 2010 at 7:56pm
You don't need to check c before you pass it to to[lower,upper]() because those functions do that. If c does not need to be converted, then it is returned verbatim.

The code
1
2
3
4
5
while (*s != 0) {
	if (islower(*s))
		*s = toupper(*s);
	++s;
}

is equivalent to
1
2
3
4
while (*s != 0) {
	*s = toupper(*s);
	++s;
}
Dec 27, 2010 at 10:01pm
@chrisname:
What you say is technically correct, but unless I'm mistaken he wants to flip the Caps (e.g turn "Red FoX NAy" into rED fOx naY").
You need to check it to do that.
Dec 27, 2010 at 10:30pm
Oh, right, in that case, you should do:
1
2
3
4
5
6
7
while (*s != 0) {
	if (islower(*s))
		*s = toupper(*s);
	else
		*s = tolower(*s);
	++s;
}


I would still strongly recommend against using
1
2
3
4
5
6
7
8
		if((s[i] > 64)&&(s[i] < 91)) //check if in range of upper case characters
		{
			s[i] += 32; //is upper, offset 32 to make lower
		}
		else if((s[i] > 96)&&(s[i] < 123)) //check if in range of lower case characters
		{
			s[i] -= 32; //is lower, offset -32 to make upper
		}

when the ctype library was created specifically to stop people from doing that.
Dec 28, 2010 at 3:46am
thanks all
i will try all your ideas


Dec 29, 2010 at 12:21pm
this is the last sloution


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include<iostream>
using namespace std;
void ChangeCase(char word[]){
for(int i=0;i<strlen(word);i++){
if(isupper(word[i]))
word[i]=tolower(word[i]);
else
if(islower(word[i]))
word[i]=toupper(word[i]);
}
}
int main(){

char word[20]="C++ ProGram";
ChangeCase(word);
cout<<word;



return 0;}
Last edited on Dec 29, 2010 at 12:23pm
Dec 29, 2010 at 1:51pm
Good job. You just need to apply some careful formatting to your code. (If you do this from the very start it will be much easier for you to reason about your code. You'll notice that everyone who responded here posted nicely formatted code which is easy to read and understand. If you do the same to your code you'll find that you struggle less with it.

Use whitespace liberally. Things that are subordinate to another thing need to be indented further. For example:
1
2
3
4
5
6
7
8
9
10
int myfunction()  // no indent -- the function is at the file level
{
  // everything inside the function gets an indent, since it is all inside the function

  if (fooey())
    barf();  // again, we only barf if fooey happens -- so we indent a little more on this line than the if's line

  return 9;  // since this is not dependent on fooey(), but it is on myfunction(), we return to the function body indent distance
}
Notice also how I put the open and close braces on the same line, and how there is a blank line following the closing brace. While style is a matter of taste and debate, in your particular case this particular form is a good idea. It will help you to uncrowd your program and manage indenting properly. It will also get you higher marks from your professor. (Honest!)


Well then, without further ado, here is your program:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <cstring>
#include <iostream>
using namespace std;

void ChangeCase(char word[])
{
  for(size_t i = 0; i < strlen(word); i++)
  {
    if(isupper(word[i]))
      word[i] = tolower(word[i]);
    else
      if(islower(word[i]))
        word[i] = toupper(word[i]);
  }
}

int main()
{
  char word[20] = "C++ ProGram";

  ChangeCase(word);
  cout << word;

  return 0;
}
I made two changes.

Line 1: this one was necessary, since you use strlen() on line 7. Whenever you use a function it is a good idea to make sure you have its header #included at the top of your code. You can find out what header is necessary just by googling something like "c++ strlen". Your top result will usually point right back to this site. The file to #include is listed on the top, right side of the page.
You don't technically need to use strlen(). Line 7 could read:
   7   for (size_t i = 0; word[i] != '\0'; i++)
Every c-string ends with the zero character ('\0'), so you can just stop when you find it.

Line 7: this change was not necessary, but you might as well learn it anyway. ;-)
Using int as your loop counter variable i's type is fine, but it causes compiler warnings when it doesn't match the signedness of strlen()'s result. If you use the same type for the variable as returned by strlen(), then there is no sign mismatch and the compiler doesn't spew verbiage at you.

Hope this helps.
Dec 31, 2010 at 11:38am
yes thank u its help alot
Topic archived. No new replies allowed.