除非您不能使用来自 STL 的容器,例如 std::vector,否则您将通过使用它们变得更容易,更不容易出错。在这里,虽然您可以读取第一个值 N,但当您使用 std::vector 进行存储时,则不需要它。 STL 容器会自动处理所需的存储空间,因此您真正关心的是从文件中读取实际数据值,然后使用 .push_back() 成员函数将值添加到向量中。
不要在您的代码中硬编码文件名。这就是 int main (int argc, char **argv) 的参数的用途(或者您可以将文件名作为输入)。例如你可以这样做:
int main (int argc, char **argv) {
int N, tmp; /* int N and temporary int to use filling vector */
std::vector<int> v; /* vector of int */
if (argc < 2) { /* valdate 1 argument given for filename */
std::cerr << "usage: " << argv[0] << " filename\n";
return 1;
}
std::ifstream f (argv[1]); /* open file */
if (!f.good()) { /* validate file open */
std::cerr << "error: file open failed.\n";
return 1;
}
无需硬编码您的文件名,只需将其作为参数传递给main()。
打开文件后,以最简单的形式,您可以简单地使用重载的>> 流运算符从文件中读取值。您必须验证每次读取以确保杂散的非数字字符确实会导致匹配失败并在输入流上设置失败的流状态。例如要检查N 的读取是否良好(这里不错),您可以这样做:
if (!(f >> N)) { /* read/validate N */
std::cerr << "error: invalid integer input - N.\n";
return 1;
}
由于意图是退出,除非读取良好,因此使用了!(f >> N) 表单。 (这也降低了您在代码中构建的缩进级别)。你可以这样做:
if (f >> N) { /* read/validate N */
/* rest of your code goes here on good read */
}
验证是相同的,但是在第一种情况下,我们在读取 N 失败时退出,在第二种情况下,我们只是不进入包含其余代码的块(现在又移动了一个右边的缩进层...)
读取其余值并填充向量只需以相同方式读取临时值tmp,然后在确认读取良好后,您只需使用 @987654336 将值添加到向量中@成员函数,例如
while (f >> tmp) /* read remaining int values into vector v */
v.push_back(tmp);
(注意: 读取所有数值 空格 被忽略。这意味着文件中是否还有 1 行或 1000 行整数值 - 全部将被读入您的向量。所有'\n' 都将被忽略,因为'\n' 是空白。如果您只需要读取一行)
读取第一个N 仅有助于与向量的.size() 进行比较,您现在可以使用它来确认您已将N 值读入向量中,例如
if (v.size() != (size_t)N) { /* valdate .size() == N */
std::cerr << "error: number read does not equal N.\n";
return 1;
}
您可以对向量v 中的值做任何您想做的事情。在这里,它们只是使用 基于范围的 for 循环输出,并将 tmp 重新用作计数器以输出索引:
tmp = 0;
for (auto& n : v) /* loop over all values in v outputting */
std::cout << "v[" << tmp++ << "] : " << n << '\n';
总而言之,你可以这样做:
#include <iostream>
#include <fstream>
#include <vector>
int main (int argc, char **argv) {
int N, tmp; /* int N and temporary int to use filling vector */
std::vector<int> v; /* vector of int */
if (argc < 2) { /* valdate 1 argument given for filename */
std::cerr << "usage: " << argv[0] << " filename\n";
return 1;
}
std::ifstream f (argv[1]); /* open file */
if (!f.good()) { /* validate file open */
std::cerr << "error: file open failed.\n";
return 1;
}
if (!(f >> N)) { /* read/validate N */
std::cerr << "error: invalid integer input - N.\n";
return 1;
}
while (f >> tmp) /* read remaining int values into vector v */
v.push_back(tmp);
if (v.size() != (size_t)N) { /* valdate .size() == N */
std::cerr << "error: number read does not equal N.\n";
return 1;
}
tmp = 0;
for (auto& n : v) /* loop over all values in v outputting */
std::cout << "v[" << tmp++ << "] : " << n << '\n';
}
使用/输出示例
使用文件dat/nint.txt 中的数据,您将使用以下程序生成以下输出:
$ ./bin/readnint dat/nint.txt
v[0] : 4
v[1] : 7
v[2] : 9
v[3] : 2
v[4] : 1
故事的寓意 -- 请勿使用 scanf。对于新的 C/C++ 程序员来说,它充满了陷阱,并且它的不当使用会在本网站上产生如此多的问题,这无异于 programming-malpractice 提出scanf 解决方案。如果您还有其他问题,请仔细查看并告诉我。