读取文件并将其内容存储到 2-D 数组C++中

Reading a file and storing its contents into a 2-D Array C++

本文关键字:2-D 数组 C++ 存储 文件 读取      更新时间:2023-10-16

我一直在尝试创建一个函数,该函数读取名为"test.txt"的文件并将其内容存储到二维数组中以用于其他函数。

它似乎正在从文本文件中读取某些内容,但它只在测试.txt数字应该在的区域重复"-9.25996e+61"。

任何帮助将不胜感激,谢谢。

"test.txt"文件包含以下 12 个元素。它们在文档中垂直对齐:

70
80
90
75
85
90
60
80
80
90
80
75

我的代码是:

#include <iostream>
#include <fstream>
using namespace std;
//S is the # of students and T is the number of test scores per student
const int S = 3;
const int T = 4;
void getTests(double[][T]);
int main()
{
double testScores[S][T];
getTests(testScores);
}
//*******************
//Gets test scores
void getTests(double testScores[S][T])
{
ifstream testFile("test.txt");
double score;
for (int student = 0; student < S; student++)
{
cout << "Student " << student + 1 << endl;
for (int test = 0; test < T; test++)
{
testFile >> score;
cout << "Test " << test + 1 << endl;
cout << score << endl;
}
}
}

上面的代码输出:

Student 1
Test 1
9.25596e+61
Test 2
9.25596e+61
Test 3
9.25596e+61
Test 4
9.25596e+61
Student 2
Test 1
9.25596e+61
Test 2
9.25596e+61
Test 3
9.25596e+61
Test 4
9.25596e+61
Student 3
Test 1
9.25596e+61
Test 2
9.25596e+61
Test 3
9.25596e+61
Test 4
9.25596e+61

输出表明您尝试使用ifstream testFile("test.txt");打开文件失败。您永远不会验证文件是否已打开,并且无法验证每次读取,因此您无法知道文件从未打开过。

处理输入时,必须验证每个操作。您可以通过验证流状态 std::basic_ios 提供成员函数来执行此操作,允许您通过成员函数.good(), .eof(), .fail() & .bad()检查流状态。应在尝试打开文件后立即验证流状态。使用.good()显式执行,或通过验证每次尝试从文件中读取是否成功来隐式执行。

在您的情况下,您可以执行以下操作:

/* read test scores from file 'fname' */
void getTests(double testScores[][T], std::string fname)
{
std::ifstream testFile (fname); /* open file */
double score;
if (!testFile.good()) { /* validate file is open for reading */
std::cerr << "error: file open failed - " << fname << 'n';
return;
}

(注意:不要在代码中硬编码文件名,尤其是不要埋在函数中。将文件名作为参数传递,或者更好的是,在调用方中打开文件,并在验证调用方中的打开成功后将打开的文件流作为参数传递。如果文件无法成功打开,则无需进行函数调用...

从文件中读取分数时,必须验证每次读取。您可以通过使用读取本身的结果控制读取循环来做到这一点。getTests()函数的简单其余部分可以是:

for (int student = 0; testFile.good() && student < S; student++) {
int test = 0;
std::cout << "Student " << student + 1 << 'n';
while (test < T && testFile >> score) { /* validate EVERY input */
testScores[student][test] = score;  /* store value in array */
std::cout << "Test " << ++test << 'n' << score << 'n';
}
}
}

上面的读取循环以test < TtestFile >> score为条件。如果读取score失败,循环将退出。同样,由于您使用嵌套循环来读取一定数量的学生,因此外部循环只会递增,而testFile.good()保持不变。

总而言之,您的简短示例将是:

#include <iostream>
#include <fstream>
#include <string>
const int S = 3;    /* number of students */
const int T = 4;    /* number of scores per-student */
void getTests(double[][T], std::string fname);  /* pass filename as parameter */
int main (int argc, char **argv) {
double testScores[S][T];
std::string filename = argc > 1 ? argv[1] : "test.txt";
getTests (testScores, filename);
}
/* read test scores from file 'fname' */
void getTests(double testScores[][T], std::string fname)
{
std::ifstream testFile (fname); /* open file */
double score;
if (!testFile.good()) { /* validate file is open for reading */
std::cerr << "error: file open failed - " << fname << 'n';
return;
}
for (int student = 0; testFile.good() && student < S; student++) {
int test = 0;
std::cout << "Student " << student + 1 << 'n';
while (test < T && testFile >> score) { /* validate EVERY input */
testScores[student][test] = score;  /* store value in array */
std::cout << "Test " << ++test << 'n' << score << 'n';
}
}
}

(注意:程序期望文件名作为程序的第一个st参数读取。如果未提供参数,则默认情况下,程序将尝试从test.txt读取。另请注意:您通常希望避免在代码中包含整个namespace std。这取决于你,但通常不受欢迎。

示例输入文件

$ cat dat/test12elements.txt
70
80
90
75
85
90
60
80
80
90
80
75

示例使用/输出

$ ./bin/studentscores dat/test12elements.txt
Student 1
Test 1
70
Test 2
80
Test 3
90
Test 4
75
Student 2
Test 1
85
Test 2
90
Test 3
60
Test 4
80
Student 3
Test 1
80
Test 2
90
Test 3
80
Test 4
75

仔细查看,如果您有其他问题,请告诉我。此外,与其将分数存储在普通的旧数组中double,不如考虑使用 std::array 或 std::vector。您甚至可以创建一个简短的结构或std::unordered_set,以允许您存储学生姓名以及测试分数的数组或向量。