簡體   English   中英

c語言中的scanf說明

[英]Scanf clarification in c language

是否可以讀取包含空格的整個字符串,例如scanf() gets()函數?

我可以使用gets()函數來做到這一點。

char s[30];
gets(s);

這將讀取一行字符。 這可以在scanf()嗎?

您可以使用scanf()讀取一行,包括空格,但是這個函數很微妙,使用它很容易出錯。 使用%[^\\n]轉換說明符,您可以告訴scanf()匹配字符以形成字符串,不包括'\\n'字符。 如果這樣做,則應指定最大字段寬度。 此寬度指定要匹配的最大字符數,因此您必須為'\\0'終止符留出空間。

輸入流中的第一個字符可能是'\\n' 在這種情況下, scanf()將返回值0 ,因為在遇到換行符之前沒有匹配項。 但是, s不會存儲任何內容,因此您可能有未定義的行為。 為避免這種情況,您可以首先使用%*[\\n]轉換說明符調用scanf() ,丟棄任何前導'\\n'字符。

字符串被讀取后,輸入流中會有額外的字符。 至少存在一個'\\n' ,如果用戶輸入的字符超過指定的最大字段寬度,則可能還有更多字符。 然后您可能想要丟棄這些額外的字符,以便它們不會干擾進一步的輸入。 下面的代碼包含一個循環來執行此操作。

第一次調用scanf()將消耗輸入流中的所有換行符,直到遇到非換行符。 雖然我認為對scanf()的第二次調用應該總是成功的,但始終檢查scanf()的返回值(這是成功分配的次數scanf()是一種很好的做法。 我已將此值存儲在result ,並在打印字符串之前檢查它。 如果scanf()返回意外結果,則會打印錯誤消息。

使用fgets()讀取整行會更好也更容易。 您必須記住fgets()保留了尾隨換行符,因此您可能希望將其刪除。 也有可能用戶輸入的字符多於緩沖區存儲的字符數,而將剩余的字符留在輸入流中。 在提示更多輸入之前,您可能希望刪除這些額外的字符。

同樣,您應該檢查fgets()的返回值; 此函數返回指向存儲緩沖區第一個元素的指針,或在發生錯誤時返回NULL指針。 下面的代碼替換字符串中的任何尾隨換行符,丟棄輸入流中的額外字符,並僅在調用fgets()成功時才打印字符串。 否則,將打印錯誤消息。

#include <stdio.h>

int main(void)
{
    char s[30];
    int result;

    printf("Please enter a line of input:\n");
    scanf("%*[\n]");                // throw away leading '\n' if present
    result = scanf("%29[^\n]", s);  // match up to 29 characters, excluding '\n'

    /* Clear extra characters from input stream */
    int c;
    while ((c = getchar()) != '\n' && c != EOF)
        continue;                   // discard extra characters

    if (result == 1) {
        puts(s);
    } else {
        fprintf(stderr, "EOF reached or error in scanf()\n");
    }

    printf("Please enter a line of input:\n");    
    char *ps = fgets(s, 30, stdin); // keeps '\n' character

    if (ps) {
        while (*ps && *ps != '\n') {
            ++ps;
        }
        if (*ps) {                  // replace '\n' with '\0'
            *ps = '\0';
        } else {
            while ((c = getchar()) != '\n' && c != EOF)
                continue;           // discard extra characters
        }

        puts(s);

    } else {
        fprintf(stderr, "EOF reached or error in fgets()\n");
    }

    return 0;
}

請注意,這兩種獲取輸入行的方法並不完全等效。 此處所寫的scanf()方法不接受空行(即僅由'\\n'字符組成的行),但接受由其他空白字符組成的行。 fscanf()方法將接受一個空行作為輸入。

此外,如果忽略前導空格字符是可以接受的,那么遵循 Jonathan Leffler 在評論中給出的建議只使用一次scanf()調用會更簡單:

result = scanf(" %29[^\n]", s);

這將忽略前導空白字符,包括換行符。

不要使用scanf()gets()函數 — 使用fgets()代替。 但是對於上面的問題,請找到答案。

int main() {
    char a[30];
    scanf ("%29[^\n]%*c", name);
    printf("%s\n", a);
    return 0;
}

它也強烈推薦,就像我在開始時所說的那樣使用fgets()代替。 我們顯然不理解奇怪的要求。 我會使用fgets()來讀取字符。

fgets(a, size(a), stdin);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM