[英]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.