1

だから私は長い間起きていたので、これを理解できないのかもしれません。しかし、私のコードは最初の実行でのみ機能します。つまり、約 4 つのオプションを含むメニューがあるため、最初に選択されたオプションに対してのみ機能します。do while ループが開始され、メニューが再び表示されると、何を選択してもメニューが再表示され続けます。do while ループを分析しましたが、問題はないと確信しています。私は最近ファイル I/O について学び始めたばかりなので、見逃しているものがあるかもしれません。どんな助けでも本当に感謝しています。ありがとう。

コードは次のとおりです。

電話帳.h

#include <iostream>
#include <fstream>
#include <cstdlib>
#include <string>

using namespace std;

class Phone
{ 
public:
void display_phonebook(ifstream& in_stream);// phonebook is the text file 
void display_backup(string a[], int size);// backup copy is a string array
void datacopy(ifstream& in_stream, string a[]);// to copy the phonebook to the array
int numberOfLines(ifstream& in_stream);// to check number of lines in the text file
};

電話帳.cpp

#include <iostream>
#include <fstream>
#include <cstdlib>
#include <string>
#include "Phonebook.h"

using namespace std;

void Phone::datacopy(ifstream& in_stream, string a[])
{
int i=0;
while(in_stream.good())
{
    string line;
    getline(in_stream, line);
    a[i]=line;
    i++;
}
int s=i;
for(int x=0;x<s;x++)
{
    cout<<a[x]<<endl;
}
}


int Phone::numberOfLines(ifstream& in_stream)
{
int count=0;
while(!in_stream.eof())
{
    string line;
    getline(in_stream, line);
    count++;
}
return count;
}

void Phone::display_phonebook(ifstream& in_stream)
{
while(!in_stream.eof())
{
    string line;
    getline(in_stream, line);
    cout<<line<<endl;
}
}

void Phone::display_backup(string a[], int size)
{
for(int i=0;i<size;i++)
{
    cout<<a[i]<<endl;
}
cout<<endl;
}

main.cpp

#include <iostream>
#include <fstream>
#include <cstdlib>
#include <string>
#include "Phonebook.h"

using namespace std;

int main()
{
Phone p;
int size=0;
ifstream fin;
ofstream fout;
char file[50], ch;
string backup[50];
int flag=0;
do
{
    cout<<"Enter the name of the file: "<<endl;
    cin>>file;
    fin.open(file);
    cout<<endl;
    if(fin.fail())
    {
        cout<<"File not found!"<<endl<<endl;
        cout<<"Try Again? (Y/N)"<<endl;
        cin>>ch;
        if(ch=='N' || ch=='n')
        {
            cout<<"Terminating..."<<endl;
            system("PAUSE");
            exit(1);
        }
    }
    else
    {
        flag=1;
    }
}
while((ch=='Y' || ch=='y') && flag==0);
cout<<"Success! File Opened"<<endl<<endl;
int choice;
do
{
    cout<<"1 - Display phonebook"<<endl;
    cout<<"2 - Display backup copy"<<endl;
    cout<<"3 - Update backup copy"<<endl;
    cout<<"4 - Exit"<<endl;
    cout<<"Enter your choice:  ";
    cin>>choice;
    if(choice==1)
    {
        p.display_phonebook(fin);
    }
    else if(choice==2)
    {
        size=p.numberOfLines(fin);
        p.display_backup(backup, size);
    }
    else if(choice==3)
    {
        p.datacopy(fin, backup);
    }
} 
while(choice!=4);
fin.close();
fout.close();
system("PAUSE");
return 0;
}
4

4 に答える 4

3

したがって、ifstream を関数に送信して getline を呼び出すと、「バッファ」が進められることに注意してください。そのため、バッファを再度開かずにその行を読み直すことはできません。これを考慮してコードを再編成するか、表示中にデータを再読み込みするのではなく、ファイルからデータを内部的に保存する必要があります。

于 2012-05-08T15:50:06.230 に答える
3

