user2848183
user2848183

Reputation: 31

C++ stringstream parsing

I am trying to read valid a user input from command prompt:

for example, valid user input is in following format:

getData <>

<> - any string type value

on Command Prompt:

e.g getData name => Correct (only one parameter entered after getData as expected) e.g getData name ID => InCorrect (more than one parameter entered after getData) e.g getData => InCorrect (due to no parameter entered after getData)

How do I check for number of parameters? my code logic is as follow:

string cmd_input;

getline(cin, cmd_input)

stringstream ss(cmd_input);

string input;
string parameter;

 ss >> input; //getData
 ss >> parameter; //name

How do I go about valid/invalid checking? I don't want to run it through loop till EOF stream and count the number of parameter. I read up on peek() and not sure how it fits here. Also, I don't want to use vectors to store parameter.

Thanks!

Upvotes: 1

Views: 13222

Answers (4)

LihO
LihO

Reputation: 42085

With the constraint of not using loops and not even std::vector, it could look the following way:

std::string line, command, arg1, arg2, arg3;

if (std::getline(std::cin, line)) {

    std::istringstream is(line);
    if (is >> command) {
        std::string word;
        if (is >> arg1) {
            ...
            if (is >> arg2) {
                ...
                if (is >> arg3) {
                     ...
                }
            }
        }
    } // end of is >> command
}

Yet if you change your mind and decide to use std::vector, it could look like this:

std::string line, command;
std::vector<std::string> arguments;

if (std::getline(std::cin, line)) {

    std::istringstream is(line);
    if (is >> command) {
        std::string word;
        while (is >> word)
            arguments.push_back(word);
    }
}

Upvotes: 1

Dietmar K&#252;hl
Dietmar K&#252;hl

Reputation: 153792

Here is a simple test program reading commands. If the command is getData one argument is extracted and, if this is successful, any trailing whitespace is skipped. At this point the stream parsing the line is expected to have reached its end, i.e., eof() needs to be set:

#include <iostream>
#include <sstream>
#include <string>

int main()
{
    for (std::string line; std::getline(std::cin, line); ) {
        std::istringstream in(line);
        std::string command, name;
        if (in >> command) {
            if (command == "getData" && in >> name && (in >> std::ws).eof()) {
                std::cout << "getData: read one argument: '" << name << '\n';
            }
            else {
                std::cout << "wrong format on line '" << line << "'\n";
            }
        }
    }
}

Upvotes: 0

clcto
clcto

Reputation: 9648

ss >> input;
if( ss.eof() )
    //no parameter code
else
{
    ss >> param;
    if( !ss.eof() )
         // too many param code
    else
         // good input
}

Upvotes: 0

jxh
jxh

Reputation: 70372

You can check the state of the stream itself after you retrieve input. If the retrieval succeeded, it will be true. You want it to return true after two retrievals, but be false on the third.

if (!(ss >> input1) || input1 != "getData") { //... error : unexpected cmd
}
if (!(ss >> input2)) { //... error: no param
}
if (ss >> input3) { //... error: too many params
}
//... okay

Upvotes: 1

Related Questions