字串輸入首先要考慮的是儲存位置和儲存空間大小。
例子:char *name; scanf("%s", name); 指標未初始化,可能指向記憶體中的任意地方,字串讀入的時候有可能覆蓋記憶體中的關鍵資料,造成程式或機器崩潰。
char name[81]; 這種方式顯式宣告空間並進行初始化。
scanf("%s", str)函式讀入單個word。而gets()可以讀取一整行的字串。它通過換行符讀取整行,丟棄換行符,儲存剩餘的字元,新增空字元('\0')以建立c字串。一般和puts()搭配使用。
示例:
#include#define stlem 81
int main(void)
⚠️:gets函式的問題(int puts(const char *);):雖然在定義字串的時候宣告了大小為81,但gets函式無法阻止輸入超過大小的字串長度,編譯執行時將報錯"warning: this program uses gets(), which is unsafe."
gets函式只接收乙個引數,char型別的指標。沒有其他引數限定使用者輸入的字串長度。gets()只知道陣列的開始位置,卻不知道陣列的長度。
如果輸入字串太長,則會出現緩衝區溢位,這意味著多餘的字元溢位了指定的目標。 額外的字元可能只是進入未使用的記憶體並且沒有立即出現問題,或者它們可能會覆蓋程式中的其他資料,但這些肯定不是唯一的可能性。
c99已經不建議使用該函式,並建議將gets()從標準庫中移除,c11已經將gets()從標準中移除。但c的標準只是要求編譯器廠商必須符合所要求的標準,而不是限制編譯器廠商不能做什麼。所以,主流的編譯器依然支援gets()函式已確保向後相容。
為了解決gets()函式容易引起的緩衝區溢位問題,出現了fgets()函式。char *fgets(char * __restrict, int, file *);
fgets()與gets的主要不同點為:
示例:
#include#define stlen 14
int main(void)
解讀:
其次輸入"strawberry shortcake",字串長度超過14,則僅保留13個有效當前輸入(額外乙個留給'\0')。故使用puts()時輸出"strawberry sh\0\n"('\n'為額外新增)。而使用fputs()輸出時,不會新增'\n',故直接輸出"strawberry sh",緊接著是"done."。
fgets()函式的返回值為指向char型別的指標。指標指向輸入的字串位址。但是,如果函式遇到檔案結尾,則返回乙個稱為空指標的特殊指標。這是乙個確保不指向有效資料的指標,因此它可用於指示特殊情況。在**中,該指標可以表示為數字0,或者在c中更通常的表示方法為巨集null。
由於fgets()會儲存換行符,這就帶來了一些問題。有時,你不想儲存該換行符,而僅僅將使用者輸入的換行符作為buffered i/o的乙個指令,通知臨時儲存區的資料可以被fgets()函式使用。
如何丟棄換行符?
while (words[i] != '\n')
i++;
words[i] = '\0';
words為通過fgets()得到的輸入字串,將換行符替換為'\0'。
如果想將超過陣列定義大小的剩餘字串也丟棄掉,以免作為下次的輸入,如何做到呢?
while (getchar() != '\n')
continue;
null字元或'\0',用來標記字串的結束。**為0的字元,ascii 為0的字元。
空指標或null具有與有效資料位址不對應的值。 它通常由函式使用,否則返回有效位址以指示某些特殊情況,例如遇到檔案結束或未能按預期執行。
另外,空字元是int型別,而null指標是指標型別。
c11引入了乙個新函式gets_s(),類似fgets(),但和fgets也有不同之處。
char * s_gets(char *st, int n)
}return ret_val;
}
s_gets()函式為自定義函式,可以丟棄fgets()函式保留的換行符,同時丟棄超過最大字元數的剩餘輸入。
一般我們使用scanf()函式和%s格式讀取字串。scanf()更像是讀取乙個單詞,而不是乙個字串。
示例:input statement
original input queue*
name contents
remaining quenue
scanf("%s', name);
fleebert#hup
fleebert
#hup
scanf("%5s", name);
fleebert#hup
fleeb
ert#hup
scanf("%5s", name);
ann#ular
ann#ular
『#』代表space character(/t, /b等)。
可以到,scanf會在遇到空白字元或最大字元時讀取結束,其他字元將再下次輸入時讀取。scanf的返回值為成功讀取到的字串個數。
puts()函式用來輸出字串,函式原型為int puts(const char *); 引數為乙個char型別的指標。那puts()是如何知道字串的結尾位置呢?因為字串結尾為'\0',puts()函式讀到'\0'時截止。
puts()函式會在字串末尾新增'\n'換行符,因為puts()函式讀取字串時會丟棄'\n'換行符。
fputs()是puts()函式的面向檔案的版本,原型為:int fputs(const char * __restrict, file * __restrict); 和puts()的主要區別如下:
和puts()函式類似,也是將字串位址作為函式引數。printf()函式使用起來不如puts(),但它更通用,因為它格式化各種資料型別。printf()也不會自動新增換行符。
輸入型別
引數及返回值
說明輸出型別
引數及返回值
說明int scanf(const char \* __restrict, ...)
scanf函式不會預設新增換行符,且一般用其讀入單個單詞(讀到空格字元停止)
int printf(const char \* __restrict, ...)
一般用來格式化輸出
char \*gets(char \*);
缺省會丟棄輸入的換行符。已在c11標準中移除,無法控制使用者輸入的字串長度,可能造成緩衝區溢位
int puts(const char \*);
該函式會預設新增換行符
char \*fgets(char \* __restrict, int, file \*);
引數:字串位址;字串最大長度;指向file物件的指標,該物件標識從中讀取字元的流(可為stdin)
返回值:成功時,該函式返回相同的str引數。 如果遇到檔案結尾且未讀取任何字元,則str的內容保持不變,並返回空指標。如果發生錯誤,則返回空指標
gets()函式的替代品,防止緩衝區溢位。fgets()會預設保留輸入的換行符
int fputs(const char \* __restrict, file \* __restrict)
引數:包含要寫入的以null結尾的字串行的陣列;指向file物件的指標,該物件標識要寫入字串的流(可為stdout)
返回值:返回非負值,否則在返回eof時返回錯誤。
該函式不會預設新增換行符
字串輸入輸出函式
while gets name null 可檢查檔案是否結尾 while ch getchar eof gets 讀取換行符並將其丟棄,fgets 把換行符存字串裡,但每次顯示字串會顯示換行符 不足之處 fgets 是為檔案i o而設計得,在處理鍵盤輸入時就不如gets 那麼方便。它需要第二個引數來...
字串的輸入輸出函式總結
字元資料的輸入輸出 1.putchar 函式 字元輸出函式 putchar 函式是字元輸出函式,其功能是在顯示器上輸出單個字元。其一般形式為 putchar 字元變數 2.getchar函式 鍵盤輸入函式 getchar函式的功能是從鍵盤上輸入乙個字元。其一般形式為 getchar 通常把輸入的字元...
字串和輸入輸出
一.示例程式 include include define density 62.4 int main 該程式的新特性 1.使用乙個陣列來存放字串,可以存放40個位元組,每個位元組都可以存放乙個字元值。2.使用 s轉換說明符來處理字串輸入和輸出。3.使用預處理器定義 4.使用strlen 這個函式來...