为什么 getline() 不读取行中的最后一个 int 值?
Why does getline() not read the last int value in the line?
我有一个包含书籍列表的文件。每本书有 4 个变量,用制表符分隔。
变量是
- 标题
- 作者
- isbn
- 数量
大约有 400 本书条目。
我已经设法编写了一个函数,将每个输入读取到一个数组并将其保存到一本书中 object。
void loadFile() {
std::ifstream inputFile("books");
std::string bookArray[4];
std::string line;
Book book;
while (getline(inputFile, line)) {
size_t field2 = 0;
size_t field1 = line.find("\t");
for (int i = 0; i <= 3; i++) {
size_t field1 = line.find("\t" , field2);
if (field1 != std::string::npos) {
std::string str2 = line.substr(field2, field1 - field2);
bookArray[i] = str2;
}
field2 = field1 + 1;
}
book.setTitle(bookArray[0]);
book.setAuthor(bookArray[1]);
book.setIsbn(bookArray[2]);
book.setQty(stoi(bookArray[3]));
std::cout << "Book: " <<book.getTitle <<'\t'<< book.getQty<< " records.\n";
}
但该函数似乎无法获取每行末尾的数量。除了数量之外,其他一切似乎都很好。我找不到函数有什么问题。
我试过使用'\t'定界符参数实现相同的getline()
函数,如下所示:
while(getline(input, line, '\t')) {
输出只读了第一行的标题就停在那里。我知道第一个功能有效。
为什么它不获取 qty 值?
书籍文件格式如下:
A First Look at Graph Theory Clark John; Holton Derek Allan 9788170234630 5
A Practical Approach To Data Structures And Algorithms Sanjay Pahuja 9788122420678 7
A Practical Approach to High-Performance Computing Sergei Kurgalin; Sergei Borzunov 9783030275587 6
A Practical Guide to UNIX for Mac OS X Users Mark G. Sobell; Peter Seebach 9780321629982 5
A River Marc Martin 9781452162256 4
这里是菜鸟,如果我的代码很笨拙,我深表歉意。
原因是在数量之后的行尾(可能)没有制表符。因此,当您第 4 次调用 line.find("\t", field2)
时,它 returns string::npos
并且您不会在 bookArray[3]
中存储任何内容
最好的解决办法可能是用 if:
放一个 else
} else {
std::string str2 = line.substr(field2, std::string::npos);
bookArray[i] = str2;
break; // there can be no more fields on the line
请注意,如果一行中的字段少于 4 个,bookArray
中未找到字段的元素将不会被触及(因此将继续具有上一行的值)
解释了为什么您的代码无法解析 qty
值。
作为替代解决方案,我建议使用 std::istringstream
来解析每个 line
和 std::getline()
,让它为您处理搜索和拆分 1 ,例如:
void loadFile() {
std::ifstream inputFile("books");
std::string bookArray[4];
std::string line;
Book book;
while (std::getline(inputFile, line)) {
std::istringstream iss(line);
for(int i = 0; i < 4; ++i) {
std::getline(iss, bookArray[i], '\t');
}
book.setTitle(bookArray[0]);
book.setAuthor(bookArray[1]);
book.setIsbn(bookArray[2]);
book.setQty(stoi(bookArray[3]));
std::cout << "Book: " << book.getTitle << '\t' << book.getQty << " records.\n";
}
}
1: 当然还有 many different ways 来标记分隔符上的字符串。
或者,让 istringstream
为您处理 qty
到 int
的转换,无需手动调用 std::stoi()
:
void loadFile() {
std::ifstream inputFile("books");
std::string bookArray[3];
int qty;
std::string line;
Book book;
while (std::getline(inputFile, line)) {
std::istringstream iss(line);
for(int i = 0; i < 3; ++i) {
std::getline(iss, bookArray[i], '\t');
}
iss >> qty;
book.setTitle(bookArray[0]);
book.setAuthor(bookArray[1]);
book.setIsbn(bookArray[2]);
book.setQty(qty);
std::cout << "Book: " << book.getTitle << '\t' << book.getQty << " records.\n";
}
}
我有一个包含书籍列表的文件。每本书有 4 个变量,用制表符分隔。
变量是
- 标题
- 作者
- isbn
- 数量
大约有 400 本书条目。
我已经设法编写了一个函数,将每个输入读取到一个数组并将其保存到一本书中 object。
void loadFile() {
std::ifstream inputFile("books");
std::string bookArray[4];
std::string line;
Book book;
while (getline(inputFile, line)) {
size_t field2 = 0;
size_t field1 = line.find("\t");
for (int i = 0; i <= 3; i++) {
size_t field1 = line.find("\t" , field2);
if (field1 != std::string::npos) {
std::string str2 = line.substr(field2, field1 - field2);
bookArray[i] = str2;
}
field2 = field1 + 1;
}
book.setTitle(bookArray[0]);
book.setAuthor(bookArray[1]);
book.setIsbn(bookArray[2]);
book.setQty(stoi(bookArray[3]));
std::cout << "Book: " <<book.getTitle <<'\t'<< book.getQty<< " records.\n";
}
但该函数似乎无法获取每行末尾的数量。除了数量之外,其他一切似乎都很好。我找不到函数有什么问题。
我试过使用'\t'定界符参数实现相同的getline()
函数,如下所示:
while(getline(input, line, '\t')) {
输出只读了第一行的标题就停在那里。我知道第一个功能有效。
为什么它不获取 qty 值?
书籍文件格式如下:
A First Look at Graph Theory Clark John; Holton Derek Allan 9788170234630 5
A Practical Approach To Data Structures And Algorithms Sanjay Pahuja 9788122420678 7
A Practical Approach to High-Performance Computing Sergei Kurgalin; Sergei Borzunov 9783030275587 6
A Practical Guide to UNIX for Mac OS X Users Mark G. Sobell; Peter Seebach 9780321629982 5
A River Marc Martin 9781452162256 4
这里是菜鸟,如果我的代码很笨拙,我深表歉意。
原因是在数量之后的行尾(可能)没有制表符。因此,当您第 4 次调用 line.find("\t", field2)
时,它 returns string::npos
并且您不会在 bookArray[3]
最好的解决办法可能是用 if:
放一个else
} else {
std::string str2 = line.substr(field2, std::string::npos);
bookArray[i] = str2;
break; // there can be no more fields on the line
请注意,如果一行中的字段少于 4 个,bookArray
中未找到字段的元素将不会被触及(因此将继续具有上一行的值)
qty
值。
作为替代解决方案,我建议使用 std::istringstream
来解析每个 line
和 std::getline()
,让它为您处理搜索和拆分 1 ,例如:
void loadFile() {
std::ifstream inputFile("books");
std::string bookArray[4];
std::string line;
Book book;
while (std::getline(inputFile, line)) {
std::istringstream iss(line);
for(int i = 0; i < 4; ++i) {
std::getline(iss, bookArray[i], '\t');
}
book.setTitle(bookArray[0]);
book.setAuthor(bookArray[1]);
book.setIsbn(bookArray[2]);
book.setQty(stoi(bookArray[3]));
std::cout << "Book: " << book.getTitle << '\t' << book.getQty << " records.\n";
}
}
1: 当然还有 many different ways 来标记分隔符上的字符串。
或者,让 istringstream
为您处理 qty
到 int
的转换,无需手动调用 std::stoi()
:
void loadFile() {
std::ifstream inputFile("books");
std::string bookArray[3];
int qty;
std::string line;
Book book;
while (std::getline(inputFile, line)) {
std::istringstream iss(line);
for(int i = 0; i < 3; ++i) {
std::getline(iss, bookArray[i], '\t');
}
iss >> qty;
book.setTitle(bookArray[0]);
book.setAuthor(bookArray[1]);
book.setIsbn(bookArray[2]);
book.setQty(qty);
std::cout << "Book: " << book.getTitle << '\t' << book.getQty << " records.\n";
}
}