重载运算符>>() 表示未知的输入长度/结构
Overloading operator>>() for unknown length/structure of input
我正在尝试读取包含个人信息的文件。每行包含一个人的数据,假设它看起来像这样:
First(s) Last ID SSN
Peter Barker 1234 5678
James Herbert Bond 007 999
Barack Hussein Obama 2007 14165
所以我想用std::copy
来读取每一行,并将其复制到(std::vector<Person>
(中,如下所示:
struct Person
{
std::string firstName_s;
std::string lastName;
int ID;
int SSD;
}
我认为为此重载提取运算符会很方便:
std::istringstream& operator>>(std::istringstream& in, struct Person& person)
{
struct Person tmp;
in >> tmp.firstName_s
>> tmp.lastName
>> tmp.ID
>> tmp.SSN;
person = std::move(tmp);
return in;
}
但是,我遇到的问题是我不知道这个人会有多少个名字。
我想过将全名读成一个字符串,直到我遇到一个数字,他们将姓氏与包含名字的字符串分开,这工作正常,但看起来很"丑陋"。 如果有人有更好的建议,或者我可以查看的链接,那就太好了,我似乎无法自己找到一些东西! 谢谢。
更改文件,因此此答案不再适用。工作正在进行中。
这里有两大策略
我们可以选择:
- 让用户为我们设置数据格式。
- 让程序格式化数据。
然后我们解析它。
1(固定数据格式:
最简单的解决方案。
让用户以易于解析的格式输入数据。在这里,由用户正确输入数据,程序将检查输入的数据是否正确。这可以通过多种方式完成,包括但不完全:
Peter-Richmond Barker 1234 5678 // hyphen(-) separated
"James Herbert" Bond 007 999 // enclosed in quotes("")
Barack_Hussein Obama 2007 14165 // underscore(_) separated
在第一种和第三种情况下,std::cin >> person.first_names
就足够了。
在第二种情况下,您必须
std::getline(std::cin, person.first_names, '"'); // any character delimiter
它,在用std::cin.get() == '"'
检查打开分隔符后。
2(缓慢而稳定
另一个非常简单的解决方案。只需让用户一次输入一件事:
std::cout << "Enter some datum 1: ";
std::cin >> person.some_datum_1;
...
(与流行的想象相反,数据是单数的,数据是复数的(。
对于多个输入,请参阅行标记化:
让我在这里抓住一种方法:
std::cout << "Enter some data 1: ";
// Grab the line and put into a stream
std::getline(std::cin, line);
std::stringstream line_buffer(line);
// Prepare to iterate over the stream
std::istream_iterator<std::string> it(line_buffer);
std::istream_iterator<std::string> end;
// Set the name with a move assignment operator
person.first_names = std::move(std::vector<std::string>(it, end));
...
请注意,此方法需要person.first_names
是std::vector<std::string>
。
3(从最后开始
在这里,我们首先输入未确定的大小数据。
警告:它仅适用于单个未确定大小的输入。如果名字和姓氏都可以超过两个,这将不起作用。我提到它只是为了完整。
如果您不想强迫用户这样做并破坏他们的体验,则必须自己解析输入。用好的旧std::getline(std::cin, line);
输入整行。
初始化int read_from = std::string::npos;
。
现在,用read_from = line.rfind(' ', read_from);
找到最后一个空格。read_from == std::string::npos
会告诉您所有输入都已解析,或者存在错误。
line.substr(read_from)
将获取最后一个输入。将其转换为适当的类型并存储。您还必须使用line.resize(read_from);
擦除解析的输入
冲洗并重复其他输入。
注意:建议将未确定的数据存储在适当类型的
std::vector
中。
4(字节进行曲
我知道你会说我们没有解决OP的问题,
。读取包含个人信息的文件...
现在我们已经讨论了从用户那里获取输入,我们还可以选择如何存储它(并获取它(。
最简单的方法是:
personal_data_file.write((char*)&person_list[i], sizeof(Person)); // Write it...
personal_data_file.read((char*)&person_list[i], sizeof(Person)); // ...Now read it.
在循环中,其中person_list
是Person
s 的std::vector
。
注意:请记住以
std::ios::binary
模式打开文件!
优雅!
但以防万一您不熟悉上面示例中使用的类和某些功能。以下是一些链接:
标准::获取线https://www.geeksforgeeks.org/how-to-use-getline-in-c-when-there-are-black-lines-in-input/
std::istream::readhttp://www.cplusplus.com/reference/istream/istream/read/
std::ostream::writehttp://www.cplusplus.com/reference/ostream/ostream/write/
标准::矢量https://www.geeksforgeeks.org/vector-in-cpp-stl/
标准::istream_iterator
如果你有一个可变长度的行(就字数而言(,你可以简单地读取整行并从右侧处理它,或者缓存所有单词并使用偏移量。下面的示例执行后一个示例。
int to_int(std::string_view str)
{
int val = 0;
std::from_chars(str.data(), str.data() + str.size(), val);
return val;
}
std::istream& operator>>(std::istream& in, Person& person)
{
std::string line;
// read whole line
if (std::getline(in, line))
{
// split line into words
std::vector<std::string> words;
std::stringstream tmp_stream(line);
for (std::string word; tmp_stream >> word; )
words.push_back(word);
// join first names
tmp_stream.str(words[0]);
for (std::size_t i = 1; i < words.size() - 3; i++)
tmp_stream << ' ' << words[i];
person.firstName_s = tmp_stream.str();
person.lastName = words[words.size() - 3];
person.ID = to_int(words[words.size() - 2]);
person.SSN = to_int(words[words.size() - 1]);
}
return in;
}
我认为代码是不言自明的。这是一个完整的示例。
- 在C++程序中输入的文本文件将不起作用,除非文本被复制和粘贴
- 2D数组来自文本输入,中间有空格
- 如何使用 < 和 > 命令获取 c++ 中的输入和输出?
- 检查输入是否不是整数或数字
- 正在尝试了解输入验证循环
- 读取文件并输入到矢量中
- C++如何通过用户输入删除列表元素
- 用c++从输入文件中读取另一行
- 读取文件的最后一行并输入到链接列表时出错
- 创建一个函数以在输入为负数或零时输出字符串.第一次执行用户定义的函数
- 如何使用用户输入在C++中正确填充2D数组
- C++MySQL C api用户输入行
- 输入到文件并输出到另一个文件,并将流文件传递给函数
- 用户定义函数中的指针和输入
- 如何在C++中检查2D数组中负值的输入验证
- 如何只允许用户输入正整数
- 在while循环中输入带有std::cin的字符串后,控制台会输出大量胡言乱语
- 输入中的字符串数未知(以字母表示)
- cpp二进制搜索问题,计算给定数组中输入元素的出现次数
- 在一个模板函数中,若输入的类型是enum类,我该如何使用std::underlying_type