1

私はこの質問を調査しようとしましたが、私を助けるものを見つけることができませんでした。私は常にを使用してデバッグしようとしていますfprintが、それでも理解できません。

私は中級のプログラマーです。ここで助けを得ることができればと思います。これが私のコードです:

int i = 0;
const int arraySize = 10;
char buf[256];
char str[256];
char buffer[256];
char *beerNames[arraySize] = { };

FILE *names;
FILE *percent;
i = 0;
int numBeers = 0;
printf("Please enter a name or (nothing to stop): ");
gets(buf);
while (strcmp(buf, "") != 0) {
    beerNames[i] = strdup(buf);
    i++;
    numBeers++;

    if (numBeers == arraySize)
        break;

    printf("Please enter a name or (nothing to stop): ");
    gets(buf);
}

// now open files and look for matches of names:        //      
names = fopen("Beer_Names.txt", "r");
percent = fopen("Beer_Percentage.txt", "r");

while (fgets(str, sizeof(str) / sizeof(str[0]), names) != NULL) {
    fgets(buffer, sizeof(buffer) / sizeof(buffer[0]), percent);
    for (i = 0; i < numBeers; i++) {
        if (strcmp(str, beerNames[i]) == 0) {
            printf("Beer: %s Percentage: %s\n", str, beerNames[i]);
            break;
        }
    }
}

fclose(names);
fclose(percent);

だから、私が抱えている問題は、私がしようとしたときにstrcmp()、正しく比較されておらず、a-1またはaのいずれかを返していること1です。値も出力してみましたstrcmp()が、0に等しい場合は一致をスキップしてしまいます。

私のBeer_Names.txt(短縮)は次のようになります。

Anchor Porter
Anchor Steam
Anheuser Busch Natural Light 
Anheuser Busch Natural Ice
Aspen Edge
Big Sky I.P.A. 
Big Sky Moose Drool Brown Ale 
Big Sky Powder Hound (seasonal) 
Big Sky Scape Goat Pale Ale 
Big Sky Summer Honey Ale (seasonal) 
Blatz Beer 
Blatz Light
Blue Moon

そして、私のBeer_Percentage.txt(短縮)は次のようになります。

5.6
4.9
4.2
5.9
4.1
6.2
5.1
6.2
4.7
14.7
4.8
0
5.4

これは宿題ではありません。私は個人的なプロジェクトを行っているだけで、Cを上達させようとしています。

4

2 に答える 2

3

問題は、gets()が文字列の一部として改行文字を返さないのに対し、fgets()が返すことです。

したがって、ユーザーが入力した値「Anchor Porter」が gets で読み取られると、文字列は次のようになり"Anchor Porter\0"ますが、fgets を使用してファイルから読み取ると、次のようになります"Anchor Porter\n\0"

于 2012-03-27T01:15:44.693 に答える
2
gets(buf);

が便利であることはわかっていますしgets(3)、これがおもちゃであることはわかっていますが、使用しないでくださいgets(3)。安全なコードを書くことは不可能でgets(3)あり、将来の C ライブラリにはこの関数が含まれない可能性さえあります。(はい、標準化されていることは知っていますが、将来のバージョンでは省略されることを期待できます。POSIX.1-2008 では削除されています。) 合理的なコンパイラは、その使用について警告します。fgets(3)代わりに使用してください。

while (fgets(str, sizeof(str) / sizeof(str[0]), names) != NULL) {

sizeof(char)と定義されています1。これが変更される可能性は低く、配列の型を変更する可能性はほとんどありません。一般的には大したことではありませんが、このような構造を頻繁に使用することはできません。この場合に使用できるstr[]のは、 がこの行の外側のスコープで宣言されているためです。strパラメータとして渡された場合、演算子は配列のサイズではなくsizeof(str)、データ ポインタのサイズを返します。この構成に慣れすぎないようにしてください。常に期待どおりに機能するとは限りません。

names = fopen("Beer_Names.txt", "r");
percent = fopen("Beer_Percentage.txt", "r");

while (fgets(str, sizeof(str) / sizeof(str[0]), names) != NULL) {
    fgets(buffer, sizeof(buffer) / sizeof(buffer[0]), percent);

fopen(3)成功か失敗かを確認する時間をとってください。これは良い習慣です。適切なエラー メッセージを提供すれば、将来的にも時間を節約できる可能性があります。fopen()行を次のように置き換えます。

names = fopen("Beer_Names.txt", "r");
percent = fopen("Beer_Percentage.txt", "r");

if (!names) {
    perror("failed to open Beer_Names.txt");
    exit(1);
}
if (!percent) {
    perror("failed to open Beer_Percentage.txt");
    exit(1);
}

fopen()それを、戻り値をチェックし、エラーメッセージを出力して終了するか、FILE*オブジェクトを返す関数にまとめることができます。

そして今、あなたをここに連れてきたバグ: Robertはそれを指摘し、入力の終了改行を異なる方法で処理しましたfgets(3)。(できるだけ早くgets(3)取り除くもう1つの理由。)gets(3)

于 2012-03-27T01:21:44.017 に答える