**引言:如果想把一個字符串讀到程序中,必須首先預留存儲字符串的空間,然后使用輸入函數來獲取這個字符串。**
**讀取字符串輸入的第一件事是建立一個空間以存放讀入的字符串。**
char *name;
scanf("%s", name);
這段代碼雖然可能通過編譯,但因為name可以指向任何地方,所以它的輸入值可能覆蓋以前name所指位置的值。
解決辦法是聲明一個固定大小的字符數組,或者使用C庫里的分配存儲空間的函數。
1、gets函數從系統標準輸入獲得一個字符串,讀取字符串直到遇到一個換行符(\n),它讀取換行符之前的所有字符,在這些字符后添加一個空字符(\0),然后把這個字符串交給調用它的程序。它把讀取的換行符直接丟棄,而不是把它放入字符串中,這與下面討論的fgets函數不同,下面再給出例子證明這一點。
~~~
#include <stdio.h>
char *gets(char *s);
~~~
**示例:**
~~~
#include <stdio.h>
#define MAX 18
int
main(int argc, char **argv)
{
char name[MAX];
char *ptr;
printf("what't your name?\n");
ptr = gets(name); /*注意:gets()返回的指針與傳遞給它的是同一個指針*/
printf("%s? Ah ! %s\n", ptr, name);
return 0;
}
~~~
**注意,如果gets出錯時它返回一個空地址,因此在使用時一般使用如下技巧:**
~~~
while((ptr = gets(name)) != NULL){
……
}
~~~
2、gets函數的一個不足是它不檢查預留存儲區是否能夠容納實際輸入的數據。多出來的字符簡單地溢出到相鄰的內存區。fgets()函數改進了這個問題。它可以指定最大讀入字符數。fgets()和gets()有3點不同:
a、它需要第二個參數來說明組大讀入字符數。如果這個參數值為n,fgets()就會讀取最多n-1個字符或者讀完一個換行符為止。
b、如果fgets讀取到換行符,就會把它存放在字符串里,而不是像gets()那樣丟棄它。也就是說它在字符串的最后存放的是換行符(\n),而不是空字符(\0)。
c、它還需要第三個參數來說明讀哪一個文件。
~~~
#include <stdio.h>
char *fgets(char *s, int size, FILE *strem);
~~~
**示例**
~~~
#include <stdio.h>
#define MAX 18
int
main(int argc, char **argv)
{
char name[MAX];
char *ptr;
printf("what't your name?\n");
ptr = fgets(name, MAX, stdin);
printf("%s? Ah ! %s\n", ptr, name);
return 0;
}
~~~
**編譯測試結果顯示:**
~~~
what't your name?
libing
libing
? Ah ! libing
~~~
它顯示了fgets()的一個不足之處,fgets()把換行符存儲到字符串里了,這樣每次顯示字符串時就會顯示換行符。
下面對fgets()和gets()兩個函數對于換行符不同處理的示例證明:
~~~
#include <stdio.h>
#define MAX 18
int
main(int argc, char **argv)
{
char name1[MAX];
char name2[MAX];
char *ptr;
printf("what't your name?\n");
ptr = fgets(name1, MAX, stdin);
ptr = gets(name2);
if(strcmp(name1, name2)){<span style="white-space:pre"> </span>/*比較兩個字符串,因為gets會在最后將\n改為\0存入字符串,而fgets會直接將\n存入字符串*/
printf("name1 is not equal name2\n");
}
return 0;
}
~~~
3、scanf()和gets()主要的差別在于它們如果決定字符串何時結束。scanf()更給予獲取單詞而不是獲取字符串;而gets()函數,會讀取所有的字符,直到遇到第一個換行符為止。scanf()使用兩種方法決定輸入結束,如果使用%s格式,字符串讀到下一個空白字符。如果指定了字段寬度,比如%10s,scanf()就會讀入10個字符或直到遇到第一個空白字符,由二者中最先滿足的哪一個終止輸入。
~~~
#include <stdio.h>
int
main(void)
{
char name1[11], name2[11];
int count;
while(1){
printf("please input 2 names.\n");
count = scanf("%5s %10s", name1, name2);
printf("I read the %d names %s and %s.\n"
,count, name1, name2);
}
return 0;
}
~~~
**運行執行測試:**
~~~
please input 2 names.
Jesse Jukes
I read the 2 names Jesse and Jukes.
please input 2 names.
Liza Applebottham
I read the 2 names Liza and Applebotth.
please input 2 names.
Portensia Callowit
I read the 2 names am and Portensia.
please input 2 names.
I read the 2 names Callo and wit.
~~~
- 前言
- (四)回調函數
- (一)while(1)死循環與for(;;)死循環的區別
- (二)static關鍵字
- (三)函數
- (四)可變參數函數
- (五)setjmp和longjmp
- (六)指針
- (七)回調函數
- (八)字符串
- (九)動態內存分配
- (十)結構體
- (十一)深入理解指針
- (十二)命令行參數
- (十三)printf、fprintf、sprintf和snprintf函數
- (十四)const關鍵字詳解
- (十五)字符串輸入函數fgets、gets和scanf
- (十六)字符串輸出函數puts、fputs和printf
- (十七)字符/字符串輸出函數fputc、fputs、putc、putchar和puts
- (十八)字符/字符串輸入函數fgetc、fgets、getc、getchar和gets
- (十九)restrict關鍵詞
- (二十)scanf函數詳解
- (二一)內聯函數
- (二二)位操作
- (二三)errno變量
- (二四)內存分配