无法正常输入带空格的字符串

无法正常输入带空格的字符串

我想要实现的功能是一次输入图书的书名、id、时间等等和图书简介(带空格的字符串)。尝试了:
1.scanf()里面用%s。缺点是不能输入空格
2.get()
3.fgets()
2和3的共同缺点是,在运行时,刚输出完introduction:那一行后,程序好像直接跳过了输入的语句,开始输出下面的内容。

下面是源代码的部分内容:

p = (struct bookstruct*)malloc(sizeof(struct bookstruct));

            strcpy(p->bookname, bookname);
            printf("ISDN ");//add
            scanf("%d", &p->id);
            printf("author: ");
            scanf("%s", p->author);
            printf("bookyear: ");
            scanf("%d", &p->year);
            printf("bookmonth: ");
            scanf("%d", &p->month);

            printf("bookcount: ");
            scanf("%d", &p->count);

            printf("price: ");
            scanf("%d", &p->price);

            printf("press:");
            scanf("%s", p->press);

            printf("introduction: ");//需要允许输入一长串英文文章(带空格的字符串)

            /*三种输入方法都不行:*/
            //gets(p->intro);
            //scanf("%s", p->intro);//不允许输入空格
            fgets(p->intro, 100, stdin);//100是char intro的长度

            bookend->next = p;
            bookend = p;
            bookend->next = NULL;

该回答引用ChatGPT4与博主@晓码自在合作编写:

你遇到的问题是,C语言的scanf()和fgets()在读取带空格的字符串时的问题。原因是:

  1. scanf()在读取%s格式时,遇到空格、回车等会停止读取。

  2. fgets()在读取时,输入的字符串包含空格,那么空格之后输入的内容会作为下一次输入读取。

要解决这个问题,有两种常用的方法:

  1. 使用fgets()读取到一个缓冲区,然后使用sscanf()从缓冲区解析出需要的字符串:
c
char intro[100];
fgets(intro, 100, stdin);
sscanf(intro, "%s", p->intro);

  1. 使用fgets()读取字符串,然后使用strtok()函数分割字符串,获取需要的部分:
c
char intro[100];
fgets(intro, 100, stdin);
char *token = strtok(intro, " ");
strcpy(p->intro, token);

这里strtok()使用空格" "作为分割符,将intro字符串分割,获取第一个token,即书名字符串,存储到p->intro中。

所以你的代码可以修改为:

c
printf("introduction: ");
char intro[100];
fgets(intro, 100, stdin);
char *token = strtok(intro, " ");
strcpy(p->intro, token);

使用fgets()读取字符串,然后strtok()获取需要的部分,这样就可以解决读取带空格字符串的问题了。

strtok()每次调用会获取字符串的下一个token,所以如果需要获取字符串中的多个空格分隔的词,可以多次调用strtok()。

你可以尝试着使用fgets()函数来输入带空格的字符串,但是需要注意以下几点:

fgets()函数会将输入的换行符\n也读入缓冲区,在使用输入字符串时需要将其去除。

输入的字符串长度可能会超过您指定的缓冲区大小,所以需要对输入字符串的长度进行检查,如果超出了缓冲区大小,则需要将缓冲区扩大。

以下是优化后的代码(仅供参考):

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

#define MAX_INTRO_LEN 1000 // 输入的字符串最大长度

typedef struct bookstruct{
    char bookname[100];
    int id;
    char author[100];
    int year;
    int month;
    int count;
    int price;
    char press[100];
    char *intro;
    struct bookstruct *next;
} Book;

