天天看點

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;
}