繁体   English   中英

文本不保存到文件中

[英]Text doesn't save into the file

您好,我正在做一个程序,在我的程序中有一个Customer类。 为了将客户保存在计算机上,我创建了一个文件,并用::分隔客户的每个数据,例如name :: password :: phonenbr。 但是我的问题是,如果我在代码注释中写了一行,数据将被保存到文件中,但是如果我在if()中写同一行来检查文件是否为空,这不会尽管我在编译器中看到这行没有问题,但是仍然可以做任何事情。

如果您能帮助我,那将是很优雅的!

void Shop::Add_Customer()
{
    fstream myfile; myfile.open("CustomerFile.txt");
    string name, password, phonenbr;
    string buffer, delimitor = "::";

    system("cls");
    cout << "Name of the customer: "; cin >> name;
    cout << "Password of the customer: "; cin >> password;
    cout << "Phone number of the customer: "; cin >> phonenbr;

    if (!myfile.is_open())
    {
        myfile.open("CustomerFile.txt", ios::out);
    }
    //myfile << name + delimitor + password + delimitor + phonenbr << endl;

    if (myfile.peek() == std::ifstream::traits_type::eof())
    {
        myfile << name + delimitor + password + delimitor + phonenbr << endl;
    }
    else
    {
        while (getline(myfile, buffer))
        {
            if (CheckIfCustomerExist(buffer, name, phonenbr) == true)
            {
                cout << "Customer already exist" << endl;
            }
            else
            {
                myfile << name + delimitor + password + delimitor + phonenbr << endl;
                cout << "Customer insert in the file " << endl;
            }
        }
    }


}

当流的任何读取失败(因为它试图读取流的末尾)而失败时,将设置流中的EOF标志。 设置EOF后,流将处于错误状态,并且只有在清除EOF标志后才能对其进行读写。

这是一个非常简单的例子,说明正在发生的事情:

#include <iostream>
#include <fstream>
using namespace std;

int main()
{
    fstream myfile("CustomerFile.txt", ios::out);
    if (!myfile.is_open())
    {
        cout << "file not open." << endl;
    }
    else
    {
        if (myfile.peek() == std::ifstream::traits_type::eof())
        {
            if (myfile.eof())
            {
                cout << "Need to clear the EOF flag." << endl;
            }
        }
    }
}

偷看EOF会设置EOF标志,将流置于错误状态并使其不可写。 由于我们要扩展文件,因此需要使用适当命名的clear方法清除该标志

#include <iostream>
#include <fstream>
using namespace std;

int main()
{
    fstream myfile("CustomerFile.txt", ios::out);
    if (!myfile.is_open())
    {
        cout << "file not open." << endl;
    }
    else
    {
        if (myfile.peek() == std::ifstream::traits_type::eof())
        {
            if (myfile.eof())
            {
                cout << "Need to clear the EOF flag." << endl;
            }
            myfile.clear();
            if (!myfile.eof())
            {
                cout << "OK. EOF clear now." << endl;
            }
        }
    }
}

离题的东西:

以下代码

   while (getline(myfile, buffer))
    {
        if (CheckIfCustomerExist(buffer, name, phonenbr) == true)
        {
            cout << "Customer already exist" << endl;
        }
        else
        {
            myfile << name + delimitor + password + delimitor + phonenbr << endl;
            cout << "Customer insert in the file " << endl;
        }
    }

将对文件中的每一行重复一次,大概是与文件中的每个客户一一对应地检查输入客户。 每次输入客户不匹配时,输入客户都将添加到文件中。 这意味着输入的客户可能会多次添加到文件中。 更糟糕的是,该程序正在同时读取和写入同一文件,并且可能最终损坏该文件。

最好进行阅读和比较,然后如果找不到匹配项,则前进到文件末尾并添加输入客户。

另外,文件打开逻辑不必要地复杂,并且可能仍然会失败

fstream myfile; myfile.open("CustomerFile.txt");

if (!myfile.is_open())
{
    myfile.open("CustomerFile.txt", ios::out);
}

如果文件不存在,则第一个打开操作肯定会失败,从而迫使第二个打开操作。 也可以将ios::out添加到此调用中并完成此操作。 第二个呼叫顶部打开可能由于其他原因而失败,并且未经过成功测试,因此我建议

fstream myfile("CustomerFile.txt", ios::out);
if (!myfile.is_open())
{
    perror("file not open: ");
}
else
{
    // your code goes here
}