int main() {
    Book *p, *bookend;
    bookend = p = (Book*)malloc(sizeof(Book));
 
    printf("bookname: ");
    fgets(p->bookname, 100, stdin);
    if (strlen(p->bookname) > 0 && p->bookname[strlen(p->bookname)-1] == '\n') {
        p->bookname[strlen(p->bookname)-1] = '\0'; // 去除输入的换行符
    }

    printf("ISDN: ");
    scanf("%d", &p->id);
    fflush(stdin); // 清空输入缓冲区

    printf("author: ");
    scanf("%s", p->author);
    fflush(stdin); // 清空输入缓冲区

    printf("bookyear: ");
    scanf("%d", &p->year);
    fflush(stdin); // 清空输入缓冲区

    printf("bookmonth: ");
    scanf("%d", &p->month);
    fflush(stdin); // 清空输入缓冲区
 
    printf("bookcount: ");
    scanf("%d", &p->count);
    fflush(stdin); // 清空输入缓冲区
 
    printf("price: ");
    scanf("%d", &p->price);
    fflush(stdin); // 清空输入缓冲区
 
    printf("press: ");
    scanf("%s", p->press);
    fflush(stdin); // 清空输入缓冲区
 
    printf("introduction: ");
    char* intro = malloc(MAX_INTRO_LEN);
    fgets(intro, MAX_INTRO_LEN, stdin);
    if (strlen(intro) > 0 && intro[strlen(intro)-1] == '\n') {
        intro[strlen(intro)-1] = '\0'; // 去除输入的换行符
    }
    p->intro = intro;
 
    bookend->next = p;
    bookend = p;
    bookend->next = NULL;

    //...
 
    return 0;
}


如果使用fgets()函数输入带空格的字符串后,程序继续执行而不等待您的输入,则可能是由于在输入其它内容时,输入缓冲区中还有残留的换行符导致的。您可以在使用fgets()函数前清空输入缓冲区;

fflush(stdin); // 清空输入缓冲区
fgets(intro, MAX_INTRO_LEN, stdin);


  • 以下回答由chatgpt基于相关博客总结生成:

    可以考虑使用fgets()函数来实现包含空格的字符串输入。具体的步骤如下:

    1. 在定义字符数组变量之后,使用fgets()函数来读入用户输入的字符串,可以将输入的字符串读入到字符数组变量中。
    char str[100];  // 定义字符数组变量
    
    fgets(str, 100, stdin);  // 使用fgets()函数来读取用户输入的字符串
    
    1. 但是需要注意输入缓冲区的大小,尽可能保证其能够容纳用户输入的字符串。在上面的代码中,输入缓冲区的大小为100。

    2. fgets()函数会读取用户输入的字符串到缓冲区中,但是会把输入的回车符也一起读取,因此需要在读取字符串后去掉最后的回车符。

    str[strlen(str) - 1] = '\0';  // 去掉字符串末尾的回车符
    
    1. 为了避免程序跳过输入语句的问题,可以在使用scanf()函数之后使用getchar()函数来吸收输入缓冲区中的回车符。
    scanf("%d", &num);  // 使用scanf()函数来读入用户输入的数字
    getchar();  // 吸收输入缓冲区中的回车符
    
    1. 确保在输入一行文本后清空输入缓冲区,以免影响下一次输入。
    fflush(stdin);  // 清空输入缓冲区
    

    完整的代码示例如下:

    #include <stdio.h>
    #include <string.h>
    
    int main()
    {
        int num;
        char str[100];
    
        printf("请输入一个数字:");
        scanf("%d", &num);
        getchar();  // 吸收输入缓冲区中的回车符
    
        printf("请输入一行文本:");
        fgets(str, 100, stdin);
        str[strlen(str) - 1] = '\0';  // 去掉字符串末尾的回车符
    
        printf("您输入的数字是:%d\n", num);
        printf("您输入的文本是:%s\n", str);
    
        fflush(stdin);  // 清空输入缓冲区
    
        return 0;
    }
    

这么改,供参考:

p = (struct bookstruct*)malloc(sizeof(struct bookstruct));
    strcpy(p->bookname, bookname);
    printf("ISDN ");//add
    scanf("%d", &p->id);
    getchar();
    printf("author: ");
    scanf("%s", p->author);
    getchar();
    printf("bookyear: ");
    scanf("%d", &p->year);
    getchar();
    printf("bookmonth: ");
    scanf("%d", &p->month);
    getchar();
    printf("bookcount: ");
    scanf("%d", &p->count);
    getchar();
    printf("price: ");
    scanf("%d", &p->price);
    getchar();
    printf("press:");
    scanf("%s", p->press);
    getchar();
    printf("introduction: ");//需要允许输入一长串英文文章(带空格的字符串)

    scanf("%[^\n]", p->intro); // 用scanf()输入带空格的字符串,直到遇到回车换行符结束

    /*三种输入方法都不行:*/
    //gets(p->intro);
    //scanf("%s", p->intro);//不允许输入空格
    //fgets(p->intro, 100, stdin);//100是char intro的长度


    bookend->next = p;
    bookend = p;
    bookend->next = NULL;