[英]C - Ignore spaces in scanf()
我正在嘗試進行簡單的字符串獲取。 我需要的是從輸入(stdin)中寫入一個字符串,它可以包含空格,並在單詞之間沒有空格的情況下保存它。
到目前為止,我已經編寫了這個簡單的代碼,它保存了所有內容(還有空格),但我不知道如何讓scanf()
忽略空格。
int main(){
char str[10];
scanf("%[^\n]s, str);
printf("%s", str;
}
例如:
如果我的輸入是: I love C programming!
我的輸出應該是: IloveCprogramming!
我嘗試使用%*
,用於忽略字符,但沒有任何成功。
我也知道我可以“重新掃描”一次保存並刪除所有空格的字符串,但是我需要盡可能高效地進行此獲取,並且重新掃描每個字符串以刪除空格將大大增加計算時間(而不是只是掃描和忽略,其復雜度為 O(n))
您正在使用錯誤的工具來完成工作。 你需要使用getc
並執行以下操作
int ch;
char str[10];
// Loop until either loop reaches 9 (need one for null character) or EOF is reached
for (int loop = 0; loop < 9 && (ch = getc(stdin)) != EOF; ) {
if (ch != ' ' ) {
str[loop] = ch;
++loop;
}
}
str[loop] = 0;
printf("%s", str);
無需重新掃描
如果有興趣從輸入中刪除其他空格(除了' ')您還可以合並C庫函數isspace(。) ,它測試以下標准空格字符:
''(0x20)空格(SPC)
'\\ t'(0x09)水平標簽(TAB)
'\\ n'(0x0a)換行符(LF)
'\\ v'(0x0b)垂直制表符(VT)
'\\ f'(0x0c)feed(FF)
'\\ r'(0x0d)回車(CR)
此示例使用isspace(.);
合並函數isspace(.);
庫函數,並提供一種從C字符串中清除所有標准空格的方法。
int main(void)
{
char string[] = {"this contain's \n whitespace\t"};
int len = strlen(string);
char out[len+1];// +1 for null terminator
//(accommodates when input contains no whitespace)
int count = clean_whitespace(string, out);
return 0;
}
int clean_whitespace(const char *in, char *out)
{
int len, count=0, i;
if((in) && (out))
{
len = strlen(in);
for(i=0;i<len;i++)
{
if(!isspace(in[i]))
{
out[count++] = in[i];
}
}
out[count]=0;//add null terminator.
}
return count;
}
scanf()
對你的目的沒有用,實際上你甚至不需要一個緩沖區來從輸入行中去除空格:只需要一次讀取一個字節,忽略空格,輸出其他空格並停止在換行符或EOF:
#include <stdio.h>
int main(void) {
int c;
while ((c = getchar()) != EOF) {
if (c != ' ') {
putchar(c);
}
if (c == '\n') {
break;
}
}
return 0;
}
另請注意您的代碼有問題:
scanf()
格式字符串未終止 s
不正確,格式只是%[^\\n]
scanf("%9[^\\n]", str);
scanf()
的返回值,以避免在轉換失敗時將uninitialize數組傳遞給printf
,例如在空行或空文件上。 您可以使用scanf()
作為一種低效的方式來讀取字符而忽略空格,使用char c; while (scanf(" %c", &c) == 1) { putchar(c); }
char c; while (scanf(" %c", &c) == 1) { putchar(c); }
char c; while (scanf(" %c", &c) == 1) { putchar(c); }
但是你會無法檢測到行的末尾。
到目前為止,我已經編寫了這個簡單的代碼,它保存了所有內容(也是空格),但我不知道如何使
scanf()
忽略空格。
你從與大多數新C程序員相反的方向來實現這一目標。 問題通常不是使scanf
跳過空格,因為它默認為大多數類型的字段,特別是%s
字段。 空格通常被識別為字段分隔符,因此不僅跳過前導空格,而且還不在字段內讀取空格。 我認為這是因為你知道你正在使用%[
字段。
但你不能吃蛋糕也不能吃。 字段指令%[^\\n]
表示要讀取的數據由一系列非換行符組成。 scanf
將忠實地讀取所有這些字符並將它們傳輸到您指定的數組 。 您沒有選項來指示scanf
避免傳輸您告訴它屬於該字段的一些字符。
如果您想繼續使用scanf
那么您有兩個選擇:
另一個答案已經描述了如何做前者。 以下是你如何做后者:
int main(void) {
int field_count;
do {
char str[80];
char tail;
field_count = scanf("%79[^ \n]%c", str, &tail));
if (field_count == 0) {
// No string was scanned this iteration: the first available char
// was a space or newline. Consume it, then proceed appropriately.
field_count = scanf("%c", &tail);
if (field_count != 1 || tail == '\n') {
// newline, end-of-file, or error: break out of the loop
break;
} // else it's a space -- ignore it
} else if (field_count > 0) {
// A string was scanned; print it:
printf("%s", str);
if (field_count == 2) {
// A trailing character was scanned, too; take appropriate action:
if (tail == '\n') {
break;
} else if (tail != ' ') {
putchar(tail);
} // else it is a space; ignore it
}
} // else field_count == EOF
} while (field_count != EOF);
}
注意事項 :
scanf
%79[^ \\n]
指令中的79個字符(最大)字段寬度。 如果沒有字段寬度,則存在超出陣列邊界的嚴重風險(必須至少比字段長一個字符以允許字符串終止符)。 [
是字段類型,而不是限定符。 s
是一個單獨的字段類型,它也處理字符串,但具有不同的行為; 這里沒有使用s
字段。 scanf
的返回值告訴您成功掃描了多少個字段,如果在輸入和格式之間發生不匹配,或者到達輸入的結尾,或者I /,則可以少於格式字符串中描述的字段數。發生O錯誤。 需要考慮這些可能性。 %c
實際上是掃描的,它允許您確定前面的字符串字段是否結束,因為字段寬度已經耗盡而沒有到達空格或換行符,因為觀察到空格,或者因為換行符被觀測到。 每種情況都需要不同的處理。 scanf
跳過大多數字段類型的前導空格,但%[
和%c
字段是三個例外中的兩個。 ' '
); 它不會跳過其他空格字符,例如水平和垂直制表符,回車符,換頁符等。這種方法也可以適用於處理這些字符,但所提供的內容足以證明。 我發布這個來證明也可以用scanf來解決這個問題。
int main() {
char a[10];
for(int i = 0; i < 10 ; i++){
scanf("%c", &a[i]);
if( a[i] == ' ')
i--;
}
}
上面的一個只掃描10個字符,中間沒有空格。
for(int i = 0; i < 9; i++){
printf("%c,", a[i]);
}
printf("%c", a[9]);
如果你想用其他東西替換空格,這是使用的方式,例如:','
如果您希望輸入包含更多字符,只需定義一個新變量x並將10更改為x,將9更改為x-1
為了完整起見,這里有一個使用 scanf() 的簡單版本:
#include <stdio.h>
int main(void)
{
char buff[10];
int r;
r = 1;
while (r == 1) {
scanf("%*[ ]");
r = scanf("%9[^ \n]%*[ ]", buff);
if (r == 1) fputs(buff, stdout);
}
putchar('\n');
return 0;
}
這是做什么的:
scanf("%*[ ]")
:跳過初始空格,如果有的話(請求格式:非空的空格序列,不將其存儲在變量中),忽略結果。r = scanf("%9[^ \\n]%*[ ]", buff)
:讀取兩種請求的格式(解釋如下)並返回成功轉換的次數。
%9[^ \\n]
: 要求的格式:最多 9 個字符的連續文本(讀到換行符)。%*[ ]
: 請求格式:非空的空格序列,不將其存儲在變量中。if (r == 1) fputs(buff, stdout)
:檢查是否讀取了某些文本(從scanf()
成功轉換 1 次)。 如果是,輸出它。 這在循環中執行,直到無法再讀取文本切片。 或者,可以使用getchar()
讀取最終的\\n
。
示例執行:
$ ./scanstring
abcd xyz aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa wwwwwwwwwwwwwwwwwwwwwwwwwwww zzzzz 1234567891011121314 !!!
abcdxyzaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaawwwwwwwwwwwwwwwwwwwwwwwwwwwwzzzzz1234567891011121314!!!
scanf()
手冊: https : //man7.org/linux/man-pages/man3/scanf.3.html
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.