2

テキストファイル内の英数字の数を数えるプログラムを作成しました。ただし、返される数は、オンライン文字カウンターが返す数よりも常に大きくなります。

たとえば、プログラムはこのテキストの英数字の数を計算します。

これらの人々が奇妙な流行を持っていて、最も異常な問題に従順であると期待した場合、彼らは少なくとも彼らの偏心の代償を払う準備ができていました

プログラムを再度実行すると、テキストに164​​文字が含まれていることがわかります。もう一度実行すると、156文字あると表示されます。このオンライン文字カウンターを使用すると、文字数は144より少なくなるはずです(オンライン文字カウンターにはスペースも含まれます)。

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

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

int main() {
    char line[100];
    int charcount = 0;
    ifstream file("pg1661sample.txt");
    while (!file.eof()) {
        file.getline(line, 99);
        for (int i = 0; i < 100; i++) {
            if (isalnum(line[i])) {
                charcount++;
            }
        }
    }

    cout << endl << "Alphanumeric character count: " << charcount;
    cin.get();
    return 0;
}

私は何が間違っているのですか?

4

3 に答える 3

5

試す:

#include <iterator>
#include <algorithm>
#include <iostream>
#include <cctype>
bool isAlphaNum(unsigned char x){return std::isalnum(x);}
int main()
{
    std::cout << "Alphanumeric character count: " <<
    std::count_if(std::istream_iterator<char>(std::cin),
                  std::istream_iterator<char>(),
                  isAlphaNum
                 ) ;
}

コードの問題:

ファイルの終わりを超えて読み取るまで、EOFは真ではありません。

 // this is true even if there is nothing left to read.
 // If fails the first time you read after there is nothing left.
 while (!file.eof()) {

 // thus this line may fail
     file.getline(line, 99);

常にこれを行うことをお勧めします:

 while(file.getline(line, 99))

ループに入るのは、getlineが実際に機能した場合のみです。

また、悪いバージョンのgetlineを使用しています(行が100文字を超える場合があるため)。
std :: stringで動作するバージョンを使用して、自動拡張されるようにしてください。

std::string  line;
while(std::getline(file, line))
{
     // stuff
}

次に、その行が正確に100文字であると想定します。
行の長さが2文字しかない場合はどうなりますか?

for (int i = 0; i < 100; i++)

基本的に、データをスキャンして、前の行の残りの文字(前の行が現在より長い場合)または完全にランダムなゴミをカウントします。まだ使用している場合はfile.getline()、を使用して1行から文字数を取得できますfile.gcount()。std :: getline()を使用する場合、変数lineは読み取られた行の正確なサイズになります(line.size())。

于 2012-08-20T22:45:11.640 に答える
1
while (!file.eof()) {

これをしないでください。eof()は、入力の試行が失敗するまでtrueを返さないため、このようなループは余分な時間を実行します。代わりに、これを行います。

while (!file.getline(line, 99)) {

入力が終了すると、ループは終了します。

もう1つの問題は、文字をカウントするループにあります。自問してみてください。入力ループを通過するたびに、何文字がバッファに読み込まれましたか。では、なぜカウントループは100文字を見ているのでしょうか。

于 2012-08-20T22:35:19.970 に答える
0

あなたはそれが正確に100文字でgetline()埋められると仮定しています。lineによって読み込まれた文字列の長さを確認しますgetline()。たとえば、:を使用しstrlen()ます。

for (int i = 0; i < strlen(line); i++) {
    if (isalnum(line[i])) {
        charcount++;
    }
}

編集:また、他の回答からの提案に注意して、をgetline()呼び出すのではなく、ループ条件にの戻り値を使用するようにしてくださいeof()

于 2012-08-20T22:33:01.327 に答える