0

私のプログラムは、タイトルと著者のリストを含むファイルから入力を受け取るように設計されています。ファイルは次のようになります。

タイトル
関連する著者
次のタイトル
関連する著者
等

私が抱えている問題は、showBooksByTitle関数とshowBooksByAuthor関数にあります。現在、このコードは完全一致のみを返し、空の改行といくつかのスペースと()を含む新しい行を出力します。

もちろん、どんな助けでも大歓迎です。これは私の最初の年のプログラミングです。問題になる可能性のあるものを除外しないように、安全のためにコード全体を含めました。

#include <iostream>
#include<string>
#include<fstream>
#include<cstring>

using namespace std;

struct Book {
    string title;
    string author;
};

const int ARRAY_SIZE = 1000;
Book books [ARRAY_SIZE];

int loadData (string);
void showAll (int);
int showBooksByAuthor (int, string);
int showBooksByTitle (int, string);

int main() {
    //Declare variables
    string pathname;
    string title;
    string name;
    string word;
    int count;
    char response;

    //ask user for pathname
    cout << "What is the path of the library file? ";
    cin >> pathname;
    cout << endl;
    count = loadData(pathname);

    //input data into arrays
    loadData(pathname);
    cout << endl << count << " records loaded successfully." << endl << endl;

    //Show user menu
    cout << "Please enter Q to Quit, A to search for the Author, T to search for the Title, "
    << endl << "or S to Show all: ";
    cin >> response;

    switch(response) {
        case 'q':
            break;
        case 'Q':
            break;
        case 'a':
            cout << endl << "Please enter author's name: ";
            cin >> name;
            showBooksByAuthor(count, name);
            break;
        case 'A':
            cout << endl << "Please enter author's name: ";
            cin >> name;
            showBooksByAuthor(count, name);
            break;
        case 't':
            cout << endl << "Please enter all or part of the title: ";
            cin >> title;
            showBooksByTitle(count, title);
            break;
        case 'T':
            cout << endl << "Please enter all or part of the title: ";
            cin >> title;
            showBooksByTitle(count, title);
            break;
        case 's':
            cout << endl;
            showAll(count);
            break;
        case 'S':
            cout << endl;
            showAll(count);
            break;
        default:
            cout << endl << "Invaled input, please try again: ";
            break;
    }

    //pause and exit
    cout << endl;
    system("PAUSE");
    return 0;
}


int loadData(string pathname) {
    int i = 0;
    int j = 0;
    ifstream library;

    //open file, if not successful, output error message
    library.open(pathname.c_str());
    if (!library.is_open()) {
        cout << "Unable to open input file." << endl;
        return -1;
    }
    //reads title and author from file into designated string
    //this is assuming title comes first and author comes after
    while(!library.eof()) {
        getline(library, books[i].title);
        getline(library, books[i].author);
        i++;
    }
    return i;
}

void showAll (int count) {
    for (int i = 0; i < count; i++) {
        cout << books[i].title << " (" << books[i].author << ")" << endl;
    }
}

int showBooksByAuthor(int count, string name) {
    int found;
    for(int n = 0; n < 28; n++) {
        found = name.find(books[n].author);
        if(found != string::npos) {
            cout << endl << books[n].title << " (" << books[n].author << ")" << endl;
        }
    }
    return 0;
}


int showBooksByTitle (int count, string title) {
    int found;
    for(int n = 0; n < 28; n++) {
        found = title.find(books[n].title);
        if(found !=string::npos) {
            cout << endl << books[n].title << " (" << books[n].author << ")" << endl;
        }
    }
    return 0;
}
4

2 に答える 2

1

予期しない出力は、データファイルの読み取りが間違っているためです。ストリームのEOFフラグは、ストリームで操作を試行するまで設定されないため、ループは1回から何度も繰り返されます。

ループを次のように変更しますloadData

while(getline(library, books[i].title) && getline(library, books[i].author))
    i++;

これはstd::getline、ストリームを返すという事実と、ストリームをtrue/false値として使用できるという事実を使用します。

于 2013-03-18T11:53:47.170 に答える
1

主な問題はすでにヨアヒムによって指摘されていました。いくつかのレビューコメントを追加したいと思います:

  1. C ++には、可変長配列、 。がありstd::vectorます。また、リンクリストやその他のコンテナもあります。したがって、本を固定配列にするのではなく、標準のコンテナを使用してください。
  2. インデックスではなく、イテレータを使用して物事を繰り返します。配列の場合、ポインターはイテレーターです(C ++ 11にはend()、配列の終わりを過ぎたところにポインターを取得する関数があります。C++ 03で自分自身を作成するのは簡単ですが、とにかく古い配列を使用しないでください)。
  3. 入力文字列で本の名前/タイトルを探しています。サブストリングの一致が必要な場合は、逆の方法で行う必要があります。
于 2013-03-18T12:05:32.390 に答える