这是逻辑:
read first integer from the text file into IntegerOne
if end-of-file on intInput.dat
display error message “Input file exists but has no values”
end program execution
文本文件可能没有任何值,或者可能有多个值。如果没有值,那么我希望它显示错误消息,如果它具有多个值,那么我只想读取第一个值并将该值存储到IntegerOne中。
我了解如果我想读取一个值数组,那么可以执行以下操作:
int main() {
int arr[30];
ifstream is("InputFile.txt");
int cnt = 0;
int x;
while (cnt < arr[30] && is >> x)
{
arr[cnt++] = x;
}
cout << "The integers are:" << "\n";
for (int i = 0; i < cnt; i++) {
cout << arr[i] << ' ';
}
is.close();
}
但是我不确定如何只读取第一个值,我应该将“ arr [30]”更改为“ arr [1]”吗?我很犹豫,因为稍后,我将只需要读取第二个值(并检查它是否存在)。任何意见,将不胜感激!
您正在尝试对您的代码做几件事,这些事情可以轻松地按顺序完成。如评论中所问,不清楚IntegerOne
要读取的值是否与要读取到数组中的其余值是分开的,或者它是否是第一个数组元素。(在第一行上有一个单独的整数,其中包含一个数字,该数字指定后面的值的数量是一种通用格式-我们将假定这是您的意思)
首先,请避免在代码中使用幻数或硬编码文件名。如果需要一个常量来声明数组,则可以使用#define
一个常量或声明一个const int
值。要打开文件名,main()
需要使用参数int main (int argc, char **argv)
(其中argc是参数计数,告诉您参数向量中包含多少个单独的字符串),这些参数使您可以将文件名作为打开的第一个参数传递给程序(或者您可以可以将其作为输入stdin
)。这样,您就可以在一个方便的位置更改数组大小,而无需重新编译程序就可以从另一个文件中读取。
例如,arr
可以通过以下任一方式为数组定义常量:
#include <iostream>
#include <iomanip>
#include <fstream>
#define MAXI 30 /* if you need a constant, #define one, or declare const int */
int main (int argc, char **argv) {
...
int arr[MAXI] = {0}; /* array of MAXI (30) integers */
或者#define
在C ++中代替使用,您可以声明和初始化a const int
,例如
const int MAXI = 30;
在没有背景的情况下,如何将文件中的第一个整数值读取到名为的变量中IntegerOne
?(我认为您打算x
在您的代码中使用)。无论您使用什么名称,方法都是相同的。声明一个变量以保存整数值,打开文件(验证它已打开以供读取),然后将第一个值读取到变量中(验证读取成功),例如
int IntegerOne; /* separate variable for IntegerOne */
...
std::ifstream f (argv[1]); /* open file stream */
if (!f.good()) { /* validate file stream state good */
std::cerr << "error: file open failed.\n";
return 1;
}
if (!(f >> IntegerOne)) { /* read/validate 1st value */
std::cerr << "Input file exists but has no values.\n";
return 1;
}
如果您已经在程序中达到了这一点,则说明您已成功将文件中的第一个值读入IntegerOne
,只需输出该值即可确认:
std::cout << "IntegerOne: " << IntegerOne << '\n'; /* output IntegerOne */
下一个任务是读取最大为数组大小的值。您使用MAXI
上面定义的整数常量(最大整数个数)声明数组:
int arr[MAXI] = {0}; /* array of MAXI (30) integers */
(注意:将POA(普通旧数组)初始化为全零是有用的,以防止在循环中调用未定义行为的元素中意外读取尚未设置值的元素)
为了在验证对数组元素的每次读取时保护数组边界,您可以简单地使用定义的常量和计数器,以防止向数组中写入多余的整数。您可以像IntegerOne
上面一样验证每个读物。将这两个条件放在一起,您可以执行以下操作:
int cnt = 0, /* counter for array values */
...
/* read remaining integers into arr up to MAXI values */
while (cnt < MAXI && f >> arr[cnt])
cnt++;
现在,您已将第一个值读入IntegerOne
数组,并将文件中的所有剩余值读入数组。从现在开始,您可以输出它们或以任何您喜欢的方式使用它们。下面的示例仅输出读取的值或您指定的错误消息(如果提供的文件名不存在,还会输出其他消息)。
完全可以做到:
#include <iostream>
#include <iomanip>
#include <fstream>
#define MAXI 30 /* if you need a constant, #define one, or declare const int */
int main (int argc, char **argv) {
if (argc < 2) { /* validate at least 1 argument for filename */
std::cerr << "usage: " << argv[0] << " filename\n";
return 1;
}
int IntegerOne, /* separate variable for IntegerOne */
cnt = 0, /* counter for array values */
arr[MAXI] = {0}; /* array of MAXI (30) integers */
std::ifstream f (argv[1]); /* open file stream */
if (!f.good()) { /* validate file stream state good */
std::cerr << "error: file open failed.\n";
return 1;
}
if (!(f >> IntegerOne)) { /* read/validate 1st value */
std::cerr << "Input file exists but has no values.\n";
return 1;
}
std::cout << "IntegerOne: " << IntegerOne << '\n'; /* output IntegerOne */
/* read remaining integers into arr up to MAXI values */
while (cnt < MAXI && f >> arr[cnt])
cnt++;
/* output array, 10 values per line */
for (int i = 0; i < cnt; i++) {
if (i && i % 10 == 0)
std::cout << '\n';
std::cout << std::setw(5) << arr[i];
}
if (cnt) /* conditionally output final newline if array values printed */
std::cout << '\n';
}
每当您编写必须满足多个条件的代码时,请测试这些条件以验证您的代码是否按预期工作。
使用/输出示例
不存在的文件:
$ ./bin/read1stvalue+array goldfish
error: file open failed.
空的文件:
$ ./bin/read1stvalue+array dat/empty.txt
Input file exists but has no values.
具有单整数值的文件321
:
$ ./bin/read1stvalue+array dat/oneint.txt
IntegerOne: 321
在文件中第一个值之后具有10个整数的文件,例如
$ cat dat/int_cnt+10_by-5.txt
10
702 344 138 77 294
27 67 978 727 301
读取以上文件,每行输出数组值10:
$ ./bin/read1stvalue+array dat/int_cnt+10_by-5.txt
IntegerOne: 10
702 344 138 77 294 27 67 978 727 301
在文件中第一个值之后具有30个整数值的文件,例如
$ cat dat/int_cnt+30_by-5.txt
30
393 936 97 365 928
257 645 987 221 22
237 853 584 905 819
910 576 730 859 495
13 818 281 908 582
421 156 177 831 646
读取以上文件,每行输出数组值10:
$ ./bin/read1stvalue+array dat/int_cnt+30_by-5.txt
IntegerOne: 30
393 936 97 365 928 257 645 987 221 22
237 853 584 905 819 910 576 730 859 495
13 818 281 908 582 421 156 177 831 646
在文件中第一个值之后具有50个整数的文件,例如
$ cat dat/int_cnt+50_by-5.txt
50
302 697 190 743 391
709 699 824 839 976
817 246 695 833 918
2 712 422 737 326
706 170 394 720 903
798 291 683 682 971
70 216 668 260 960
59 969 891 883 40
867 700 519 795 766
437 29 710 91 767
读取以上文件,每行输出数组值10:
$ ./bin/read1stvalue+array dat/int_cnt+50_by-5.txt
IntegerOne: 50
302 697 190 743 391 709 699 824 839 976
817 246 695 833 918 2 712 422 737 326
706 170 394 720 903 798 291 683 682 971
(请注意,只有前30个值存储在数组中)
使用STL容器而不是普通的旧阵列
尽管知道如何处理普通的旧数组并没有什么错-已有数十年的旧C ++使用它们,但新代码应利用标准模板库提供的容器来提供自动内存管理,并能够添加如果需要,std::vector
可以使用其他元素,等等。可以用来替换任何普通的旧数组。花点时间看一下它的用法,并在std :: vector为每个成员函数提供示例。(它们确实确实使生活更加轻松)
如果您还有其他问题,请告诉我。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句