逐字读取文本文件中的每一行并转换为 int(无限循环或崩溃?



我正在尝试读取此文本文件:

8 4 4 6 1
8 4 4 6 2
8 4 4 6 3
8 4 4 6 4
8 4 4 6 5
8 4 4 6 6
8 4 4 6 7
8 4 4 6 8
11 4 4 6 3
15 11 13
7 2 1 4 4 
9 4 3 9 9
8 2 1 5 4 
10 1 2 3 4 6 1
6 1 1 2 5 3 2
13 1 1 2 10 3 8 
11 2 11 10 7

并完全按照控制台显示的方式打印它(以确保我得到了每个输入(。

但是,由于某种原因,我的代码在读取第一行后崩溃。我什至无法终止调试器。

这是我的代码:

while(getline(inFile, buffer)){
buffer2 = strdup(buffer.c_str());
line = strtok(buffer2, " ");
size = atoi(line);
cout << size << " ";
while(line!=NULL){
line = strtok(NULL, " ");
cout << line << " ";
}
cout << "~~~~~~~~~" << endl;
}

如果你打算使用C++你应该利用它,使用字符串流:

#include <fstream>
#include <sstream>
#include <iostream>

using namespace std; //for sample purposes, should not be used
int main() {
int temp, count = 0, sum = 0, total = 0;
string buffer;
ifstream myFile("in.txt");
if (!myFile.is_open())
cout << "No file" << endl;
else{
while(getline(myFile, buffer)){
sum = 0;
stringstream ss(buffer);
while(ss >> temp){
count++;         //number count            
sum += temp;     //line sum
cout << temp << " ";
}
total += sum;   //total sum
cout << endl << "count: " << count <<  endl
<< "sum: " << sum << endl << "total: " << total << endl << endl;
}
myFile.close();
}
cout << "~~~~~~~~~" << endl;  
}

您正在泄漏strdup()分配的内存。 使用完buffer2后,您需要调用free()

但更重要的是,当没有更多代币要返回时,strtok()会返回NULL。 但是将NULLchar*指针传递给operator<<未定义的行为。 您的while循环在到达每行末尾时正是这样做的,因此任何事情都可能发生,包括崩溃。

试试这个:

while (getline(inFile, buffer)) {
buffer2 = strdup(buffer.c_str());
if (buffer2 != NULL) {
line = strtok(buffer2, " ");
while (line != NULL) {
size = atoi(line);
cout << size << " ";
line = strtok(NULL, " ");
}
free(buffer2);
}
cout << "~~~~~~~~~" << endl;
}

话虽如此,你为什么要使用strdup()strtok()atoi()? 您正在编写C++代码,您应该C++语义而不是 C 语义。 例如,您可以改用std::istringstream,例如:

while (getline(inFile, buffer)) {
istringstream iss(buffer);
while (iss >> size) {
cout << size << " ";
}
cout << "~~~~~~~~~" << endl;
}

与往常一样,有许多可能的解决方案。我想再展示一个。这是使用更现代的C++元素,主要来自算法和迭代器库。

那么,我们该怎么办?

首先,我们将每一行读取为带有std::getline的简单 for 循环中的std::string。然后我们将再次将行放在std::istringstream中,以便我们可以利用C++迭代器:std::istream_iterator.

此迭代器将遍历字符串中的元素并提取所有整数。这就像为行字符串中的所有元素调用提取器运算符(>>(。

我们在所谓的 os astd::vector的范围构造函数中使用迭代器。这个就地创建的向量将被添加到目的地数据中。因此,结果,我们将得到 int 向量的向量:一个二维向量。

出于调试目的,我们将每一行 intes 复制到std::cout.

请注意,我们确实只需要很少且非常简单的语句即可完成任务。

请检查。

#include <iostream>
#include <string>
#include <algorithm>
#include <sstream>
#include <vector>
#include <iterator>
std::istringstream sourceFile{R"(8 4 4 6 1
8 4 4 6 2
8 4 4 6 3
8 4 4 6 4
8 4 4 6 5
8 4 4 6 6
8 4 4 6 7
8 4 4 6 8
11 4 4 6 3
15 11 13
7 2 1 4 4 
9 4 3 9 9
8 2 1 5 4 
10 1 2 3 4 6 1
6 1 1 2 5 3 2
13 1 1 2 10 3 8 
11 2 11 10 7)"};
int main()
{
// Here we will store the resulting int values
std::vector<std::vector<int>> data{};
for (std::string line{}; std::getline(sourceFile, line); ) {
// Split the line into integers and add to target array
std::istringstream iss(line);
data.emplace_back(std::vector<int>(std::istream_iterator<int>(iss), {}));
}       
// Now all data is in our vector of vector of int
// Show read data on screen
std::for_each(data.begin(), data.end(), [](const std::vector<int>& v){ 
std::copy(v.begin(), v.end(), std::ostream_iterator<int>(std::cout, " ")); std::cout << "n";});
return 0;
}

请注意。我没有关于 SO 的文件。所以我使用std::istringstream作为输入流。您当然可以将其与任何其他std::ftream交换

最新更新