2

私はこのCコードを持っています:

#include "stdio.h"

main()
{
    struct books
    {
        char name[100],author[100];
        int year,copies;
    }book1,book2;

    printf("Enter details of first book\n");
    gets(book1.name);
    gets(book1.author);
    scanf("%d%d",&book1.year,&book1.copies);

    printf("Enter details for second book\n");
    gets(book2.name);
    gets(book2.author);
    scanf("%d%d",&book2.year,&book2.copies);

    printf("%s\n%s\n%d\n%d\n",book1.name,book1.author,book1.year,book1.copies);
    printf("%s\n%s\n%d\n%d\n",book2.name,book2.author,book2.year,book2.copies);  
}  

ここで起こっていることは、2 冊目の本の著者名までしかスキャンしないということです。その後、出力を直接印刷します。

これが私の入力です:(最初の2行は最初のprintfステートメントです)

Enter details of first book
warning: this program uses gets(), which is unsafe.
the c programmign laguagne
dfadsda
3432
23
Enter details for second book
ruby on rails
mark hammers  

その後、出力を直接印刷します

the c programmign laguagne
dfadsda
3432
23

ruby on rails
0
0

ここで何が問題なのですか?また、2 冊目の本の名前が著者に割り当てられていることがわかります。

gccMac OS X ML のコンパイラとして使用しています。

4

5 に答える 5

1

ソースコードでは、

scanf("%d%d",&book1.year,&book1.copies);

これは 2 つの整数を読み取るだけなので、"23" の後の "\n" は読み取りません。

この問題の 1 つの解決策は、次のように、2 冊目の本を読む前に gets() を実行することです。

#include "stdio.h"

main()
{
    struct books
    {
        char name[100],author[100];
        int year,copies;
    }book1,book2;

    printf("Enter details of first book\n");
    gets(book1.name);
    gets(book1.author);
    scanf(" %d %d",&book1.year,&book1.copies);
    char a[100];
    gets(a);

    printf("Enter details for second book\n");
    gets(book2.name);
    gets(book2.author);
    scanf("  %d  %d",&book2.year,&book2.copies);

    printf("%s\n%s\n%d\n%d\n",book1.name,book1.author,book1.year,book1.copies);
    printf("%s\n%s\n%d\n%d\n",book2.name,book2.author,book2.year,book2.copies);  
}  

このため、gets を使用して整数を読み取り、その後 atoi を使用する方が簡単な方法です。

#include "stdio.h"

main()
{
    struct books
    {
        char name[100],author[100];
        int year,copies;
    }book1,book2;

    printf("Enter details of first book\n");
    gets(book1.name);
    gets(book1.author);
    char buff[100];
    gets(buff);
    book1.year = atoi(buff);
    gets(buff);
    book1.copies = atoi(buff);

    printf("Enter details for second book\n");
    gets(book2.name);
    gets(book2.author);
    gets(buff);
    book2.year = atoi(buff);
    gets(buff);
    book2.copies = atoi(buff);

    printf("%s\n%s\n%d\n%d\n",book1.name,book1.author,book1.year,book1.copies);
    printf("%s\n%s\n%d\n%d\n",book2.name,book2.author,book2.year,book2.copies);  
}  
于 2013-10-15T08:21:26.360 に答える
1

解決:

#include <stdio.h>  /* Using fgets(), scanf(), printf() in this program */
#include <string.h> /* Using strlen() in this program */

int main()
{
    struct books
    {
        char name[100],author[100];
        int year,copies;
    }book1,book2;

    char c;
    char read_new_line;

    printf("Enter details of first book\n");
    if (fgets(book1.name, sizeof(book1.name), stdin) == NULL)
    {
        fprintf(stderr, "error reading name of book 1\n");
        return -1;
    }
    /* Strip out \n character added by fgets */
    book1.name[strlen(book1.name) - 1] ='\0';

    if (fgets(book1.author, sizeof(book1.author), stdin) == NULL)
    {
        fprintf(stderr, "error reading author of book 1\n");
        return -1;
    }
    /* Strip out \n character added by fgets */
    book1.author[strlen(book1.author) - 1] ='\0';

    scanf("%d %d",&book1.year,&book1.copies);
    /* Strip out \n character left out in input stream */
    while ((read_new_line = getchar()) != EOF && read_new_line != '\n')                                             
        ;

    printf("Enter details for second book\n");
    if (fgets(book2.name, sizeof(book2.name), stdin) == NULL)
    {
        fprintf(stderr, "error reading name of book 2\n");
        return -1;
    }
    /* Strip out \n character added by fgets */
    book2.name[strlen(book2.name) -1 ] = '\0';

    if (fgets(book2.author, sizeof(book2.author), stdin) == NULL)
    {
        fprintf(stderr, "error reading author of book 2\n");
        return -1;
    }
    /* Strip out \n character added by fgets */
    book2.author[strlen(book2.author) - 1] ='\0';

    scanf("%d %d",&book2.year,&book2.copies);
    /* Strip out \n character left out in input stream */
    while((c = getchar()) != '\n' && c != EOF)
        ;

    printf("%s\n%s\n%d\n%d\n",book1.name,book1.author,book1.year,book1.copies);
    printf("%s\n%s\n%d\n%d\n",book2.name,book2.author,book2.year,book2.copies);  
    return 0;
}

