当我的结构有整数和字符变量时,我无法输入

时间:2016-04-25 08:29:41

标签: c

以下是我用C编写的程序

#include <stdio.h>

struct Book
{
    char Title[80] ;
    char Author[80];
    int Pages;
    int DatePB;
};

struct Book input_book(void)
{
    struct Book b1;
    gets(b1.Title);
    gets(b1.Author);
    scanf("%d" , &b1.Pages);
    scanf("%d" , &b1.DatePB);
    return b1;
}   

int main(int argc , char *argv[])
{
    struct Book b1[3];
    int i;
    for (i = 0; i < 3; ++i)
    {
        printf("Enter Book %d:\n" , i + 1);
        b1[i] = input_book();
        printf("\n");
    }
    for (i = 0; i < 3; ++i)
    {
        printf("Book %d:\n" , i + 1);
        printf("%s\t%s\t%d\t%d\n" , b1[i].Title , b1[i].Author , b1[i].Pages , b1[i].DatePB);
        printf("\n");
    }
    return 0;
}

这是我得到的输出:

Enter Book 1:
Five Mistakes
Aaditua
532

Enter Book 2:
Four Mistakes
Aaditya

Enter Book 3:
Nine Mistakes 
Aaditya

Book 1:
Five Mistakes   Aaditua 581983988   532

Book 2:
    Four Mistakes   1   32681

Book 3:
Aaditya Nine Mistakes   1   32681

我不明白。我可以输入第一本书的每个细节,而我不能在第二本和第三本书中输入整数。请帮我解答相应的答案。

3 个答案:

答案 0 :(得分:0)

您可以替换;

gets(b1.Title);  // gets is deprecated
gets(b1.Author);

fgets(b1.Title,80,stdin);
fgets(b1.Author,80,stdin);
  

请注意,获取与fgets完全不同:不仅获得使用   stdin作为源,但它不包括结束换行符   在结果字符串中,不允许指定最大大小   对于str

然后把

while(getchar()!='\n') // Wasting any unprocessed buffer
  continue;;

在第二个scanf()之后。这是出于以下原因:

gets()可以取空字符串(参见上面的引文)。如果你的终端是行缓冲的,那么在第二个scanf()之后,当你在键盘上按Enter键时,会为\n缓冲区创建一个未经处理的stdin,这将被下一个{ {1}}。换句话说,下一个gets()将是一个空字符串。不好的一面是,这会在之后弄乱整个输入序列。

参考: gets

答案 1 :(得分:0)

不推荐使用gets()函数,主要是因为它可能导致缓冲区溢出。 fgets()是更好的选择:

  

char *fgets(char *str, int count, FILE *stream)

     

最多读取 - 给定文件流中的1个字符和   将它们存储在str指向的字符数组中。解析停止,如果   发生文件结束或找到换行符,在这种情况下为str   将包含该换行符。如果没有发生错误,则写入null   在最后一个字符写入后的位置处的字符   到str。如果count小于1,则行为未定义。

如果您在scanf之后使用问题,则问题可能会增加,因为fgets将通过scanf读取流中剩余的换行符并停止解析。

此处在评论和上一个答案中发布的解决方案的替代方法是编写您自己的帮助函数以从流中读取单行,跳过尾随换行符:

int read_line( char *str, int size, FILE *f ) {
    int ch,
        i = 0;

    --size;
    while ( i < size  &&  (ch = fgetc(f)) != EOF ) {
        if ( ch == '\n' ) {
            if ( i ) {
                // end of line
                break;
            }
            // skip empty lines
            continue;
        }
        str[i] = ch;
        ++i;
    }
    if ( i == size ) {
        // consume any unread char in line
        do {
            ch = fgetc(f);
        } while ( ch != '\n'  &&  ch != EOF );
    }
    str[i] = '\0';
    return i;
}

您还可以添加其他功能来读取数字:

#define NUMBER_SIZE 12

int read_number( FILE *f ) {
    int num;
    static char buffer[NUMBER_SIZE];

    read_line(buffer, NUMBER_SIZE, f);
    if ( sscanf(buffer, "%d", &num) != 1 )
        return 0;
    return num;
}

使用这些,您可以像这样重写您的程序:

#include <stdio.h>
#include <string.h>

#define TITLE_SIZE 80
#define AUTHOR_SIZE 80

/* ...define read_line and read_number here...  */

typedef struct
{
    char Title[TITLE_SIZE];
    char Author[AUTHOR_SIZE];
    int Pages;
    int DatePB;
} Book;

void input_book( Book *b, FILE *f )
{
    read_line(b->Title, TITLE_SIZE, f);
    read_line(b->Author, AUTHOR_SIZE, f);
    b->Pages = read_number(f);
    b->DatePB = read_number(f);
}   

int main(void) {
    Book books[3];
    int i;

    for ( i = 0; i < 3; ++i )
    {
        printf("Enter Book %d:\n" , i + 1);
        input_book(&books[i], stdin);
        printf("\n");
    }
    for ( i = 0; i < 3; ++i )
    {
        printf("Book %d:\n" , i + 1);
        printf("%s\t%s\t%d\t%d\n", books[i].Title, books[i].Author,
                                   books[i].Pages, books[i].DatePB);
        printf("\n");
    }
    return 0;
}

您还可以通过添加一些用户输入错误检查来改进input_book功能。

答案 2 :(得分:0)

我在Android上运行你的程序。  我可以参加第一本书的版本年,但我无法进入第二本书的第四部分。  所以我通过添加另一个get来修复它  在input_book方法中它运行良好。

struct Book input_book(void)        {     struct Book b1;
    char empty[80];
     gets(b1.Title); 
     gets(b1.Author);
     scanf("%d" , &b1.Pages);
     scanf("%d" , &b1.DatePB);
     gets(empty);

     return b1; }