1

In my program, I'm asking the user for input via getline, and then in a separate class, splitting the string into three different strings which I will then check via a list of pre-determined values.

The way it works now, if someone enters an invalid command, I display "INVALID"

The problem I'm having is with a string containing only spaces or only a single newline character.

Here is what I'm trying to do:

std::string command; // command user enters
getline(std::cin, command); // user input here

std::string tempCheck; // if we have a value in here other than empty, invalid
// use istringstream to grab the words, max of 3
std::istringstream parse{fullCommand}; // parse command into words

if(fullCommand.empty()){ // nothing has been input
    std::cout << "INVALID" << std::endl;
    return;
}

parse >> command; // stores first word (the command)
parse >> actionOne; // stores second word as parameter
parse >> actionTwo; // stores third word as parameter
parse >> tempCheck;

if(!tempCheck.empty()) {
    std::cout << "INVALID" << std::endl;
    return;
}

The variable tempCheck basically means that if it goes over three words (the limit I want for commands), then it is INVALID. I also thought that having an empty string would work, but it just ends up in an infinite loop when nothing is input, but I just hit enter.

Here is what I expect my input to be doing (bold is output):

CREATE username password
**CREATED**
      LOGIN          username password
**SUCCEEDED**
ASDF lol lol
**INVALID**

**INVALID**
REMOVE username
**REMOVED**

**INVALID**
QUIT
**GOODBYE**

Here is what is happening:

CREATE username password
**CREATED**
 // newline entered here

And it goes into a seemingly infinite loop. I can still type things, however, they don't actually affect anything. For example typing QUIT does nothing. But, if I restart my program and just type "QUIT" without trying to only use a newline character or only use a space, I get the expected output:

QUIT
**GOODBYE**

So, how do I tell either getline, or my istringstream, that if a user just enters a bunch of spaces and then hits enter, OR if the user just hits enter, display invalid and return? And is there anyway to do this with just getline or istringstream?

Alex
  • 2,145
  • 6
  • 36
  • 72
  • `getline` and `istringstream` are not mutually exclusive as you seem to make them out to be. – chris Nov 27 '14 at 04:41
  • It will be helpful if you can post an [MCVE](http://stackoverflow.com/help/mcve), sample input, and expected output. – R Sahu Nov 27 '14 at 04:47
  • @chris How do I get them to work together correctly then? I just thought getline goes until it hits a newline character, and istringstream stores characters delimited by a space or newline – Alex Nov 27 '14 at 04:47
  • @RSahu I added sample input and expected output, also what happens when I do it. – Alex Nov 27 '14 at 04:52
  • @Alex You can do a check if the string is all white space before processing it. – PaulMcKenzie Nov 27 '14 at 04:57
  • After reading command with getline, try to validate with regex: `if (std::regex_match(command, std::regex(" *"))) std::cout << "INVALID" << std::endl;` – alvmed Nov 27 '14 at 04:58
  • @alvmed sorry, I'm updating the limitations right now, I forgot to add that in. I'm only allowed to use basic functions: cout/cin, getline, istringstream :( – Alex Nov 27 '14 at 04:59
  • @Alex, `std::istringstream` just provides an IO streams interface for strings. `std::getline` works the same way for it as it does for any other stream. – chris Nov 27 '14 at 05:00
  • @PaulMcKenzie how would I do that? – Alex Nov 27 '14 at 05:01
  • @Alex - Use the `find` or `find_if` algorithm functions, looking for a non-space character. If the find returns the end() iterator, the string is all spaces. In other words, I believe you need to do some "hand validation" yourself before you place the string into the istringstream object. – PaulMcKenzie Nov 27 '14 at 05:05
  • @PaulMcKenzie Just checked the instructions and found that I'm not allowed to use "generic algorithms (like std::find)" either. :[ – Alex Nov 27 '14 at 05:07
  • @PaulMcKenzie I'll try validating everything then before I put them in istringstream. That could be why it's failing. Thanks! – Alex Nov 27 '14 at 05:08

1 Answers1

0

Alex, the following code may be helpful:

std::string strip(std::string const& s, std::string const& white=" \t\n")
{
    std::string::size_type const first = s.find_first_not_of(white);
    return (first == std::string::npos)
        ? std::string()
        : s.substr(first, s.find_last_not_of(white)-first+1);
}

You may apply it before creating the istringstream:

std::istringstream parse{strip(fullCommand)};

The above code was borrowed and slightly modified from the old well-known technique.

Simon Woo
  • 474
  • 3
  • 5