-1

So I am still new to C++, and I'm trying to make a program that has the user input a string, and then my functions return the string in reverse case, all lower case, and then all uppercase. Instead I just keep receiving the first letter of the string back, always uppercase. Not sure what I am doing wrong. Any suggestions?

#include <iostream>
#include <string>
#include <cstring>
using namespace std;

char answer[255] = "";
int max = strlen(answer);

void reverse() {
    for (int i = 0; i < max; i++) {
        if (islower(answer[i])) {
            isupper(answer[i]);
        }
        else if (isupper(answer[i])) {
            islower(answer[i]);
        }
        else if (isspace(answer[i])) {
            isspace(answer[i]);
        }
    }
    cout << answer[max];
}

void lower() {
    for (int i = 0; i < max; i++) {
        if (isupper(answer[i])) {
            islower(answer[i]);
        }
        else {
            answer[i] = answer[i];
        }
    }
    cout << answer[max];
}

void upper() {
    for (int i = 0; i < max; i++) {
        if (islower(answer[i])) {
            isupper(answer[i]);
        }
        else {
            answer[i] = answer[i];
        }
    }
    cout << answer[max];
}

int main() {

    cout << "Please enter a word, or a series of words: " << endl;
    cin >> answer[max];

    reverse();
    lower();
    upper();

    system("pause");
    return 0;
}
Harshith Rai
  • 3,018
  • 7
  • 22
  • 35
webbern
  • 19
  • 2
  • Post your code as text, not as an image. It would just make it a whole lot easier for us to go through and debug it, and maybe come up with a solution. – Harshith Rai Mar 07 '19 at 05:12
  • Picture has been removed and I entered it in. Sorry, created an account just to post this. – webbern Mar 07 '19 at 05:14
  • no probs.. Buddy, isLower and isUpper can only CHECK if the character is upper or lower case. Doesn't convert it to that case. – Harshith Rai Mar 07 '19 at 05:15
  • To convert to upper, use `toUpper` and for lowercase, use `toLower`. – Harshith Rai Mar 07 '19 at 05:16
  • `cin >> answer[max];` will read exactly one character because `answer[max]` is exactly one character, the first character. In C++ you have to do things in order. For example, `int max = strlen(answer);` will provide an answer based on what is in that string at that time. Since the string was initialized one line earlier and contains an empty string, `max` will be 0. – user4581301 Mar 07 '19 at 05:25

2 Answers2

0

islower(char) is just a built in function to check if the char is in lowercase or not. Same goes with isupper. It does not change the case of the character.

In order to convert to lowercase/uppercase, use tolower/toupper. This would return the character in the converted case. But, it is important that you need to assign the returned value to the character itself.

Refer to this answer for some more clarity related to islower, isupper, tolower and toupper.

  • And now coming to the point why it's printing just the 1st character: As @user4581301 has mentioned in his comment,

"cin >> answer[max]; will read exactly one character because answer[max] is exactly one character, the first character. In C++ you have to do things in order. For example, int max = strlen(answer); will provide an answer based on what is in that string at that time. Since the string was initialized one line earlier and contains an empty string, max will be 0."

Hence your cin should be cin >> answer. BUT, this will accept the 1st word of your sentence. In order to accept all the words including the spaces, use getline() instead. And for using this, answer should be declared as string answer instead of a char array.

This is how you accept a full sentence: getline(cin,answer);

  • And your variable max will give an error in a few compilers as being ambiguous. This is because of the using namespace std;. to avoid this, rename max to something else, like maxlen.
  • And finding the length of answer: It would be better if you call answer.length() after accepting the string from user rather than doing it globally.

Your working code should look something like this:

#include <iostream>
#include <string>
#include <cstring>
using namespace std;

string answer;
int maxlen;

void reverse() {
    for (int i = 0; i < maxlen; i++) {
        if (islower(answer[i])) {
            answer[i] = toupper(answer[i]);
        }
        else if (isupper(answer[i])) {
            answer[i] = tolower(answer[i]);
        }
        else if (isspace(answer[i])) {
            answer[i]=' '; 
        }
    }
    cout << "Reversed string: " + answer << endl;
}

void lower() {
    for (int i = 0; i < maxlen; i++) {
        if (isupper(answer[i])) {
            answer[i] = tolower(answer[i]);
        }
        else {
            answer[i] = answer[i];
        }
    }
    cout << "Lower case string: " + answer << endl;
}

void upper() {
    for (int i = 0; i < maxlen; i++) {
        if (islower(answer[i])) {
            answer[i] = toupper(answer[i]);
        }
        else {
            answer[i] = answer[i];
        }
    }
    cout << "Upper case string: " + answer << endl;
}