1)これほど多くのコードを投稿するべきではありません。最小限の完全な例を投稿する必要があります。つまり、まだ悪い動作を生成しながら、できる限りコードを削ります。最終的には、バグが明らかになるか、私たちが徹底的に調査できるように、はるかに小さくて単純なものに到達するかのいずれかです.

2) 関連のないコードをすべて削除するのに疲れ果てていませんか? 問題ありません。最初から書かないでください。小さく始め、構築し、すべての段階でテストし、機能しないコードに決して追加しないでください。問題を発見せずにコードをこれほど大きくしてはいけません。

3)

void Phone::display_phonebook(ifstream& in_stream)
{
  while(!in_stream.eof())
    {
      string line;
      getline(in_stream, line);
      cout<<line<<endl;
    }
}

これにより、ファイルの内容が1 回表示されます。次に、本の裏表紙をじっと見つめるように、ファイル ストリームはファイルの最後にあります。関数を再度呼び出すと、それ以上何も得られません。ファイルの内容を変数に保存するか、ストリームを閉じてから再度開く必要があります (または巻き戻しますが、これはより高度な手法であり、推奨されません)。

于 2012-05-08T15:54:38.817 に答える
0

皆さんの提案に感謝します。しかし、ええ、問題は、コントロールが 2 番目の関数に渡されたときに、入力ストリームがファイルの最後でスタックしていたことです。最も簡単な修正は、ストリームがファイルの最後に達した後にストリームを閉じて再度開くことでした。それが私が採用したものです。また、私がより良いコーダーになるのに役立つ他のことについても、皆さんから多くのことを知るようになりました (願っています!)。また、コードの例外処理を確実に検討します(@James Kanzeに感謝します)。よし、みんなハッピーコーディング。

于 2012-05-09T00:18:55.680 に答える
0

コードには多くの問題があります。

コードが一度だけ「機能する」理由は、最初にファイルを最後まで読み取り、入力をファイルの最後に残して、それ以上の読み取りが失敗するためです。前もってファイルを完全にメモリに読み込んでから、画像を渡す必要があります(おそらくさまざまな関数に渡すか、各関数でローカル変数として std::vector<std::string>新しいオブジェクトを作成する必要があります(メインにオブジェクトを持たないでください)それ以外の場合は、エラーをクリアして、各関数の前にストリームの先頭をシークする必要があります。std::ifstreamstd::ifstream

あなたがしているもう1つのことは、in_stream.good()or !in_stream.eof()をループの制御条件として使用することです。そして、少なくともdatacopyとでは、 が成功したことを確認せずに、display_phonebookによって読み取られた文字列を使用します 。通常、これにより最後の行が 2 回処理されます。 価値のない関数であり、失敗を検出した後に のみ興味深いものになります。ループを記述する正しい方法は次のとおりです。std::getlinestd::getlinestd::istream::good()st::istream::eof()

std::string line;
while ( std::getline( in_stream, line ) ) {
    //  ...
}

Phone::datacopy入力ファイルが 50 行を超えると、動作が未定義になります (おそらくクラッシュします)。ここで使用し、関数の先頭でクリアしてから、読み取った行ごとstd::vector<std::string> に呼び出し ます。push_back

また、コマンドを読み取るときにエラー処理を行う必要があります。たとえば、ユーザーが を入力する'a'と、無限ループに陥ります。std::getline行を個別に解析して、おそらくインタラクティブな入力にも使用します。そうすれば、実際の入力は、ユーザーがジャンクを入力した場合にクリアする必要があるエラー状態にはなりません。(そして、彼が のようなものを"Display phonebook"入力した場合、入力内の余分な文字をすべて削除する心配はありません。)

最後に、Linewhich operaator>>uses を使用してユーザー クラス を定義すると、ほとんどの関数は、 および を使用して をgetline1 回呼び出す だけになります。std::copystd::istream_iterator<Line>

チェーンのswitch代わりにa を使用できます。if/else if

于 2012-05-08T17:15:44.127 に答える