天天看点

C primer plus这本书中的自定义获取标准输入(屏幕)字符串函数s_gets函数解析以及程序清单14.2中while(getchar() != ‘\n‘)的不同用法

记在前头

···第70行–105行是对s_gets函数的解析···

···第32行–39行和93行–96行主要解释了while语句的不同用法----前者是辅助scanf函数,后者是丢弃了第n-1个字符后的多余输入,但本质上是一样的。

···c primer plus这本书多次调用这个自定义函数s_gets函数讲解知识点,其中第11章和12、13章调用时,函数有细微的改变,但是93行–96行while语句的用法是一样的·····

//* 程序清单14.2book.c -- 一本书的图书目录 */
#include <stdio.h>
#include <string.h>
#define MAXTITL 40
#define MAXAUTL 40
#define MAXBKS 100 //最多保存100本书的数据
char *s_gets(char *st, int n);

struct book
{
    char title[MAXTITL];
    char auther[MAXAUTL];
    float value;
};

int main()
{
    struct book library[MAXBKS]; //把library声明为一个book类型的数组

    int count = 0;
    int index;
    char ch;
    puts("PLease input the 1th book's title.");
    puts("And empty line to quit.");
    while (s_gets(library[count].title, MAXTITL) != NULL && count < MAXBKS && library[count].title[0] != '\0')
    {
        printf("Please enter the %dth book's auther.\n", count + 1);
        s_gets(library[count].auther, MAXAUTL);
        printf("Please enter the %dth book's value.\n", count + 1);
        scanf("%f", &library[count].value);
        count++;
        /*fun scanf遇到空格字符或换行符qian就结束,不读取这两个字符*/
        /*若输入12.50[Enter]--传送字符-->12.50\n */
        /*下面两行的意思是获取下一个字符但不保存:如不是'\n',则继续获取下一个字符但不保存;
        若是换行符,则表示此时本行输入已经全部被获取,可以再用s_get函数获取下一组信息*/
        while (getchar() != '\n')
        {
            continue;
        }

        printf("PLease input the %d book's title.\n", count + 1);
    }
    printf("Ok,Now would you want to diplay the book list?\n");
    puts("<A> Yes    <B> No");
    while ((ch = getchar()) != EOF)
    {
        if (ch == 'A')
        {
            for (index = 0; index < count; index++)
            {
                printf("%s by %s: $%.2f.\n", library[index].title, library[index].auther, library[index].value);
            }
            break;
        }
        else if (ch == 'B')
        {
            puts("Ok!Bye!");
            break;
        }
        else
        {
            puts("Please check your input code and input again.");
        }
    }

    printf("Done!");
    return 0;
}

/*这里主要解释了27行while语句存在的意义*/
/*该函数从屏幕读取n-1个字符,将其中的换行符替换为空字符,成功时返回st,失败时返回NULL指针*/
char *s_gets(char *st, int n)
{
    char *ret_val;
    char *find;
    /*fgets获取的是一行字符串,遇到换行符或读取到n-1个字符时结束读取,前者将换行符保存进字符串st,然后再保存一个空字符*/
    /*注意字符串中的空格字符不是'\0'*/
    ret_val = fgets(st, n, stdin);
    /*成功读取数据为返回str,不成功则返回NULL空指针 */
    if (ret_val != NULL)
    {
        /*str是专门搜索字符串中的字符的,遇到'\0'或者找到目标字符就会停止*/
        /*查找st所指向的字符串中的换行符'\n',返回指向该字符的指针,未找到返回NULL指针*/
        find = strchr(st, '\n');
        /*表示找到了换行符*/
        if (find != NULL)
        {
            *find = '\0';
        }
        /*else表示未找到'\n',但是已经搜寻到了字符串末尾,这是因为fgets获取了n-1个字符就结束了*/
        else
        {
            /*此时fgets获取了n-1个字符,屏幕中的输入字符没有读完故使用getchar继续读取,当读取到'\n'时表示该行输入读取完,
            目的是为了避免,接下来继续读取字符时,续接之前的输入数据,这实质上是丢弃了第n-1个字符后的多余输入,如果再次获
            取输入字符要从下一行开始*/
            /*getchar()函数是从标准输入(屏幕)读取下一个字符*/
            while (getchar() != '\n')
            {
                continue;
            }
        }
    }

    return ret_val;
}