質問に投稿されたコードに関する観察:

コードが機能しない理由を理解してみましょう。

以下のステートメントから scanf を呼び出した後

scanf("%d%d",&book1.year,&book1.copies);

あなたの入力は

3432\n
23\n

scanfを読み込んで3432に格納し&book1.year、次\nは入力ストリームで除外されます。次に、2 番目%dは先頭の空白 (このコンテキストの空白にはスペース、タブ、改行などが含まれます) を破棄し、それを読み取って23に保存し&book1.copiesます\n

gets(book2.name)入力ストリームでが呼び出された場合、条件に\n一致するgets()ため、「空の文字列」が割り当てられbook2.name、意味するものと提供されたユーザー入力book2.nameが に保存されbook2.authorます。

適切な整数が入力されず、失敗したためbook2.author、ユーザー入力が %d に割り当てられているため、その変換が行われ、失敗します。book2.yearscanf()

ノート :

于 2013-10-15T09:42:03.523 に答える
1

fflush(stdin)各入力ステートメントの前に使用します。このメソッドは入力バッファをクリアします。変更後、コードは次のようになります-

#include "stdio.h"

int main()
{
    struct books
    {
        char name[100],author[100];
        int year,copies;
    }book1,book2;

    printf("Enter details of first book\n");
    gets(book1.name);
    fflush(stdin);

    gets(book1.author);
    fflush(stdin);

    scanf("%d%d",&book1.year,&book1.copies);
    fflush(stdin);

    printf("Enter details for second book\n");
    gets(book2.name);
    fflush(stdin);

    gets(book2.author);
    fflush(stdin);
    scanf("%d%d",&book2.year,&book2.copies);

    printf("%s\n%s\n%d\n%d\n",book1.name,book1.author,book1.year,book1.copies);
    printf("%s\n%s\n%d\n%d\n",book2.name,book2.author,book2.year,book2.copies);  
    return 0;
} 

詳細はfflush() こちらからご覧いただけます

UPDATED : ここでは、scanf() ステートメントの後で、入力バッファーをフラッシュする必要があります。fflush() メソッドは、出力ストリームに対してのみ定義されているため、ここでは役に立ちません。次のように、各 scanf() 行の後に単一行コードを使用して、部分的に読み取られた行の残りを消費できます。

while((c = getchar()) != '\n' && c != EOF);

あなたのコードよりも:

#include "stdio.h"

int main()
{
    struct books
    {
        char name[100],author[100];
        int year,copies;
    }book1,book2;
    char c;
    printf("Enter details of first book\n");
    gets(book1.name);
    gets(book1.author);

    scanf("%d%d",&book1.year,&book1.copies);
    while((c = getchar()) != '\n' && c != EOF);

    printf("Enter details for second book\n");
    gets(book2.name);
    gets(book2.author);
    scanf("%d%d",&book2.year,&book2.copies);
    while((c = getchar()) != '\n' && c != EOF);

    printf("%s\n%s\n%d\n%d\n",book1.name,book1.author,book1.year,book1.copies);
    printf("%s\n%s\n%d\n%d\n",book2.name,book2.author,book2.year,book2.copies);  
    return 0;
} 

出力:

Enter details of first book
warning: this program uses gets(), which is unsafe.
sadsadas
asa
12
34
Enter details for second book
zxczxc
sds
23
22
sadsadas
asa
12
34
zxczxc
sds
23
22
于 2013-10-15T08:12:54.823 に答える
0

ちょっとしたメモですが、バッファーの安全性の問題により廃止されたため、おそらくfgets()代わりに使用する必要があります。gets()

これは、 が次のエントリのデータを読み取る前にscanf()最後に食べるという事実によるものです。\n

于 2013-10-15T08:10:11.363 に答える