C語言風格字符串的概念、定義、輸入字符串、輸出字符串


字符串: C語言中最有用、最重要的數據類型之一。

字符串:是以\0字符結尾的char類型數組。所以可以把數組和指針知識應用於字符串。

如何在程序定義字符串:

1、 字符串字面量

用雙引號括起來的內容稱為字符串字面量,也叫作字符串常量。雙引號中的字符和編譯器自動加入末尾的\0字符,都作為字符串儲存在內存中。

如果要在字符串內部使用引號,必須要在雙引號前面加上一個反斜杠(\

字符串字面量被視為const,就不能更改了。

字符串常量屬於靜態存儲類別。這說明如果在函數中使用字符串常量,該字符串只會被儲存一次,在整個程序的生命期內存在,即使函數被調用多次。用雙引號括起來的內容被視為指向該字符串儲存位置的指針。

2、 字符串數組和初始化

定義字符串數組時,必須讓編譯器知道需要多少空間,一種方法是足夠空間的數組儲存字符串。

指定數組大小的時候,必須確保數組的元素個數至少比字符串長度多1

省略數組初始化聲明中的大小,編譯器會自動計算數組的大小;

 

數組表示法_創建字符串:char words[MAXLENGTH]=“I am a string in an array.”

指針表示法_創建字符串:char * pt1 = “Something is pointing at me.”

3數組和指針

數組表示法_創建字符串:char words[MAXLENGTH]=“I am a string in an array.”

              這種表示法,字符串字面量被存儲在靜態存儲區。數組只有在運行時才會被分配內存。此時,才將字符串拷貝到數組中。此時字符串有兩個副本,一個是在靜態內存中的字符串字母量,另一個是儲存在words數組中的字符串。

       指針表示法_創建字符串:char * pt1 = “Something is pointing at me.”

              編譯器為字符串在靜態存儲區預留了29個元素的空間。一旦開始運行程序,它就會為指針變量pt1留出一個儲存位置,並把字符串的地址儲存在指針變量中。

4數組和指針的區別

       char heart[] = “I love Tillie!”;  ->數組名heart是常量;

       const char *head = “I love Millie!”; ->指針名是head變量;

       head =heart ->可以;

       heart =head –>不可以,非法構造,賦值運算符左邊必須是變量

5、字符串數組

       const char *mytalents[LIM]={

    "Adding number swiftly",

    "Multiplying accurately",

    "Stashing data",

    "Following instructions to the letter",

    "Understanding the C language"

};

 

    char yourtalents[LIM][SLEN]={

    "Walking in a straight line",

    "Sleeping","Watching television",

    "Mailing letters","Reading email"

};

 

字符串數組分配內存的使用率低。因為數組中儲存着字符串字面量的副本。每個字符串都被儲存了兩次。

 

如果要使用數組表示待顯示的字符串,建議使用指針數組。指針數組也有缺陷,就是字符串字面量不能更改。如果要改變或者為字符串輸入預留空間,不要使用指向字符串字面量的指針。

++++++++++++++++++++++++++++++++++++++++++++++++++++++

字符串的輸入:

想把字符串讀入程序,首先必須預留儲存該字符串的空間。然后用輸入函數獲取該字符串。

如何分配空間:

  要做的第1件事就是分配空間。以儲存稍后讀入的字符串。意味着必須為字符串分配足夠的空間。不能指望計算機在讀取字符串時順便計算它的長度。

       char *name;

       scanf(“%s”,name);

       name是未初始化的指針,name可能指向任何地方。所以可能會擦寫掉程序中的數據或代碼,從而導致程序異常中止。

 

       最簡單的辦法:在聲明時顯式指明數組的大小。

       char name[81];

 

       現在name是一個已分配塊(81字節)的地址。還有一種辦法就是使用C庫函數來分配內存。

       

  空字符:

      用於標記C字符串末尾的字符;對應的字符ASCII編碼是0;

  空指針:

有一個值,該值不會與任何有效的地址對應。

  本質上講空字符是整數類型,占1個字節;

  空指針是指針類型,是一個地址,占4個字節。

  丟棄輸入行中余下的字符,是因為,輸入行中多出來的字符會被留在緩沖區中。成為下一次讀取語句的輸入。

  

  1、gets() 函數    這個函數不安全,被摒棄了

  scanf()和轉換說明%s只能讀取一個單詞,可是在程序中經常要讀取一整行輸入,而不僅僅是一個單詞。

很久前gets()就用於處理這種情況。gets()函數簡單易用,它讀取整行輸入,直至遇到換行符。

gets()函數有個問題,無法檢查數組是否裝得下行。數組名會被轉換成數組首元素的地址。get()函數只知道數組的開始處,並不知道數組中有多少個元素。

如果輸入字符串過長,會導致緩沖區溢出(buffer overflow)。多余的字符超出了指定的目標空間。如果這些多余的字符只是占用了尚未使用的內存,就不會立即出現問題。但是一旦擦寫掉程序中的其他數據,就會導致程序異常中止。

C99標准建議不要使用get()函數,甚至被C11標准摒棄了。

  

  2、fgets()函數

  函數原型:char *fgets(char *buf, int bufsize, FILE *stream);  ---->從指定的文件讀取一個字符串

buf 字符型指針,指向存儲讀入數據的緩沖區的地址;---->存到哪

n 從流中讀入n-1個字符;--->讀多少個

stream 指向讀取的流;   --->從哪讀                                                                                  

會在讀入的最后一個字符后加上串結束標志'\0'

返回值:讀取失敗或讀到文件結尾返回NULL;輸入成功時,返回 char 型指針,指向讀入的字符串內容,含換行鍵;

  為什么會有換行符問題:因為輸入時會敲回車嘛,就產生換行符。函數會把換行符一並存儲起來。(讀一行字符串的范疇)

  fgets()會存儲換行符,有好處也有壞處。好處就是:檢查末尾有沒有換行符就知道是否讀取了一整行。壞處就是:你可能並不想把換行符儲存在字符串中,這樣的換行符會帶來一些麻煩。

  如何處理掉換行符:在已經儲存的字符串中查找換行符,將其替換成空字符

while (words[i] != ‘\n’)

i++;

words[i]=’\0’;

  

  3、gets_s()函數

  函數原型: gets_s(words,STLEN);

        只從標准輸入中讀取數據,不需要第3個參數;

        如果讀到換行符,會丟棄它,而不是儲存它;(不存換行符)

        如果讀到最大STLEN字符數的話,.....很復雜;

        沒有fgets()函數靈活,易用;不建議用;

 

  4、s_gets()函數

函數實現如下:

 1 char * s_gets(char * st, int n)
 2 {
 3     char * ret_val;
 4     int i=0;
 5 
 6     ret_val = fgets(st, n, stdin); //讀取成功,返回一個指針,指向輸入字符串的首字符;
 7     if(ret_val)
 8     {
 9         while(st[i]!='\n' && st[i]!='\0')
10             i++;
11         if(st[i] =='\n') //fgets會把換行符也吃進來了,fgets會在末尾自動加上\0;
12             st[i]='\0';
13         else   //其實是'\0'
14             while(getchar() != '\n')  //會把緩沖區后續的字符都清空
15                 continue;
16     }
17     return ret_val;
18 }

特性:1、會吃進換行符,但是會將其替換成\0空字符;2、會把\0后續的緩沖區內容都清空,為的是不干擾下次輸入;

 

  5、scanf()函數

  函數原型:int scanf(const char * restrict format,...);

  返回一個整數值:該值等於sanf()成功讀取的項數或EOF(文件結尾)。文件結尾不存在於文件中,而僅僅是一種標志,流的狀態的標志。

scanf("%d %d",&a,&b);
函數返回值為int型。如果a和b都被成功讀入,那么scanf的返回值就是2;
如果只有a被成功讀入,返回值為1;
如果a和b都未被成功讀入,返回值為0;
如果遇到錯誤或遇到end of file,返回值為EOF。end of file為Ctrl+z 或者Ctrl+d。

++++++++++++++++++++++++++++++++++++++++++++++++++++++

字符串的輸出:

1、puts()函數

自動在字符串末尾加上換行符,\n

函數只用來輸出字符串,沒有格式控制,里面的參數可以直接是字符串或者是存放字符串的字符數組名。

2、fputs()函數

int fputs(const char *str, FILE *stream); ---->向指定的文件寫入一個字符串;

str  這是一個數組;

stream 指向FILE對象的指針,該FILE對象標識了要被寫入字符串的流。

3、printf()函數

函數的輸出格式很多,可以根據不同格式加轉義字符,達到格式化輸出。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM