检查 !str.find() 时抛出调试错误

Debug Error Thrown When Checking !str.find()

我正在学习 C++。我正在开发一个简单的“图书馆管理”应用程序,允许用户创建帐户、借阅书籍等。每本书都使用唯一的文本文件进行管理。文本文件包含如下三行,但是第三行是这里唯一重要的内容,因为它包含本书的所有者。

以下代码打印包含所有书籍列表的附加文本文件的内容,但这与错误无关。它将文本文件的内容转换为字符串,然后检查“NA”是否存在。如果存在“NA”,则将其替换为当前用户名。然后使用 ios::trunc 重新打开文件以擦除文件,并将新字符串传递到文件中。这很好用。

问题是,当 运行 应用程序时,如果用户名已经存在而不是“NA”,我得到的 Debug Error 只显示 abort() has been called。我试过调试,但无法获得更多信息。

这是错误和代码:

void bookCheckout()
{
    system("CLS");
    string line;
    string bookChoice;
    ifstream checkBookList;
    ofstream checkOutBook;
    checkBookList.open("books/booklist.txt");
    
    string sTotal;
    string s;

    

    cout << "<---Avaliable Books--->" << endl;
    while (getline(checkBookList, line)) {
        cout << line << endl;
    }
    checkBookList.close();

    cout << "\nWhat Book Would You Like?:";
    cin >> bookChoice;

    checkBookList.open("books/" + bookChoice + ".txt");
    while (!checkBookList.eof()) {
        getline(checkBookList, s);
        sTotal += s + "\n";
    }

    checkBookList.close();
    if (sTotal.find("NA")) {
        sTotal.replace(sTotal.find("NA"), 2,  globalUsername);
        checkOutBook.open("books/" + bookChoice + ".txt", ios::trunc);
        checkOutBook << sTotal;
        checkOutBook.close();
    }
    else if (!sTotal.find("NA")) {
        
        cout << "Book already checked out!" << endl;
    }
    
    checkOutBook.close();
    


    
    system("PAUSE");

    

}

您的代码存在一些问题:

  • 缺乏错误处理。

  • while (!checkBookList.eof()) - 参见 Why is iostream::eof inside a loop condition (i.e. while (!stream.eof())) considered wrong?

  • if (sTotal.find("NA")) - string::find() returns 一个索引,而不是布尔值。如果返回 0,则将被评估为 false。所有其他值都将被评估为 true,包括 string::npos (-1),如果未找到匹配项,这就是 string::find() returns。

此外,您的目标是检查 3RD LINE SPECIFICALLY 是否为 "NA",因此使用 string::find() 不是该目的的最佳选择。想一想如果第一行或第二行碰巧 包含 字母 NA 会发生什么。您的代码逻辑将无法正常运行。

  • else if (!sTotal.find("NA")) - 根本不需要在 else 中调用 find()。直接使用else即可。

话虽如此,试试这样的东西:

void bookCheckout()
{
    system("CLS");

    ifstream checkBookList;

    checkBookList.open("books/booklist.txt");
    if (!checkBookList.is_open()) {
        cerr << "Unable to open booklist.txt" << endl;
        return;
    }

    string line;

    cout << "<---Available Books--->" << endl;
    while (getline(checkBookList, line)) {
        cout << line << endl;
    }
    checkBookList.close();

    cout << "\nWhat Book Would You Like?:";

    string bookChoice;
    getline(cin, bookChoice);

    checkBookList.open("books/" + bookChoice + ".txt");
    if (!checkBookList.is_open()) {
        cerr << "Unable to open " + bookChoice + ".txt for reading" << endl;
        return;
    }

    string sTotal, sOwner;
    int lineNum = 0;
    string::size_type ownerIndex = string::npos;

    while (getline(checkBookList, line)) {
        ++lineNum;
        if (lineNum == 3) {
            sOwner = line;
            ownerIndex = sTotal.size();
        }
        sTotal += line + "\n";
    }

    checkBookList.close();

    if (sOwner == "NA") {
        sTotal.replace(ownerIndex, 2, globalUsername);

        ofstream checkOutBook("books/" + bookChoice + ".txt", ios::trunc);
        if (!checkOutBook.is_open()) {
            cerr << "Unable to open " + bookChoice + ".txt for writing" << endl;
            return;
        }

        checkOutBook << sTotal;
        checkOutBook.close();

        cout << "Book checked out!" << endl;
    }
    else {
        cout << "Book already checked out by " << sOwner << "!" << endl;
    }

    system("PAUSE");
}

或者,使用 std::vector 来收集图书内容,这样您就可以通过索引访问每一行:

#include <vector>

void bookCheckout()
{
    system("CLS");

    ifstream checkBookList;

    checkBookList.open("books/booklist.txt");
    if (!checkBookList.is_open()) {
        cerr << "Unable to open booklist.txt" << endl;
        return;
    }

    string line;

    cout << "<---Available Books--->" << endl;
    while (getline(checkBookList, line)) {
        cout << line << endl;
    }
    checkBookList.close();

    cout << "\nWhat Book Would You Like?:";

    string bookChoice;
    getline(cin, bookChoice);

    checkBookList.open("books/" + bookChoice + ".txt");
    if (!checkBookList.is_open()) {
        cerr << "Unable to open " + bookChoice + ".txt for reading" << endl;
        return;
    }

    vector<string> sTotal;
    sTotal.reserve(3);

    while (getline(checkBookList, line)) {
        sTotal.push_back(line);
    }

    while (sTotal.size() < 3) {
        sTotal.push_back("");
    }

    checkBookList.close();

    if (sTotal[2] == "" || sTotal[2] == "NA") {
        sTotal[2] = globalUsername;

        ofstream checkOutBook("books/" + bookChoice + ".txt", ios::trunc);
        if (!checkOutBook.is_open()) {
            cerr << "Unable to open " + bookChoice + ".txt for writing" << endl;
            return;
        }

        for(size_t i = 0; i < sTotal.size(); ++i) {
            checkOutBook << sTotal[i] << '\n';
        }
        checkOutBook.close();

        cout << "Book checked out!" << endl;
    }
    else {
        cout << "Book already checked out by " << sTotal[2] << "!" << endl;
    }

    system("PAUSE");
}