为什么stream :: ignore无法正常工作?

时间:2018-10-26 22:07:48

标签: c++ string file stream ignore

据我所知,stream.ignore(n,'n')应该忽略(n)个字符或是否达到'\ n',然后跳到下一行,但是,当我运行时下一个代码:

// include...
void insertInfo(int info) {
    std::fstream stream("infoFile.txt"); // Open the file
    while (!stream.eof()) {
        std::string a{};
        // getline(stream, a);    <--- Tryied this, didn't work neither
        stream.ignore(99, '\n');
    } // Skip to the last line without any number, in theory
    std::cout << info << std::endl; // Check if the output it's correct (Wich is)
    stream << info; // Insert the info
    stream.close(); // Close the file
}

void main() //Main
{
    std::cout << "Enter your name, followed by the info you want to add to infoFile:" << std::endl;
    std::string info, temp = "";
    std::getline(std::cin, temp); // Get the info input
    std::stringstream sstream;
    sstream << temp;
    sstream >> temp >> info; // Remove the name keeping only the info
    temp = "";              // ^
    std::string::size_type sz;
    insertInfo(stoi(info, &sz)); // Convert info string into an integer and insert it in infoFile
}

控制台会打印出“ info”正确的值,但是,当我检查info.txt时(以前我在其中写了一个“ 0”),则看不到任何更改。 我尝试删除“忽略”功能,它覆盖了0,这正是我要防止的功能。 我也尝试使用“ getline”功能,但是发生了同样的事情。 这是什么错误?

1 个答案:

答案 0 :(得分:0)

问题

无法写入文件。

为什么

void insertInfo(int info) {
    std::fstream stream("infoFile.txt"); // Open the file

使用默认权限打开文件,包括读取。 C ++标准says I should expect "r+" behaviour和C标准说,必须存在一个以“ r +”行为打开的文件才能被读取(如果有,请添加一个链接)。您无法创建新文件。这是问题1。Asker通过提供文件来解决此问题。

注意:通过相对路径处理文件时要小心。该程序的工作目录可能不在您认为的位置。这是问题1a。看来,问问者目前已经照顾好了。

    while (!stream.eof()) {

常见错误。有关更多详细信息,请参见Why is iostream::eof inside a loop condition considered wrong?。在这种情况下,由于您要查找的只是文件的末尾,因此会丢失该文件根本没有打开或遇到任何读取错误的事实。由于处于错误状态的文件永远无法到达文件末尾,因此这很快就变成了无限循环。这是问题2。

        std::string a{};
        // getline(stream, a);    <--- Tryied this, didn't work neither
        stream.ignore(99, '\n');

始终测试IO事务是否成功。此呼叫可能会失败,无法选中。

    } // Skip to the last line without any number, in theory

假定没有任何问题,并且由于我们没有做所有假设的错误状态检查,因此文件已到达末尾,现在处于EOF错误状态。在我们clear出现此错误之前,我们无法从流中读取或写入流。这是第3个问题,可能是Asker正在努力解决的问题。

    std::cout << info << std::endl; // Check if the output it's correct (Wich is)
    stream << info; // Insert the info

这可能会失败而未选中。

    stream.close(); // Close the file

这不是必需的。该文件超出范围时将关闭。

}

解决方案

void insertInfo(int info) {
    std::fstream stream("infoFile.txt"); // Open the file
    while (!stream.eof()) {
        stream.ignore(99, '\n');
    } // Skip to the last line without any number, in theory
    std::cout << info << std::endl; // Check if the output it's correct (Wich is)
    stream.clear(); // Added a call to clear the error flags.
    stream << info; // Insert the info
    stream.close(); // Close the file
}

现在我们可以写入文件了。但是让我们改善一下吧?

void insertInfo(int info) {
    std::fstream stream("infoFile.txt"); 
    while (stream.ignore(99, '\n')) // moved ignore here. now we ignore, then test the result
    {
    } 
    stream.clear();
    stream << info << '\n'; // added a line ending. Without some delimiter the file 
                            // turns into one big number 
}

请注意,这并非完全符合犹太标准。如果任何忽略由于某种原因而失败,我们将退出紧急状态并可能覆盖数据,因为代码会盲目地clear进行写入。我不会在这里花费很多时间来尝试对此进行修补,因为我们可以非常简单地解决同时创建不存在文件的问题。

void insertInfo(int info) {
    std::fstream stream("infoFile.txt", std::ios::app); 
    stream << info << '\n'; 
}

两行,差不多完成了。使用app,我们将附加到文件中。我们不需要查找文件的末尾,流会自动指向它。如果该文件不存在,则会创建它。

下一个改进:让人们知道写入是否失败。

bool insertInfo(int info) {
    std::fstream stream("infoFile.txt", std::ios::app);
    return static_cast<bool>(stream << info << '\n');
}

如果由于某种原因未写入文件,则该函数将返回false,并且调用者可以弄清楚该怎么做。剩下的唯一一件事就是加强流程。由于我们所做的只是写给ti,因此我们不需要fstream的宽容。始终从限制性最高的位置开始,并移至最小的位置。这样可以避免可能的错误,从而避免发生这些错误。

bool insertInfo(int info) {
    std::ofstream stream("infoFile.txt", std::ios::app);
    return static_cast<bool>(stream << info << '\n');
}

现在,我们使用ofstream并消除了在不读取流时读取流的能力带来的所有额外开销和风险。