0

これは宿題の質問ですが、私はすでに完了しています。これは私の理解のためです。追加するために、私はSTLを使用できませんでした:(

基本的には、5 つのパラメーター (姓名、ID、学年、専攻) を持つ「Student」クラスを実装する必要がありました。次に、各 Student オブジェクトを配列に格納する必要があります (教室と呼びましょう)。

私の問題は、ユーザーが新しい学生を追加するときに発生します。最初、私のコードは次のように各パラメーターを取りました:

cin >> first >> last >> id >> grade >> major;

そして、それらを配列に格納する別の関数に渡します。ユーザーが必要に応じてすべてを入力すると、これは正常に機能します。入力例:

students> add John Smith 123 Freshman Computerscience

しかし、間違って入力された場合、具体的には次のように ID 入力 (int) を使用した場合:

students> add John Smith 123abc Freshman Computerscience

学年として「abc」、専攻として「新入生」を取得し、残りについてはエラーを吐き出します。

そこで、入力全体を単一の文字列として取得して解析することにしました。そのコードは次のとおりです。

    class Student {
    private:
        string first_name;
        string last_name;
        int ID;
        string classification;
        string major;
    public:
        Student();

        /* Main class functions */
        void add(string, string, int, string, string);
        void print(string);
        bool remove(int);

        /* Helper class functions */
        bool empty();
        bool ifexist(int);
    };

  int main() 
     {
        bool done = false;
        string command, first, last, grade, major;
        int id;
        string query, input;
        string inputArray[6];
        string token = " ";
        while(!done) {
            cout << prompt;
            cin >> command;

            if(command == "add")
            {
                /* Get new student info */
                cin >> first >> last >> id >> grade >> major;;

                // this commented code is my attempt to fix error
                // count = 0;
                // while(getline(cin, input)) {
                //  stringstream s(input);
                //  while(s >> token) {
                //      inputArray[count] = token;
                //      count++;
                //  }
                //  if(count == 5) break;
                // }

                // first = inputArray[0];
                // last  = inputArray[1];
                // if(atoi(inputArray[2].c_str()))
                //  id= atoi(inputArray[2].c_str());
                // else cout << ERROR_INPUT << endl; 
                // grade = inputArray[3];
                // major = inputArray[4];

                // for (int i=0; i<5; i++) {
                //  cout << inputArray[i] << endl;
                // }
                //cout << first << endl << last << endl << id << endl << grade << endl << major << endl;

                int i = getInsertPoint();
                bool e = ifexist(id);

                /* Check if student already exists */
                if(e) cout << "Error! Already exists, try again" << endl;
                else  classroom[i].add(first, last, id, grade, major); 
            }
            else if(command == "print") 
            {
                /* Get query type to be printed (ex: firstname) */
                cin >> query;
                print(query);
            }
            else if(command == "remove")
            {
                cin >> id;
                remove(id);
            }
            else if(command == "quit") done = true;
            else cout << ERROR_INPUT << endl;
        }
        return 0;
    }

配列を出力するとすべてうまくいきますが、それぞれをオブジェクトに格納する関数に渡すと、何も表示されません。ただし、最初に言及したコードを使用すると機能します。

だから私の質問はこれです:各トークンを個別に別の関数に送信できるようにする入力文字列(STLなし)を解析/チェックするより良い方法はありますか?

4

1 に答える 1

0

あなたのループ構造はやや壊れています。問題になる可能性のある意図に応じて:

while(getline(cin, input)) {
    stringstream s(input);
    while(s >> token) {
      inputArray[count] = token;
      count++;

ここでは、配列が処理できる 6 ワードを超えて蓄積しても、問題なく続行できます。これが発生すると、プログラムの動作は未定義になります。

    }
    if(count == 5) break; //got everything I need

したがって、(配列が対応できる 6 つの単語のうち) 正確に 5 つの単語を蓄積した場合、それらの 5 つの単語を処理します。単語が 5 未満の場合は、次の行から単語を追加していきます。1 つまたは複数 (最大 5 つ) の空でない行を「解析」して、正確に 5 語が得られた場合にのみ停止します。5 ワードの制限を超えた場合 (たとえば、最初の行が 4 ワードで、2 行目が少なくとも 2 ワードの場合)、入力が終了するか、プログラムがクラッシュするまで続行します。これは、メモリ全体に書き込みを行っているためです。

  }

を使用するatoi()と、無効な入力 (「123abc」など) が受け入れられます。一方、スペースが誤って欠落している場合 ("123Freshman")、コードは誤動作します。

したがって、あなたの質問に対する私の答えは次のとおりです。はい、入力を解析してチェックするより良い方法があります。ただし、入力のルールを明確に示すことができない限り、コードの修正を支援することはできません。また、「各トークンを個別に別の関数に送信する」方法を尋ねるとき、あなたが何を意味するのかは明確ではありません。

一言一句そのままにすると、答えは次のようになります。

string token;
while (getline(cin, token)) { 
   another_function(token);
}

完全な例 (コードと入力) を示さないと、「[あなた] がそれぞれをオブジェクトに格納する関数に渡したときに」なぜうまくいかないのかわかりません:起こる、あなたが代わりに見るもの。また、そのコードも示さないと、結果が「[あなたが] 最初に言及したコード」と異なる理由もわかりません。

于 2013-01-31T23:52:53.867 に答える