perror文件

问题的根源在于if陈述的条件:

    (myfile.peek() == std::ifstream::traits_type::eof())

显然,您的文件在以下行以fstream模式打开:

    fstream myfile; myfile.open("CustomerFile.txt");

现在,我之所以不能满足您的if语句条件,是因为文件模式不同。 我不确定我是否正确(在评论框中欢迎反馈),但这就是我可以提出的原因。

我尝试了一种我自己的方法,该方法始终有效,它也适用于您的代码。 我在您的代码中替换了以下几行:

    if (myfile.peek() == std::ifstream::traits_type::eof())
    {
        myfile << name + delimitor + password + delimitor + phonenbr << endl;
    }

这些行:

    myfile.seekg (0, ios::end);
    int length = myfile.tellg();

    if (length == 0)
    {
        myfile << name + delimitor + password + delimitor + phonenbr << endl;
    }

第一行myfile.seekg (0, ios::end); 获取括号中指定的2个点之间的距离。 0和ios :: end不言自明; 0是文件的开头,而ios :: end是文件的结尾。

第二行int length = myfile.tellg(); 将在上一行中查找的值存储在一个名为length的int变量中。 长度是“光标”从该文件的开头到结尾必须移动的字符数(尝试将光标想象为类似于您所用单词前面的Microsoft Word中的闪烁对象)键入,除了此处,您看不到文本文件中的光标从头到尾移动)。

如果条件很简单。 如果长度为零,则意味着光标必须移动0点才能从文件的开头到文件的结尾,然后将所需的内容写入该文件。 这项技术有效(至少对我有用)。

附带说明,您的代码还有很多其他方面可以改进。 例如,为什么要添加以下if语句:

if (!myfile.is_open())
{
    myfile.open("CustomerFile.txt", ios::out);
}

这段代码是这些代码行的重复:

fstream myfile; myfile.open("CustomerFile.txt");

.open()命令已经完成了我指出的if语句。 如果找到了open()中指定的文件,则它将打开该文件;否则,它将打开该文件。 否则它将继续创建该新文件。 因此,if语句是多余的,应予以删除,因为它会消耗不必要的CPU功率并减慢程序运行速度(不是很多,但您很快就会意识到,每毫秒都在运行代码中起作用;效率是关键)。 我建议您删除该if语句。

另一个问题是您接受输入的3个变量。 既然它们是字符串,为什么要使用cin >>方法? 使用cin仅会占用您句子中的第一个单词; 在您的以下行中:

    cout << "Name of the customer: "; cin >> name;

如果输入John Doe ,它将仅将John保存到名称变量,并将“ Doe”移至下一个输入变量,在您的情况下为密码。 如果没有其他cin,则它将忽略空格后面的单词。 因此,对所有输入点使用以下行:

    getline(cin, name);

该功能将所有单词和空格作为单个句子获取,直到您按Enter键为止,而cin不像cin那样仅获取第一个单词,而忽略其余句子。

最后,您的电话号码应为int类型。 我将根据您的要求留给您修复。

希望我回答了您的问题,希望我的建议对您有所帮助。 祝好运!


编辑:我想念您的代码的另一点是您的while循环为每一行运行。 这意味着它将在文件的每一行中检查特定客户的名称。 这不是您想要的。 您想读取文件中的每一行,但如果找到客户,则想终止该功能而不继续下一行。 另外,您只想在读取整个文件(而不只是一行)之后打印错误声明。

else
{
    int check = 0;
    while (getline(myfile, buffer))
    {
        if (CheckIfCustomerExist(buffer, name, phonenbr) == true)
        {
            cout << "Customer already exist" << endl;
            check = 1;
            break;
        }
    }
    if (check == 0)
    {
        myfile << name + delimitor + password + delimitor + phonenbr << endl;
        cout << "Customer insert in the file " << endl;
    }
}

这段代码的作用是贯穿每一行,检查该行中的客户。 如果该行有客户记录,则它将int类型的检查值从0设置为1,并且break语句终止while循环。 读取整个文件后,它将继续进入if语句。 在此语句中,如果check变量仍为0,则意味着该文件没有客户,新记录将添加到该客户中。

另外,我说过phone_number应该是一个int值。 我再回过头来看,并从StackOverflow的其他用户那里输入,电话号码更适合作为字符串值,因为其格式可能无法正确存储为int值(例如0059875将存储为59875)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM