在 C++ 中从标准输入解析字段

Posted

技术标签:

【中文标题】在 C++ 中从标准输入解析字段【英文标题】:Parsing fields from stdin in C++ 【发布时间】:2016-11-01 02:21:24 【问题描述】:

如果我有stdin 输入如下:

2014-01-23,  AA, 20
2014-05-30,  BB,2    //notice that I might have optional space
2015-03-24, CC,   5
//...
//... and so on 

如何用 C++ 编写一个程序来有效地解析 monthyear 以及后续字段?我真的被这个解析问题困住了。

我想对后续字段执行的操作将AA, 20 存储为地图。所以map[AA]=20等等。

我可以自己做。但我不知道如何阅读和解析它。 请帮忙。


尝试:

int year, month;
int  num;
string key;
map<string, int> mapping;
string s;
getline(cin,s, '-'); 
year=stoi(s); 
getline(cin,s, '-');
month=stoi(s); 
getline(cin,s, ',');
//reading the AA, BB, CC field;
getline(cin,s, ',');
for (int i=0; i<s.size(); i++);
   if (s[i]==' ') s.erase(i,1);
key=s;
//now, reading the number field following AA,BB, CC
getline(cin,s,'\n');
for (int i=0; i<s.size(); i++);
   if (s[i]==' ') s.erase(i,1);
num=stoi(s);
mapping[key]=num;

【问题讨论】:

你需要一步一步来。首先,编写一个程序,读取每一行文本,一次一行。第二步:将每一行文本解析为单独的字段。第三步:将第一个字段解析为它的组成部分,年、月和日。问题解决了。看看这有多容易? 是的,这很容易。但是我的代码有点长。 有一句古老的 Vulcan 谚语:代码越长,越有可能出现错误。 只是需要帮助才能弄清楚 【参考方案1】:

另一种选择是使用std::regex(如果您使用的是“古老”编译器,则使用Boost.Regex

匹配这条线

(\d4)\-(\d2)\-(\d2),\s*(.+),\s*(.+)

然后分别从匹配组\1、\2、\3、\4、\5中获取年、月、日、第一个字段、第二个字段

【讨论】:

如果我有非常大量的数据(很多行要读取),您认为这种方法仍然有效吗? 视情况而定。唯一知道的方法是对其进行基准测试。编译后的正则表达式可以重复使用,因此具有相当好的性能,并且可以像固定解析器那样轻松更改 这可能是一个愚蠢的问题。如何将\d4)-(\d2)-(\d2),\s*(.+),\s*(.+) 与正则表达式一起使用? learn about regex 先使用regex_search or regex_match 就像例子中一样【参考方案2】:

here 使用std::basic_string::find 给出了类似问题的答案。您可以使用-, 作为分隔符。

【讨论】:

【参考方案3】:

试试这个:

#include <bits/stdc++.h>
using namespace std;

int main()
    string s;
    char c;
    int x;
    cin >> s >> c >> x;
    s = s.substr(0,s.length() - 2);
    cout << s << " " << c << " " << x << endl;
    return 0;

【讨论】:

Why should I not #include <bits/stdc++.h>? 和 Why is “using namespace std;” considered bad practice? 感谢您的指出。这个答案是几年前的,我的知识非常有限

以上是关于在 C++ 中从标准输入解析字段的主要内容,如果未能解决你的问题,请参考以下文章

为啥在 C++ 中从标准输入读取行比 Python 慢得多?

为啥在 C++ 20 中从标准库容器中删除了比较运算符?

标准输入 C++

C++ 标准输入的行加速

C/C++编程笔记:C++中的标准输入流 & 标准输出流

c++中scanf和cout有啥区别