My string test will only accept one word but I need to be able handle multiple words

Viewed 64
#include <iostream>
#include <stdio.h>
#include <string>

using std::cout;
using std::endl;
using std::cin;

int main() {
    int i, all_alpha;
    char ch, str[100];
    {
        cout << "Enter a word/s: ";
        cin.getline(str,sizeof(str));
    }

    while (1) {
        all_alpha = 1;
        for (i = 0; str[i]; ++i) {
            ch = str[i];
            if (ch >= 'a' && ch <= 'z') { //if the string is inbetween a and z
                ch = ch - 'a' + 'A';
            } else if (ch < 'A' || ch > 'z') {
                all_alpha = 0;
            }
            str[i] = ch;
        }

        if (all_alpha) {
            cout << str << endl;
            break;
        } else {
            cout << "Sorry, that is a wrong input\n";
            cout << "Enter a word/s: ";
            cin.getline(str,sizeof(str));
        }   
    }
    return 0;
}

my output:

Enter a word: Hello Hello
Sorry, that is a wrong input
Enter a word: 

How can the user input multiple words and have the program output them all in uppercase?

2 Answers

Well in a nutshell... your input contains spaces. Spaces arent "alpha". It also contains the end of string character which if i recall correctly is \0 which also fails your "isAlpha" check.

Then there's your for loop. Going from 0 to the value of the character in the array on index i is... Not moving it at all... You might want to go from index 0 to the last array item... Either using sizeof of the array or hardcoded by the array size.. or evem better... Using the strlen function from the standard string library!

Then there's other issues...

  1. Make your all_apha a boolean instead of an integer... Or at least compare it properly with all_alpha == 1.
  2. Nice of you to assume that the sizeof of an array will give you the length of the array... It gives you the size in bytes, and sure... ASCII chars are 1 byte long in the correct conditions. But if you want to do it properly, divide the size of the array with the size of the array type for future references.

As others have mentioned in the comments, when you test an element of the string to see if it is a letter, any space character you have in your input will cause that test to fail (for the whole string).

For a quick fix, just allow spaces to pass that test; so, change:

    } else if (ch < 'A' || ch > 'z') {

to:

    } else if ((ch < 'A' || ch > 'z') && ch != ' ') { // Allow spaces.

However, if you want to learn to use C++ to its full potential, you can improve your code in a number of ways:

  1. Use the std::string STL type instead of an old-fashioned, "C-Style" character array.
  2. Use the standard character-checking/modifying functions like islower and toupper, rather than relying on manual checks that a character is in a range.1
  3. Learn the power of range-based for loops with references to elements
  4. Try to avoid infinite loops with break statements, if possible – they can make code harder to read and debug.

Here's a version of your code on which I have applied the above techniques:

#include <iostream>
#include <string>
#include <cctype> // For "islower()", "toupper()", "isspace()" and "isalpha()"

using std::cout;
using std::endl;
using std::cin;

int main()
{
    std::string str;
    cout << "Enter a word/s: ";
    std::getline(cin, str);

    bool all_alpha = false; // The "bool" type is best suited for yes/no type data
    while (!all_alpha) {    // No need for a "break" if we test this each time.
        all_alpha = true; // Set this to "true", each loop, until we find otherwise
        for (auto& ch: str) { // Use a reference to each character in the string
            if (std::islower(ch)) {
                ch = static_cast<char>(std::toupper(ch)); // toupper returns an int
            }
            else if (!std::isalpha(ch) && !std::isspace(ch)) {
                all_alpha = false;
            }
        }
        if (!all_alpha) {
            cout << "Sorry, that is a wrong input\n";
            cout << "Enter a word/s: ";
            std::getline(cin, str);
        }
    }
    cout << str << endl; // Only need to show the conversion when the loop is done.
    return 0;
}

Sorry if I have been too much of a 'schoolmaster' in my answer, and please feel free to ask for any further clarification or explanation of the points I've raised.


1 Note that your tests for lowercase and uppercase letters, and your conversion from lower to upper, assume ASCII character encoding. Now, although that system is hugely predominant on modern computer systems/compilers, there is no strict requirement in the C++ Standard for it to be used. A platform using EBCDIC encoding, for example, will need very different checking/converting algorithms. (But using the in-built routines will cover that.)

Related