Change Case

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;
}
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.
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
@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
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
		}
	}
}
 


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;
}
@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.
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.
thanks all
i will try all your ideas


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
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.
yes thank u its help alot
Topic archived. No new replies allowed.