C语言scanf()函数遇到空格和换行符就结束读取的问题

目的

创建一个书类结构体,循环读取书名、作者和价格

解决scanf()跳过空白、fgets()保留换行符的问题

所以创建了一个s_gets()函数,可以读取空格分隔的一行字符

char * s_gets(char * st, int n)
{
    char * ret_val;
    char * find;
    
    ret_val = fgets(st, n, stdin);
    if (ret_val)
    {
        find = strchr(st, '\n');   // look for newline
        if (find)                  // if the address is not NULL,
            *find = '\0';          // place a null character there
        else
            while (getchar() != '\n')
                continue;          // dispose of rest of line
    }
    return ret_val;
}

第一次代码

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

char * s_gets(char * st, int n);
#define MAXTITL  41      /* maximum length of title + 1         */
#define MAXAUTL  31      /* maximum length of author's name + 1 */


struct book {            /* structure template: tag is book     */
    char title[MAXTITL];
    char author[MAXAUTL];
    float value;
};                       /* end of structure template           */

int main(void)
{
    struct book library[2]; /* declare library as a book variable  */
    
    for(int i = 0; i < 2; i ++){
	    printf("Please enter the book title.\n");
	    s_gets(library[i].title, MAXTITL); /* access to the title portion         */
	    printf("Now enter the author.\n");
	    s_gets(library[i].author, MAXAUTL);
	    printf("Now enter the value.\n");
	    scanf("%f", &library[i].value); 
    }
    
    printf("现在开始打印\n");
    
    for(int i = 0; i < 2; i ++){
    	printf("%s: \"%s\" ($%.2f)\n", library[i].author,
        library[i].title, library[i].value);
    }
    
    printf("Done.\n");
    
    return 0;
}

char * s_gets(char * st, int n)
{
    char * ret_val;
    char * find;
    
    ret_val = fgets(st, n, stdin);
    if (ret_val)
    {
        find = strchr(st, '\n');   // look for newline
        if (find)                  // if the address is not NULL,
            *find = '\0';          // place a null character there
        else
            while (getchar() != '\n')
                continue;          // dispose of rest of line
    }
    return ret_val;
}

执行效果:

在这里插入图片描述
如图所示,在第二次循环的时候,发现titleauthor同时跳了出来导致下面打印的时候title没有值

审查代码

为了保留价格的格式,所以使用了scanf()函数来获取输入,而我们在命令行界面输入1然后回车,实际传送的字符为1\n,而scanf()接受了1却会把回车符留在输入缓冲中,这就导致第二次循环时,title就把留下的回车符读入了,这也就是出现上图情况的原因

解决

清理输入行:

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

char * s_gets(char * st, int n);
#define MAXTITL  41      /* maximum length of title + 1         */
#define MAXAUTL  31      /* maximum length of author's name + 1 */

struct book {            /* structure template: tag is book     */
    char title[MAXTITL];
    char author[MAXAUTL];
    float value;
};                       /* end of structure template           */

int main(void)
{
    struct book library[2]; /* declare library as a book variable  */
    
    for(int i = 0; i < 2; i ++){
	    printf("Please enter the book title.\n");
	    s_gets(library[i].title, MAXTITL); /* access to the title portion         */
	    printf("Now enter the author.\n");
	    s_gets(library[i].author, MAXAUTL);
	    printf("Now enter the value.\n");
	    scanf("%f", &library[i].value); 
	     while (getchar() != '\n')
                continue;
    }
    
    printf("现在开始打印\n");
    
    for(int i = 0; i < 2; i ++){
	    printf("%s by %s: $%.2f\n",library[i].title,
        library[i].author, library[i].value);
    }
    
    printf("Done.\n");
    
    return 0;
}

char * s_gets(char * st, int n)
{
    char * ret_val;
    char * find;
    
    ret_val = fgets(st, n, stdin);
    if (ret_val)
    {
        find = strchr(st, '\n');   // look for newline
        if (find)                  // if the address is not NULL,
            *find = '\0';          // place a null character there
        else
            while (getchar() != '\n')
                continue;          // dispose of rest of line
    }
    return ret_val;
}

在循环中添加代码片段while (getchar() != '\n') continue;这样就把回车符给过滤掉了
在这里插入图片描述

  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值