简体   繁体   中英

How to handle whitespace while using getline() in C++?

My program (reward system that deals with customers/items) involves getting input from the user multiple times. The usual case is that the user has to either enter a number, or type in a string. I use the standard std::cin to handle any numbers the user inputs, and std::getline() for any string they enter. My problem is that when I include a space before / after inputting a string (such as a customer's name or an item's name) it doesn't read it properly. EX: inputting the item name 'water pipe' or customer name 'John' with no spaces before or after works, but something like 'water pipe ' or ' John' with a space afterwards/beforehand ends the program. Is there any way to have std::getline() ignore white spaces before/after the user inputs a string? I noticed this problem first in my addPoints() function so I will include that here, but this is happening in my other functions also. The contents of both of the files are structured the same, with item/customer name then their points beneath them. So like this:

lighter
10
water pipe
10

And so on. Here is the code:

std::cout << "Would you like to add points to an existing member? If not, input 0 to look at other options!" << std::endl;
    std::cout<< "Otherwise, input 1 to continue to the point system." << std::endl;
    std::cin >> answer;
    std::cin.sync();
    if (answer == '0')
        options();
    if (answer == '1') {
        inFS.open("name.dat");
        if (!inFS.is_open()){
            std::cout << "Could not find name.dat." << std::endl;
            exit(1);
        }
        while (std::getline(inFS, item)) {
            std::getline(inFS, points);
            nameList.push_back(make_pair(item, std::stoi(points))); 
        }
        if (!inFS.eof()) 
            std::cout << "Failure before reaching end of file." << std::endl;
        inFS.close();
        std::cout << "Please enter the username of the rewards member you would like to add points to." << std::endl;
        std::getline(std::cin, userName);
        std::cin.sync();
        for (int i = 0; i < nameList.size(); i++) {
            if (nameList[i].first == userName) {
                    validName = true;
                    break; //fix this later so it includes a 'sorry, invalid name' type of comment//
            }
            if (nameList[i].first !=  userName) {
                    validName = false;
                    continue;
            }
        }
        if (validName == false)
            nameList.clear();
        if (validName == true) {
            std::cout << "Which rewards product did " << userName << " purchase?" << std::endl;
            std::getline(std::cin, product);
            //find out why adding a space at the end of each input ends the program//
            std::cin.sync();
            inFS.open("items.dat");
            if (!inFS.is_open()){
                std::cout << "Could not find items.dat." << std::endl;
                exit(1);
            }
            while (std::getline(inFS, item)) {
                std::getline(inFS, points);
                itemList.push_back(make_pair(item, std::stoi(points))); 
            }
            if (!inFS.eof()) 
                std::cout << "Failure before reaching end of file." << std::endl;
            inFS.close();

I haven't read your program too closely, but std::getline always reads up to (and then subsequently discards) a newline character '\n' . Instead, try trimming the strings after the call to std::getline . Unfortunately, there's no built in functions for trimming whitespace, but the following functions work (copy-pasted from https://stackoverflow.com/a/217605/8421788 ):

#include <algorithm> 
#include <functional> 
#include <cctype>
#include <locale>

// trim from start (in place)
static inline void ltrim(std::string &s) {
    s.erase(s.begin(), std::find_if(s.begin(), s.end(),
            std::not1(std::ptr_fun<int, int>(std::isspace))));
}

// trim from end (in place)
static inline void rtrim(std::string &s) {
    s.erase(std::find_if(s.rbegin(), s.rend(),
            std::not1(std::ptr_fun<int, int>(std::isspace))).base(), s.end());
}

// trim from both ends (in place)
static inline void trim(std::string &s) {
    ltrim(s);
    rtrim(s);
}

Then, you can use them in the following way:

std::getline(std::cin, userName);
userName = trim(userName);
/* ... process user name as needed ... */

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM