将 cin 中的 getline 读入 stringstream (C++)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/35974402/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 14:34:19  来源:igfitidea点击:

Reading getline from cin into a stringstream (C++)

c++cingetlinestringstreamostream

提问by user5482356

So I'm trying to read input like this from the standard input (using cin):

所以我试图从标准输入中读取这样的输入(使用cin):

Adam English 85
Charlie Math 76
Erica History 82
Richard Science 90

Adam English 85
Charlie Math 76
Erica History 82
Richard Science 90

My goal is to eventually store each data piece in its own cell in a data structure I have created, so basically I want to parse the input so each piece of data is individual. Since each row of input is inputted by the user one at a time, each time I get an entire row of input that I need to parse. Currently I am trying something like this:

我的目标是最终将每个数据段存储在我创建的数据结构中的自己的单元格中,所以基本上我想解析输入,以便每个数据段都是独立的。由于每行输入都是由用户一次输入一个,因此每次我都会得到一整行需要解析的输入。目前我正在尝试这样的事情:

stringstream ss;
getline(cin, ss);

string name;
string course;
string grade;
ss >> name >> course >> grade;

The error I am having is that XCode is telling me there's no matching function call to getlinewhich is confusing me. I have included the stringlibrary, so I'm guessing the error has to do with using getlineto read in from cinto a stringstream? Any help here would be appreciated.

我遇到的错误是 XCode 告诉我没有匹配的函数调用让getline我感到困惑。我已经包括string图书馆,所以我猜的错误与使用做getline从在读cinstringstream?任何帮助在这里将不胜感激。

回答by Ziezi

You are almost there, the error is most probably1caused because you are trying to call getlinewith second parameter stringstream, just make a slight modification and store the data within the std::cinin a stringfirst and then used it to initialize a stringstream, from which you can extract the input:

您快到了,错误很可能是1引起的,因为您尝试getline使用第二个参数进行调用stringstream,只需稍作修改并将数据存储std::cin在 a 中string,然后用它来初始化 a stringstream,您可以从中提取输入:

// read input
string input;
getline(cin, input);

// initialize string stream
stringstream ss(input);

// extract input
string name;
string course;
string grade;

ss >> name >> course >> grade;


1. Assuming you have included:

1. 假设您已包括:

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

using namespace std;

回答by Dúthomhas

You cannot std::getline()a std::stringstream; only a std::string. Read as a string, then use a stringstream to parse it.

你不能std::getline()一个std::stringstream; 只有一个std::string. 读取为字符串,然后使用字符串流对其进行解析。

struct Student
{
  string   name;
  string   course;
  unsigned grade;
};

vector <Student> students;
string s;
while (getline( cin, s ))
{
  istringstream ss(s);
  Student student;
  if (ss >> student.name >> student.course >> student.grade)
    students.emplace_back( student );
}

Hope this helps.

希望这可以帮助。

回答by Weak to Enuma Elish

You can just use cin >> name >> course >> grade;because >>will read until whitespace anyway.

您可以使用cin >> name >> course >> grade;因为>>无论如何都会读取到空格。

回答by solstice333

Either you don't have a using namespace stdin your code or you're not fully qualifying calls made to the API's in the std namespace with an std::prefix, for example, std::getline(). The solution below parses CSV instead to tokenize values that have whitespace in them. The logic for stdin extraction, parsing the CSV, and converting grade from string to int are all separated. The regex_token_iterator usage is probably the most complicated part, but it uses pretty simple regex for the most part.

要么您using namespace std的代码中没有 a ,要么您没有完全限定对 std 命名空间中带有std::前缀的 API 的调用,例如,std::getline(). 下面的解决方案改为解析 CSV 以标记其中包含空格的值。提取标准输入、解析CSV、将等级从字符串转换为整数的逻辑都是分开的。regex_token_iterator 的使用可能是最复杂的部分,但它大部分使用了非常简单的正则表达式。

// foo.txt:

// Adam,English,85
// Charlie,Math,76
// Erica,History,82
// Richard,Science,90
// John,Foo Science,89

// after compiling to a.exe, run with:
// $ ./a.exe < foo.txt 

// output
// name: Adam, course: English, grade: 85
// name: Charlie, course: Math, grade: 76
// name: Erica, course: History, grade: 82
// name: Richard, course: Science, grade: 90
// name: John, course: Foo Science, grade: 89

#include <iostream>
#include <sstream>
#include <regex>
#include <vector>

using namespace std;

typedef unsigned int uint;

uint stoui(const string &v) {
   uint i;
   stringstream ss;
   ss << v;
   ss >> i;
   return i;
}

string strip(const string &s) {
   regex strip_pat("^\s*(.*?)\s*$");
   return regex_replace(s, strip_pat, "");
}

vector<string> parse_csv(string &line) {
   vector<string> values;
   regex csv_pat(",");
   regex_token_iterator<string::iterator> end;
   regex_token_iterator<string::iterator> itr(
      line.begin(), line.end(), csv_pat, -1);
   while (itr != end)
      values.push_back(strip(*itr++));
   return values;
}

struct Student {
   string name;
   string course;
   uint grade;
   Student(vector<string> &data) : 
      name(data[0]), course(data[1]), grade(stoui(data[2])) {}
   void dump_info() {
      cout << "name: " << name << 
      ", course: " << course << 
      ", grade: " << grade << endl;
   }
};

int main() {
   string line;
   while (getline(cin, line)) {
      if (!line.empty()) {
         auto csv = parse_csv(line);
         Student s(csv);
         s.dump_info();
      }
   }
}