fscanf(scanf)|fgets(fgetchar)函式對於空格和回車的不同處理
有一道程式設計如下:
#include <stdio.h>
main()
{int i,flag;
char str[80],c;
file *fp;
fp=fopen("text","w");
flag=1;
while(flag==1)
{printf("/ninput string:/n");
gets(str);
fprintf(fp,"%s",str);
printf("/ncontinue?");
c=getchar();
if((c=='n')||(c=='n'))
flag=0;
getchar(); (接收回車)
}
fclose(fp);
fp=fopen("text","r");
while(fscanf(fp,"%s",str)!=eof)
{for(i=0;str[i]!='/0';i++)
if((str[i]>='a')&&(str[i]<='z'))
str[i]-=32;
printf("/n%s/n",str);
}
fclose(fp);
}
要弄清楚這個問題,首先要對fscanf和fgets這兩個檔案函式的概念有深入的瞭解,對於字串輸入而言這兩個函式有一個典型的區別是:
fscanf讀到空格或者回車時會結束並返回,字串自動加‘/0’,但是而fgets函式則把空格作為字元接收。
有這樣一個例子:
char str[13];
scanf("%s",str);
如果輸入以下12個字元how are you?回車
實際上並不是把這12個字元加上/0送到陣列str中,而只將空格前的“how”送到str中,由於把“how”作為一個字串處理,因此在其後加/0。
當你敲回車時,實際輸入了兩個字元,回車(13)和換行(10),scanf遇到回車就返回,結果把一個換行符丟在了鍵盤緩衝裡,而getchar偏偏見了換行符就直接返回,所以沒有別的辦法,在getchar前面先把輸入緩衝清掉,即fflush(stdin),&<60; 如果對輸入流內的資料需要保留也可在scanf後面加一句getchar把換行符先讀掉,具體情況具體處理。
getchar,gets,見了換行符才返回,所以緩衝區沒有回車或者換行這樣的字元存在了,因此gets後面的getchar能得到正確的字元,實際上scanf的這種設計是存在一些問題的,所以才導致這些問題的出現。
我們可以將gets改為scanf,即:
#include <stdio.h>
main()
{int i,flag;
char str[80],c;
file *fp;
fp=fopen("text","w");
flag=1;
while(flag==1)
{printf("/ninput string:/n");
scanf("%s",str);
fprintf(fp,"%s",str);
printf("/ncontinue?");
c=getchar();
if((c=='n')||(c=='n'))
flag=0;
getchar();
}
fclose(fp);
fp=fopen("text","r");
while(fscanf(fp,"%s",str)!=eof)
{for(i=0;str[i]!='/0';i++)
if((str[i]>='a')&&(str[i]<='z'))
str[i]-=32;
printf("/n%s/n",str);
}
fclose(fp);
}
這時候我們會發現,即便我們輸入n,程式依然會進行下去,原因就是scanf遇到回車符返回了,留有換行符,而第一個getchar遇到換行符返回,讀入的資料實際上被第二個getchar所接收了,因此無法結束。
補充一個問題,如果想讓"i" "am" "a" "student"輸出在同一行上程式應該怎麼改?
答案就是:fscanf換成fgets(fp, str) 。
再舉一例getchar()函式對空格以及回車的處理:
#include<stdio.h>
#define max 1000
main()
{int c,i,flag,flag1;
char t[max];
i=0;
flag=0;
flag1=1;
printf("/nplease input a hexadecimal number:");
while((c=getchar())!='/0'&&i<max&&flag1)
{if(c>='0'&&c<='9'||c>='a'&&c<='f'||c>='a'&&c<='f')
{flag=1;
t[i++]=c;
}
else if(flag)
{t[i]='/0';
printf("/n decimal number :%d/n",htoi(t));
printf("continue? (y/n):");
c=getchar();
if(c=='n'||c=='n')flag1=0;
else
{flag=0;
i=0;
printf("/nplease input a hexadecimal number:");
}
}
}
}
htoi(s)
char s[];
{int i,n;
n=0;
for(i=0;s[i]!='/0';i++)
{if(s[i]>='0'&&s[i]<='9')n=n*16+s[i]-'0';
if(s[i]>='a'&&s[i]<='f')n=n*16+s[i]-'a'+10;
if(s[i]>='a'&&s[i]<='f')n=n*16+s[i]-'a'+10;
}
return(n);
這道程式設計表面上看起來沒什麼,實際有一些玄妙:
第一次執行:please input a hexadecimal number:
輸入:12 回車
decimal number :18
continue? (y/n):y
please input a hexadecimal number:
這時如果輸入:ac空格 回車
會出現這樣的結果:
decimal number:172
continue? (y/n):
please input a hexadecimal number:
也就是直接跳過continue? (y/n):的條件判斷了,這不得不讓人很是奇怪,怎麼會不讓我輸入“y”或“n”來判斷呢?那麼我上面輸入:12 回車,怎麼就需要判斷了呢?
其實這個問題也和上面的類似,輸入ac+空格後,getchar函式已經得到了空格,並且這個空格在隨後的語句中沒有得到處理,不同於ac已經在if語句中被處理t[i++]=c;那麼在continue? (y/n):這個條件判斷中,記憶體中還保留有空格,所以不進行輸入(y/n)判斷而直接繼續後面的語句。
同樣你輸入acz這樣的字串也不會進行判斷,這時記憶體中儲存的是z,這裡以回車和空格舉例只是為了說明兩者之間的區別。
相關推薦
fscanf(scanf)|fgets(fgetchar)函式對於空格和回車的不同處理
有一道程式設計如下: #include <stdio.h> main() {int i,flag; char str[80],c; file *fp;
replaceAll替換空格和回車
有這個一個任務,使用者在停保的時候降停保原因寫成加空格和回車的話,再次新申請審批的時候不能帶出資訊,所以要將停保原因中的回車符去掉,加了兩行程式碼: stopreason =stopAll.g
EditText禁止輸入空格和回車
EditText經常會禁止輸入一些字元,例如,不允許輸入空格,不允許回車。 1.不允許輸入空格,這裡我們採用對EditText新增輸入監聽://監聽輸入框禁止輸入空格 editText.addTextChangedListener(new TextWatcher
字串去除空格和回車
java去除字串中的空格、回車、換行符、製表符 跳至 [1] [全屏預覽] import java.util.regex.Matcher; import java.util.regex.Pat
程式設計規範之tab設定4空格和回車設定Unix(idea)
idea使用前設定好以下幾點 1.maven自動導包及倉庫位置配置檔案 2.編碼格式 3.tab**請勿勾選**Use tab character 4.空格符設定為unix格式不
轉載 -- scanf,fscanf,fgets,sscanf區別,c語言
fgets、gets、scanf函式讀入字串比較 https://blog.csdn.net/lanceleng/article/details/8730192 首先,說說這個函式的使用方法。程式碼如下: char str[10]; fgets(str, 10, std
C/C++ scanf 函式中%s 和%c 的簡單區別
首先宣告:在鍵盤中敲入字元後,字元會首先儲存在鍵盤緩衝區中供scanf函式讀取(scanf,getchar等函式是讀取緩衝區,getch函式是讀取的控制檯資訊,即為直接從鍵盤讀取)。另外特別注意鍵盤上敲入回車實際為“\r\n”,但儲存到緩衝區時候會捨棄‘\r’而只儲存\n
C語言 gets()和scanf()函式的區別
scanf( )函式和gets( )函式都可用於輸入字串,但在功能上有區別。若想從鍵盤上輸入字串"hi hello",則應該使用__gets__函式。 gets可以接收空格;而scanf遇到空格、回車和Tab鍵都會認為輸入結束,所有它不能接收空格。 char stri
【C語言天天練(十八)】字元/字串輸入函式fgetc、fgets、getc、getchar和gets
#include <stdio.h> intfgetc(FILE *stream); char *fgets(char *s, int size, FILE *stream); int getc(FILE *stream); int getchar(void);
printf和scanf的原函式
/* <pre name="code" class="cpp">函式名: scanf 功 能: 執行格式化輸入 用 法: <strong>int scanf(char *
c++ 去除字串中的空格和標點符號 (remove_if 函式的用法)
C++中提供了自動刪除空格和標點符號的函式,使用如下: #include <ctype.h> #include <algorithm> str_testing.erase(
(1)fgets函式的理解和用法
fget函式的原型如下:char *fgets(char *buf, int n, FILE *fp)功能:從檔案流讀取一行,送到緩衝區,使用時注意以下幾點:1.當遇到換行符或者緩衝區已滿,fgets就會停止,返回讀到的資料,值得注意的是不能用fgets讀二進位制檔案,因為fgets會把二進位制檔案當成文字檔
sublime text 3 顯示空格和Tab
ces space setting 希望 pytho blog csdn 顯示 img 因為sublime text3確實太好用了所以也用它寫代碼了,可是在Python3中不支持Tab鍵和空格鍵混用所以要改變顯示方式,以便方便使用,突然發現網上的資料太少,所以我把它貼了出來
Python基礎課:定義一個函數,可以對序列逆序的輸出(對於列表和元組可以不用考慮嵌套的情況)
int 情況 type spa list bsp pri not log 1 15 def fun(arg): 2 16 if type(arg) is not tuple 3 17 and type(arg) is not str 4 18
webpack vue-cli 一有空格和分號就報錯
pac async sta 報錯 函數塊 代碼 lint 函數參數 ons webpack vue-cli 一有空格和分號就報錯 eslintrc.js 這是ESLint的配置文件,至於為什麽用ESLint的話,就是為了自動檢查代碼,保持一致的代碼風格,從而保證代碼質量.
第一天,對於課程和工作的了解
family 學習 it行業 宋體 col style 感覺 喜歡 比較 今天聽這裏的老師講了很多關於it行業的事,我對於java這一方面也是比較感興趣。 對也以後的就業今天也是有了一番了解,自我感覺,我喜歡這一塊,並且有學習的想法, 我會努力的去學習這一塊,為了工
去空格和空白文本
join [] 去空格 repl ++ bsp box == 左右 //去所有空格 var str = " 3 2 4 43 "; var reg = /\s+/g; console.log(‘(‘+str.replace(reg,"")+‘)‘) //
網上整理的對於Rest和Restful api的理解
gpo 信息 常用 method 安全 什麽 獲取 正常 stat 一、什麽是Rest? REST不是"rest"這個單詞,而是幾個單詞縮寫 -- REpresentational State Transfer 直接翻譯:表現層狀態轉移,但這個翻譯正常人根本看不懂,找到的一
保留文本空格和換行
class break body 空格 wrap pre hit clas -m .content { white-space: pre-wrap; white-space: -moz-pre-wrap; white-space: -pre-wra
【sqli-labs】 less26 GET- Error based -All you SPACES and COMMENTS belong to us(GET型基於錯誤的去除了空格和註釋的註入)
src blog sci 字符 XML 包含 col concat image 看了下源碼 所有的註釋形式和反斜線,and,or都被了過濾掉了 單引號沒有過濾 空格也被過濾了 http://localhost/sqli-labs-master/Less-26/?id=