C++ getline 函数缺少 txt 文件的第一行
C++ getline function missing the first line of txt file
我已经编写了一个函数来读取 .txt 文件并构建一个链表,但是该函数错过了文件的第一行。有人知道为什么会这样吗?
输出:
//empty line
gmail
San Francisco
123456
.txt 文件
person1
gmail
San Francisco
123456
读取文件函数
void list::readFile(std::string fileName){
fstream fs;
string dummy = "";
string firstline;
record * previous = new record;
record * temp = new record;
int recordCount = 0;
fs.open(fileName, ios::in | ios::binary);
do{
std::getline(fs, temp->name);
std::getline(fs, temp->email);
std::getline(fs, temp->address);
fs >> temp->phoneNo;
std::getline(fs, dummy);
recordCount++;
if(head == NULL){
head = temp;
previous = temp;
tail = temp;
} else {
previous->next = temp;
previous = temp;
tail = temp;
}
} while(!fs.eof());
// } else {
// cout << "there's no record in the file yet." << endl;
// }
cout << head->name << endl;
cout << head->address <<endl;
cout << head->email << endl;
cout << head->phoneNo << endl;
}
您创建了一个节点,因此循环中的每次迭代都会覆盖之前读取的值。
在 while 循环的第二次迭代中,您对 getline
的第一次调用可能会失败,并将 name
的值设置为空字符串。由于流现在处于失败状态,您的其余读取将被忽略,最后循环在循环结束时中断。
这可能更接近您想要的:
int recordCount = 0;
fs.open(fileName, ios::in | ios::binary);
while(fs) {
record * temp = new record;
std::getline(fs, temp->name);
std::getline(fs, temp->email);
std::getline(fs, temp->address);
fs >> temp->phoneNo;
if (!fs) {
// Reading failed, delete the temporary and exit the loop
delete temp;
break;
}
std::getline(fs, dummy);
recordCount++;
if(head == NULL){
head = temp;
previous = temp;
tail = temp;
} else {
previous->next = temp;
previous = temp;
tail = temp;
}
}
您的代码可以通过使用智能指针来确保 temp
永远不会泄漏,即使抛出异常也不会泄漏。
我将向您解释为什么会出现此问题以及如何避免。
这是一个典型的问题,在评论中提到了数千次,上面也是“molbdnilo”。
您不得使用 while (fs.eof())
。
我会向你解释为什么。顺便说一句,它只会发生,因为你在最后一行的末尾有一个新行。
让我们看看会发生什么:
- 变量“temp”被分配了一个次
- 文件已打开
do
-循环开始
- 您通过 未格式化 输入函数
std::getline
读取姓名、电子邮件、地址。此函数将吃掉尾随的白色 space '\n'(但不会将其处理为读取变量
- 您使用格式化输入函数
>>
来读取 phone 数字(这不是一个好主意。无论如何)。格式化输入函数将在白色 space 处停止,这里是最后一行末尾的 '\n'。它不会消耗'\n'。这仍在流中并等待输入。
- 您将
std::getline
与虚拟对象一起使用,以从流中读取仍然存在的 '\n'。流还是可以的。到目前为止一切顺利。该文件也不在 EOF。我们可以阅读所有内容。所以,很好。
do loop
结束。你说:while(!fs.eof())
。但是如上所述:还没有EOF。一切都很好,现在仍然很好。循环将继续。
- 再次回到循环的开始
std::getline(fs, temp->name);
将被调用。现在而不是以前,我们得到一个 EOF。因为我们试图阅读,现在没有什么可读的了。 “temp->name”将被设置为一个空字符串。现在,输入流处于 EOF 状态。
10 所有进一步的读取都不会执行任何操作,因为流处于 EOF 中。从现在开始,变量将不会被修改。
这就是为什么 name 为空而其他数据仍然存在的原因 运行。
为了快速修复,您可以编写
void list::readFile(std::string fileName) {
fstream fs;
string dummy = "";
string firstline;
record* previous = new record;
record* temp = new record;
int recordCount = 0;
fs.open(fileName, ios::in | ios::binary);
if (fs)
while (std::getline(fs, dummy)) {
temp->name = dummy;
std::getline(fs, temp->email);
std::getline(fs, temp->address);
fs >> temp->phoneNo;
std::getline(fs, dummy);
recordCount++;
if (head == NULL) {
head = temp;
previous = temp;
tail = temp;
}
else {
previous->next = temp;
previous = temp;
tail = temp;
}
}
// } else {
// cout << "there's no record in the file yet." << endl;
// }
cout << head->name << endl;
cout << head->address << endl;
cout << head->email << endl;
cout << head->phoneNo << endl;
}
但这也不好。稍后我会展示更好的解决方案。
我已经编写了一个函数来读取 .txt 文件并构建一个链表,但是该函数错过了文件的第一行。有人知道为什么会这样吗?
输出:
//empty line
gmail
San Francisco
123456
.txt 文件
person1
gmail
San Francisco
123456
读取文件函数
void list::readFile(std::string fileName){
fstream fs;
string dummy = "";
string firstline;
record * previous = new record;
record * temp = new record;
int recordCount = 0;
fs.open(fileName, ios::in | ios::binary);
do{
std::getline(fs, temp->name);
std::getline(fs, temp->email);
std::getline(fs, temp->address);
fs >> temp->phoneNo;
std::getline(fs, dummy);
recordCount++;
if(head == NULL){
head = temp;
previous = temp;
tail = temp;
} else {
previous->next = temp;
previous = temp;
tail = temp;
}
} while(!fs.eof());
// } else {
// cout << "there's no record in the file yet." << endl;
// }
cout << head->name << endl;
cout << head->address <<endl;
cout << head->email << endl;
cout << head->phoneNo << endl;
}
您创建了一个节点,因此循环中的每次迭代都会覆盖之前读取的值。
在 while 循环的第二次迭代中,您对 getline
的第一次调用可能会失败,并将 name
的值设置为空字符串。由于流现在处于失败状态,您的其余读取将被忽略,最后循环在循环结束时中断。
这可能更接近您想要的:
int recordCount = 0;
fs.open(fileName, ios::in | ios::binary);
while(fs) {
record * temp = new record;
std::getline(fs, temp->name);
std::getline(fs, temp->email);
std::getline(fs, temp->address);
fs >> temp->phoneNo;
if (!fs) {
// Reading failed, delete the temporary and exit the loop
delete temp;
break;
}
std::getline(fs, dummy);
recordCount++;
if(head == NULL){
head = temp;
previous = temp;
tail = temp;
} else {
previous->next = temp;
previous = temp;
tail = temp;
}
}
您的代码可以通过使用智能指针来确保 temp
永远不会泄漏,即使抛出异常也不会泄漏。
我将向您解释为什么会出现此问题以及如何避免。
这是一个典型的问题,在评论中提到了数千次,上面也是“molbdnilo”。
您不得使用 while (fs.eof())
。
我会向你解释为什么。顺便说一句,它只会发生,因为你在最后一行的末尾有一个新行。
让我们看看会发生什么:
- 变量“temp”被分配了一个次
- 文件已打开
do
-循环开始- 您通过 未格式化 输入函数
std::getline
读取姓名、电子邮件、地址。此函数将吃掉尾随的白色 space '\n'(但不会将其处理为读取变量 - 您使用格式化输入函数
>>
来读取 phone 数字(这不是一个好主意。无论如何)。格式化输入函数将在白色 space 处停止,这里是最后一行末尾的 '\n'。它不会消耗'\n'。这仍在流中并等待输入。 - 您将
std::getline
与虚拟对象一起使用,以从流中读取仍然存在的 '\n'。流还是可以的。到目前为止一切顺利。该文件也不在 EOF。我们可以阅读所有内容。所以,很好。 do loop
结束。你说:while(!fs.eof())
。但是如上所述:还没有EOF。一切都很好,现在仍然很好。循环将继续。- 再次回到循环的开始
std::getline(fs, temp->name);
将被调用。现在而不是以前,我们得到一个 EOF。因为我们试图阅读,现在没有什么可读的了。 “temp->name”将被设置为一个空字符串。现在,输入流处于 EOF 状态。 10 所有进一步的读取都不会执行任何操作,因为流处于 EOF 中。从现在开始,变量将不会被修改。
这就是为什么 name 为空而其他数据仍然存在的原因 运行。
为了快速修复,您可以编写
void list::readFile(std::string fileName) {
fstream fs;
string dummy = "";
string firstline;
record* previous = new record;
record* temp = new record;
int recordCount = 0;
fs.open(fileName, ios::in | ios::binary);
if (fs)
while (std::getline(fs, dummy)) {
temp->name = dummy;
std::getline(fs, temp->email);
std::getline(fs, temp->address);
fs >> temp->phoneNo;
std::getline(fs, dummy);
recordCount++;
if (head == NULL) {
head = temp;
previous = temp;
tail = temp;
}
else {
previous->next = temp;
previous = temp;
tail = temp;
}
}
// } else {
// cout << "there's no record in the file yet." << endl;
// }
cout << head->name << endl;
cout << head->address << endl;
cout << head->email << endl;
cout << head->phoneNo << endl;
}
但这也不好。稍后我会展示更好的解决方案。