int main() {

    cout << "Please enter a word, or a series of words: " << endl;
    getline(cin,answer);
    cout << "Original string: " + answer << endl;
    maxlen = answer.length();
    reverse();
    lower();
    upper();
    return 0;
}

With the output:

Please enter a word, or a series of words:
ReVeRsAl UPPER aNd lower
Original string: ReVeRsAl UPPER aNd lower
Reversed string: rEvErSaL upper AnD LOWER
Lower case string: reversal upper and lower
Upper case string: REVERSAL UPPER AND LOWER
Harshith Rai
  • 3,018
  • 7
  • 22
  • 35
0
cin >> answer[max];

will read exactly one character because answer[max] is exactly one character, the character in the array at position max.

max is 0 because you have to do things in order. For example,

int max = strlen(answer);

will provide the length of answer at that time this line is reached. Since the string was initialized one line earlier

char answer[255] = "";

and contains an empty string, max will be 0. This means answer[max] is answer[0] Nothing in the code ever changes max, so it will remain 0.

OK, say we change things a little and rather than reading into a single character, we read into answer as a string. You will need to

cin.getline(answer, sizeof(answer));

because

cin >> answer; 

will read one whitespace-delimited token. One word. Your stated goal is to read more than one word. istream::getline will read everything it finds into the first parameter up to the end of the line or it finds the number of characters specified in the second parameter minus 1 (in order to reserve space for the string's null terminator). sizeof(answer) is literally the size of the answer array in bytes. We're operating in byte-sized characters so the count of characters and number of bytes are the same. Extra care must be taken if multibyte characters are being used.

This seems like a good place to recommend using std::string and std::getline instead. They make a large number of problems, such as the maximum number of characters that can be read, vanish for the vast majority of cases.

I'm not going to use them here, though because the assignment likely has a "No strings" policy.

So now that we have cin.getline(answer, sizeof(answer)); reading the user's input we can work on getting the size for max. We could strlen, but we could also use istream::gcount to get the number of characters read by getline.

main now looks something like

int main() {

    cout << "Please enter a word, or a series of words: " << endl;
    cin.getline(answer, sizeof(answer));
    max = cin.gcount();

    reverse();
    lower();
    upper();

    system("pause");
    return 0;
}

Whole bunch of stuff can go wrong at this point.

using namespace std; can wreak havoc on the max because of possible collisions with std::max. In general, avoid using namespace std; The few letters it saves you from typing often are recovered by the time wasted debugging the weird errors it can introduce.

isupper(answer[i]); doesn't do anything useful as others have noted in the comments. You want

answer[i] = toupper(static_cast<unsigned char>(answer[i])); 

See Do I need to cast to unsigned char before calling toupper(), tolower(), et al.? for why that insane-and-pointless-looking cast may be necessary. Thank you HolyBlackCat for bringing that to my attention.

Self assignments like

answer[i] = answer[i];

are pointless for reasons that should be obvious once you stop and think about it.

Likewise

else if (isspace(answer[i])) {
    isspace(answer[i]);
 }

May not be particularly useful. If answer[i] is a space, set it to a space? It's already a space. What it would do is replace other forms of whitespace, tabs and carriage returns, with a space. Newline has already been picked off by getline. Also probably needs a cast similar to the one used in the toupper example above. I'm still reading up on that.

As hinted at above,

cout << answer[max];

is not effective. It prints out one character, and if max has been fixed, answer[max] will be the terminating null. Instead print out the whole array.

cout << answer;

General suggestions:

Don't write much code at a time. Write a few lines, a function at the most, before compiling and testing. If you had tested

int main() {

    cout << "Please enter a word, or a series of words: " << endl;
    cin >> answer[max];
    cout << answer;
}

You would have immediately seen data was not being read correctly. and fixed it before proceeding. By allowing errors to build up, you make it harder to find any one bug. You may correctly fix a bug only to find the fix undone or concealed by another bug.

Avoid using global variables. Try to place variables in the smallest possible scope. In this case, move answer and max into main and pass them to the other functions as parameters. This makes it a lot easier to keep track of who set what variable and when. It also helps prevent accidental Variable Shadowing.

user4581301
  • 33,082
  • 7
  • 33
  • 54
  • You need a cast in `answer[i] = toupper(answer[i]);` like so: `answer[i] = toupper((unsigned char)answer[i]);`, otherwise you get UB on negative `char`s. Same for `isupper` and other similar functions. – HolyBlackCat Mar 07 '19 at 06:17
  • Come to think of it, would that not also apply to `isupper`? I think I need to do a bit of reading. – user4581301 Mar 07 '19 at 06:24