Friday, April 29, 2011

Need user to input string /check string length (C++)

I'll need to accept a string of 5 numbers from the user (only 5). Should I use

istringstream

for the same ?

Can't I get away with something like this ?

int main()
{
    char *InputMain;
    InputMain=(char *)malloc(5+1);
    cout << "Enter the number : " <<endl;
    cin.getline ( InputMain, 5, '\n' );              // Input goes into InputMain
    cout << "The number entered is : " << InputMain <<endl;
    cin.get();
}

Then comes the next part..

How'd I make sure the user inputs only 5 chars? And maybe if the user enters more than 5 chars, I should display a warning saying only 5 chars allowed..

One more question, since this essentially is a string, I'll need to validate the input to be only numbers by parsing through each char in the string and checking against respective ASCII values (for numerals).. Is that approach the right thing?

From stackoverflow
  • Unfortunately there is no portable way to restrict the number of characters input in C++. But whatever platform you are using will provide some mechanism: for example on Windows, look up Console functions.

    If you do go with plain old C++ iostreams input from cin, it's a good idea to read the initial text into a std::string using istream& getline(istream&, string&) -- this will prevent buffer overflows, because strings resize as necessary. (Your code involving getline(InputMain, 5, '\n') is technically safe in that it won't read more than 5 characters into InputMain, but this code is fragile -- if you later decide you want 6 characters, you could easily forget to update your call to malloc(), leading to crashes. Also, you need to remember to free(InputMain). But as I said, use string instead.)

    Regarding parsing:

    Whether you read the input into a string using getline(cin, str) or some platform-specific code, once it's in there you need to get it out in the form of a number. This is where the istringstream class is useful -- it lets you treat an existing string as a stream to read from, so you can use the formatted input >> operator:

    string str;
    if (!getline(cin, str)) {
        cerr << "Something went seriously wrong...\n";
    }
    
    istringstream iss(str);
    int i;
    iss >> i;    // Extract an integer value from the stream that wraps str
    
    if (!iss) {
        // Extraction failed (or a more serious problem like EOF reached)
        cerr << "Enter a number dammit!\n";
    } else if (i < 1000 || i > 9999) {
        cerr << "Out of range!\n";
    } else {
        // Process i
    }
    

    If you're using C++ iostreams, you can actually just extract directly from cin instead of going via a string and an istringstream:

    int i;
    cin >> i;    // Extract an integer value from cin
    

    However this can have subtle undesirable effects; notably, any additional characters on the line typed by the user (in particular the '\n' typed when they press Enter) will remain in the input buffer to be read by the next << operation. Often this doesn't matter, but sometimes it does: e.g. if you follow up with cin.get();, expecting that this will wait for a keypress, it won't -- it will just read the '\n' (or the first non-digit character the user typed).

    halluc1nati0n : Did you mean I should use something like this ? #include #include using namespace std; int main() { string InputMain; cout << "Enter the number : " << endl; getline(cin, InputMain); // cin >> InputMain; //---> Would this work as well? cout << "The number entered is : " << InputMain << endl; cin.get(); }
    j_random_hacker : @halluc1nati0n: Ah sorry, I've given two alternative approaches rather than a single approach. I'll try to fix the post to clarify things.
    j_random_hacker : @halluc1nati0n: OK, have a look now. In short: no, don't use "cin >> InputMain;" -- either use "int i; cin >> i;" or "string s; getline(cin, s); int i; istringstream iss(s); iss >> i;".
    halluc1nati0n : @ j_random_hacker : I do like the istringstream approach.. I've added the sstream header and the code does compile, but somehow I'm not getting it to work. Any reasons why ?
    j_random_hacker : @halluc1nati0n: Works for me once I add the iostream and sstream headers, add "using namespace std;" below that and wrap the code snippet inside main(). Also you'll obviously need to change the error-handling code (e.g. add in a while loop and break out when the number is valid) if you want the user to reenter the number if it's invalid.
    halluc1nati0n : @ j_random_hacker : Works like a charm.. Thanks for all the help! I know more now :-)
    j_random_hacker : You're welcome :)

0 comments:

Post a Comment