从C++中的txt文件中读取数字行
Read rows of numbers from txt file in C++
大家早上好,
我有一项学校作业,我希望你能帮我完成这一项。
该程序的目标非常简单。计算数字的总和
在文件的每一行上,并在屏幕上以递减顺序显示 N 个最高的不同结果,其中 N 是每个结果的出现次数,N 作为参数由用户提供(默认值 = 3)。
因此,正如标题所说,我在 C++ 中工作,我的程序必须从提供的 txt 文件中读取数字行(双)。我已经知道 ifsream 类型的概念,并设法打开文件。我知道我可以使用 >> 运算符从文件中读取,但是每行的双精度数不固定,所以我不能做一个简单的循环。这是我目前的样子:
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
using namespace std;
int main(){
int nbresult=3;
string filename;
double tmp;
cin >> filename;
cin >> nbresult;
ifstream file;
file.open(filename.c_str());
if(file.is_open())
{
cout << "Opening file: " << filename << endl;
while(file.eof() == false)
{
vector<double> nbres;
file >> tmp;
nbres.push_back(tmp);
}
fichier.close();
}
else
{
cout << "Erreur à l'ouverture !" << endl;
}
return 0;
}
所以我的想法是将数字放入向量中并求和,但我意识到我需要为每一行创建一个向量实例。另外,我的阅读方法不允许我创建多个向量,因为它在阅读时没有意识到数字在不同的行中这一事实。
你能指导我找到有效的解决方案吗?我真的开始放松了哈哈。
提前致谢!
马特
如果我理解你的问题,如果你仍然被卡住,这个过程的概述将简单地填充一个 vector
与顶部 n
总和(默认值:3)从每个计算文件中的值行。您希望值按降序排列。
每当您需要从文件中的一行中获取未知数量的值时(无论这些值是否由逗号或空格等分隔),您的方法应该是读取整行数据进入 string
,从该行创建一个 stringsteam
,然后从 stringstream
循环输入值,直到在 stringstream
.[=39 上遇到 EOF
=]
为什么 stringstream
而不是直接从文件中读取值? (答案:线控)。由于 cin
丢弃前导空格,而 '\n'
(换行符)是空格,因此无法确定您何时到达直接从文件读取的行尾。通过先读取该行然后创建 stringstream
,您可以简单地读取直到到达您创建的 stringstream
的末尾 - 并且您已在一行中输入所有值。
您在整个代码中唯一需要维护的 vector
是按降序排列的总和向量。从您创建的 stringstream
中读取每个值时,您可以简单地使用一个临时向量来将每个值存储在给定行中,然后在临时向量上调用 accumulate
以提供总和
挑战在于在程序结束时保持最终结果向量中的前 X 个总和输出。那里的方法实际上相当简单。如果sum是第一个sum,直接用push_back()
存储即可。对于所有后续总和,使用迭代器遍历向量,将已存储的内容与当前总和进行比较,直到总和大于向量的元素,然后调用 .insert()
方法将当前总和插入结果中迭代器引用的元素之前的向量。
完成后,只需使用自动范围 for
循环输出结果向量。
有很多不同的方法可以实现它,但坚持上面的方法,你可以做如下的事情。注释代码以帮助您完成它:
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
#include <numeric> /* for accumulate */
int main (int argc, char **argv) {
if (argc < 2) { /* validate at least filename given */
std::cerr << "error: insufficient arguments\n"
"usage: " << argv[0] << " filename (nresults: 3)\n";
return 1;
}
std::string filename = argv[1], /* string for filename */
line; /* string to hold line */
std::vector<int> results; /* vector of results */
std::ifstream f; /* input file stream */
size_t nresults = 3, n = 0; /* num of results, countner */
if (argc >= 3) /* if addition arg given, set nresults */
nresults = std::stoi(argv[2]);
f.open (filename); /* open filename */
if (! f.is_open()) { /* validate file open for reading */
perror (("error file open failed " + filename).c_str());
return 1;
}
while (std::getline (f, line)) { /* read each row of values */
int val, sum; /* current value, line sum */
std::vector<int> v; /* vector to hold values */
std::stringstream s (line); /* create stringstream from line */
while ((s >> val)) /* read each value */
v.push_back (val); /* add it to vector v */
sum = accumulate (v.begin(), v.end(), 0); /* sum values in v */
if (results.empty()) /* if empty */
results.push_back (sum); /* just add */
else /* otherwise insert in decreasing order */
for (auto it = results.begin(); it != results.end(); it++)
if (sum > *it) {
results.insert (it, sum);
break;
}
if (results.size() > nresults) /* trim excess elements */
results.pop_back();
n++; /* increment line count */
}
/* output results */
std::cout << nresults << " greatest sums from " << n << " lines in " <<
filename << '\n';
for (auto& p : results)
std::cout << " " << p;
std::cout << '\n';
}
(注意: 代码将文件名作为第一个参数,然后采用可选参数报告最高总和数——使用默认值 3
)
示例输入文件
以下输入只是通过在 0 - 999
:
之间写入包含 5 个随机值的 50 行而生成的
$ cat dat/50x5.txt
106 114 604 482 340
815 510 690 228 291
250 341 774 224 545
174 546 537 278 71
706 139 767 320 948
328 683 410 401 123
140 507 238 744 990
810 559 732 732 20
24 982 361 30 439
139 204 217 676 714
288 615 853 287 935
801 847 851 211 249
206 583 756 676 328
978 486 119 711 219
139 967 433 733 997
872 104 433 89 12
147 609 627 0 897
795 34 744 878 477
225 84 61 982 761
621 960 479 740 903
930 112 870 364 77
99 468 181 532 790
193 911 399 53 912
296 80 178 273 958
887 498 274 180 712
267 801 905 747 774
40 677 118 911 273
195 242 974 376 775
764 801 686 163 854
830 692 166 240 197
124 128 927 399 540
640 898 342 777 645
348 817 555 466 960
60 661 203 34 269
978 798 302 896 194
389 959 886 555 199
83 680 559 10 311
100 882 209 442 659
87 22 709 874 488
669 934 381 104 969
650 314 999 952 211
193 341 170 79 129
601 394 809 161 637
352 261 519 793 935
411 112 957 352 986
677 21 153 58 358
122 708 672 353 892
883 547 466 285 858
595 887 253 636 48
122 220 541 641 245
如果要验证总和,可以使用简短的 awk
脚本[1].
例子Use/Output
$ ./bin/vector_n_greatest dat/50x5.txt
3 greatest sums from 50 lines in dat/50x5.txt
3703 3494 3302
$ ./bin/vector_n_greatest dat/50x5.txt 4
4 greatest sums from 50 lines in dat/50x5.txt
3703 3494 3302 3269
$ ./bin/vector_n_greatest dat/50x5.txt 10
10 greatest sums from 50 lines in dat/50x5.txt
3703 3494 3302 3269 3268 3168 3146 3126 3057 3039
检查一下,如果您还有其他问题,请告诉我。
脚注:
(1.) 输出排序后的行总和以供验证,您可以使用简短的 awk
脚本和 sort
,例如
awk '{
sum = 0
for (i=1; i<=NF; i++)
sum += $i
printf "%-20s (%4d)\n", [=13=], sum
}' file | sort -r -b -k6.2
示例文件的 awk
输出将显示:
$ awk '{
> sum = 0
> for (i=1; i<=NF; i++)
> sum += $i
> printf "%-20s (%4d)\n", [=14=], sum
> }' dat/50x5.txt | sort -r -b -k6.2
621 960 479 740 903 (3703)
267 801 905 747 774 (3494)
640 898 342 777 645 (3302)
139 967 433 733 997 (3269)
764 801 686 163 854 (3268)
978 798 302 896 194 (3168)
348 817 555 466 960 (3146)
650 314 999 952 211 (3126)
669 934 381 104 969 (3057)
883 547 466 285 858 (3039)
389 959 886 555 199 (2988)
...
大家早上好,
我有一项学校作业,我希望你能帮我完成这一项。 该程序的目标非常简单。计算数字的总和 在文件的每一行上,并在屏幕上以递减顺序显示 N 个最高的不同结果,其中 N 是每个结果的出现次数,N 作为参数由用户提供(默认值 = 3)。 因此,正如标题所说,我在 C++ 中工作,我的程序必须从提供的 txt 文件中读取数字行(双)。我已经知道 ifsream 类型的概念,并设法打开文件。我知道我可以使用 >> 运算符从文件中读取,但是每行的双精度数不固定,所以我不能做一个简单的循环。这是我目前的样子:
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
using namespace std;
int main(){
int nbresult=3;
string filename;
double tmp;
cin >> filename;
cin >> nbresult;
ifstream file;
file.open(filename.c_str());
if(file.is_open())
{
cout << "Opening file: " << filename << endl;
while(file.eof() == false)
{
vector<double> nbres;
file >> tmp;
nbres.push_back(tmp);
}
fichier.close();
}
else
{
cout << "Erreur à l'ouverture !" << endl;
}
return 0;
}
所以我的想法是将数字放入向量中并求和,但我意识到我需要为每一行创建一个向量实例。另外,我的阅读方法不允许我创建多个向量,因为它在阅读时没有意识到数字在不同的行中这一事实。
你能指导我找到有效的解决方案吗?我真的开始放松了哈哈。
提前致谢! 马特
如果我理解你的问题,如果你仍然被卡住,这个过程的概述将简单地填充一个 vector
与顶部 n
总和(默认值:3)从每个计算文件中的值行。您希望值按降序排列。
每当您需要从文件中的一行中获取未知数量的值时(无论这些值是否由逗号或空格等分隔),您的方法应该是读取整行数据进入 string
,从该行创建一个 stringsteam
,然后从 stringstream
循环输入值,直到在 stringstream
.[=39 上遇到 EOF
=]
为什么 stringstream
而不是直接从文件中读取值? (答案:线控)。由于 cin
丢弃前导空格,而 '\n'
(换行符)是空格,因此无法确定您何时到达直接从文件读取的行尾。通过先读取该行然后创建 stringstream
,您可以简单地读取直到到达您创建的 stringstream
的末尾 - 并且您已在一行中输入所有值。
您在整个代码中唯一需要维护的 vector
是按降序排列的总和向量。从您创建的 stringstream
中读取每个值时,您可以简单地使用一个临时向量来将每个值存储在给定行中,然后在临时向量上调用 accumulate
以提供总和
挑战在于在程序结束时保持最终结果向量中的前 X 个总和输出。那里的方法实际上相当简单。如果sum是第一个sum,直接用push_back()
存储即可。对于所有后续总和,使用迭代器遍历向量,将已存储的内容与当前总和进行比较,直到总和大于向量的元素,然后调用 .insert()
方法将当前总和插入结果中迭代器引用的元素之前的向量。
完成后,只需使用自动范围 for
循环输出结果向量。
有很多不同的方法可以实现它,但坚持上面的方法,你可以做如下的事情。注释代码以帮助您完成它:
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
#include <numeric> /* for accumulate */
int main (int argc, char **argv) {
if (argc < 2) { /* validate at least filename given */
std::cerr << "error: insufficient arguments\n"
"usage: " << argv[0] << " filename (nresults: 3)\n";
return 1;
}
std::string filename = argv[1], /* string for filename */
line; /* string to hold line */
std::vector<int> results; /* vector of results */
std::ifstream f; /* input file stream */
size_t nresults = 3, n = 0; /* num of results, countner */
if (argc >= 3) /* if addition arg given, set nresults */
nresults = std::stoi(argv[2]);
f.open (filename); /* open filename */
if (! f.is_open()) { /* validate file open for reading */
perror (("error file open failed " + filename).c_str());
return 1;
}
while (std::getline (f, line)) { /* read each row of values */
int val, sum; /* current value, line sum */
std::vector<int> v; /* vector to hold values */
std::stringstream s (line); /* create stringstream from line */
while ((s >> val)) /* read each value */
v.push_back (val); /* add it to vector v */
sum = accumulate (v.begin(), v.end(), 0); /* sum values in v */
if (results.empty()) /* if empty */
results.push_back (sum); /* just add */
else /* otherwise insert in decreasing order */
for (auto it = results.begin(); it != results.end(); it++)
if (sum > *it) {
results.insert (it, sum);
break;
}
if (results.size() > nresults) /* trim excess elements */
results.pop_back();
n++; /* increment line count */
}
/* output results */
std::cout << nresults << " greatest sums from " << n << " lines in " <<
filename << '\n';
for (auto& p : results)
std::cout << " " << p;
std::cout << '\n';
}
(注意: 代码将文件名作为第一个参数,然后采用可选参数报告最高总和数——使用默认值 3
)
示例输入文件
以下输入只是通过在 0 - 999
:
$ cat dat/50x5.txt
106 114 604 482 340
815 510 690 228 291
250 341 774 224 545
174 546 537 278 71
706 139 767 320 948
328 683 410 401 123
140 507 238 744 990
810 559 732 732 20
24 982 361 30 439
139 204 217 676 714
288 615 853 287 935
801 847 851 211 249
206 583 756 676 328
978 486 119 711 219
139 967 433 733 997
872 104 433 89 12
147 609 627 0 897
795 34 744 878 477
225 84 61 982 761
621 960 479 740 903
930 112 870 364 77
99 468 181 532 790
193 911 399 53 912
296 80 178 273 958
887 498 274 180 712
267 801 905 747 774
40 677 118 911 273
195 242 974 376 775
764 801 686 163 854
830 692 166 240 197
124 128 927 399 540
640 898 342 777 645
348 817 555 466 960
60 661 203 34 269
978 798 302 896 194
389 959 886 555 199
83 680 559 10 311
100 882 209 442 659
87 22 709 874 488
669 934 381 104 969
650 314 999 952 211
193 341 170 79 129
601 394 809 161 637
352 261 519 793 935
411 112 957 352 986
677 21 153 58 358
122 708 672 353 892
883 547 466 285 858
595 887 253 636 48
122 220 541 641 245
如果要验证总和,可以使用简短的 awk
脚本[1].
例子Use/Output
$ ./bin/vector_n_greatest dat/50x5.txt
3 greatest sums from 50 lines in dat/50x5.txt
3703 3494 3302
$ ./bin/vector_n_greatest dat/50x5.txt 4
4 greatest sums from 50 lines in dat/50x5.txt
3703 3494 3302 3269
$ ./bin/vector_n_greatest dat/50x5.txt 10
10 greatest sums from 50 lines in dat/50x5.txt
3703 3494 3302 3269 3268 3168 3146 3126 3057 3039
检查一下,如果您还有其他问题,请告诉我。
脚注:
(1.) 输出排序后的行总和以供验证,您可以使用简短的 awk
脚本和 sort
,例如
awk '{
sum = 0
for (i=1; i<=NF; i++)
sum += $i
printf "%-20s (%4d)\n", [=13=], sum
}' file | sort -r -b -k6.2
示例文件的 awk
输出将显示:
$ awk '{
> sum = 0
> for (i=1; i<=NF; i++)
> sum += $i
> printf "%-20s (%4d)\n", [=14=], sum
> }' dat/50x5.txt | sort -r -b -k6.2
621 960 479 740 903 (3703)
267 801 905 747 774 (3494)
640 898 342 777 645 (3302)
139 967 433 733 997 (3269)
764 801 686 163 854 (3268)
978 798 302 896 194 (3168)
348 817 555 466 960 (3146)
650 314 999 952 211 (3126)
669 934 381 104 969 (3057)
883 547 466 285 858 (3039)
389 959 886 555 199 (2988)
...