c语言字符串详细
1.字符串字面量。
"Candy \nIs dandy \nBut liquor \nIs quicker."
在c++中叫字符串字面值.可以在字符串內embed轉移序列,例如'\n'
謹慎在字符串中embed八進制和hex轉移序列,八進制轉移序列以/開始,十六進制轉移序列以/x(x必須小寫)開始,八進制轉移序列在三個數字(必須0~7范圍內)之后結束或者以第一個非八進制以內的數字結束(數字大于等于8就結束)。
十六進制/x后面沒有限制,以第一個非十六進制數字(大于f)結束。注意十六進制的數字大小寫均可(從編譯器運行結果得到)。例如看下面代碼:
#include <stdio.h> int main() { if(('\xAA') == ('\xaa'))printf("equal"); else printf("not equal.");return 0; }運行結果是:
equal2.延續字符串字面值。
(1)方法1:采用 \
例如?? "i am a student?? \
?? and you are a teacher. "
特點:第一行以\(不包含)處結束,第二行以行首開始。
(2)方法2:當兩條或者多條字符串相鄰時候,c語言會自動合并字符串。利用這個規律可以這樣書寫
"i am a student? "
" and you are a teacher. "
最后編譯器會自己把字符串合并成。"i am a student?? and you are a teacher. "
3.字符串字面量的存儲。c語言把字符串字面量當成字符數組來存儲的。當c語言遇到長度為n的字符串,那么它會為字符串字面量分配長度n+1的內存空間,末尾加'\0'。注意:這里不要混淆'\0'、'0'、'? ',空字符的碼值為0,而'0'的碼值(ASCII)為48,空格'? ' ASCll碼值是32。切記,如果字符數組默認初始化,那么就是' \0'.
字符數組默認初始化時候,每個字符也是賦值'\0'而不是空格鍵,算術類型數組初始化每個數字都是0.
空字符串是"",空字符串作為單獨的一個空字符存儲,'\0'
字符串字面之是當成數組來存儲的,所以字符串字面之會被當成是指針(數組名字會被當成指針).例如,printf("abcde");那么會傳遞給printf函數字符串"abcde"的地址(即指向字符a的內存單元的指針).
4.字符串字面值會被當成是指針。
例如 "abc"
printf("abc");這里“abc”會被當成是指針,指向字母a的內存單元。
printf 和scanf 都接受char *類型作為他的第一個參數。
5.字符串字面值的操作。
(1)字符串字面值不能更改。看下面的代碼:
#include <stdio.h> int main() { char *str = "abcde"; *str = 'a'; printf("%s",str);return 0; }運行結果發生運行時錯誤:
r@r:~/coml_/c/13/2$ gcc 3.c -o 123 r@r:~/coml_/c/13/2$ ./123 Segmentation fault (core dumped) r@r:~/coml_/c/13/2$結論:不能更改字符串字面值的內容。但是可以使char *對象指向別的字符串,例如,
#include <stdio.h> int main() { char *str = "abcde"; printf("%s\n",str); //str 重新指向另一個字符串字面量 str = "efghikasdfasd fasdf asdf asdf asf"; printf("%s",str); return 0;運行結果如下:
abcde efghikasdfasd fasdf asdf asdf asfr意外的地方:還能超過原來字符串的長度。
(2)一半情況下,可以在需要char *的任何地方使用字符串字面值。
例如,char *p;
p = "abc";這個操作不是拷貝字符串,是把字符a的地址賦值給p,也就是說指針變量p的賦值過程,而不是字符串整體的賦值過程。
(3)指針有下標操作,字符串字面值也有
"abc"[1],指的是字符b
如下函數,把整數轉換成十六進制字符的形式。
char number_to_hex(int n) { return "0123456789ABCDEF" }(4)這里注意十六進制和八進制數和轉移序列是不一樣的
????????? (a)十六進制數的定義\x00(x大寫小寫都可以,數字部分沒有長度要求),八進制數的定義,\012(數字0開頭就是八進制數,\0后面的數字也沒有長度限制)
???????? (b)十六進制轉義序列必須\x開頭(x必須小寫,而且后面數字部分最多2位從0~ff),八進制轉移序列\開頭,后面數字最多3位,看下面的圖也能復習下
6.字符串字面值和字符常量不能互換,看下面的代碼:
#include <stdio.h> int main() { printf("\n"); printf('\n'); //這里引發錯誤return 0; }gcc編譯器編譯結果如下:
r@r:~/coml_/c/13/2$ gcc 4.c -o 123 4.c: In function ‘main’: 4.c:5:8: warning: passing argument 1 of ‘printf’ makes pointer from integer without a cast [-Wint-conversion]5 | printf('\n');| ^~~~| || int In file included from 4.c:1: /usr/include/stdio.h:332:43: note: expected ‘const char * restrict’ but argument is of type ‘int’332 | extern int printf (const char *__restrict __format, ...);| ~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~ 4.c:5:1: warning: format not a string literal and no format arguments [-Wformat-security]5 | printf('\n');7.字符串變量。注意必須以“\0”結尾,否則庫函數調用它會出現未定義的行為。
#include <stdio.h> #define STR_LEN 20 int main() { //方法1:直接定義成字符數組+初始化 char str[STR_LEN + 1] = "you are welcome."; //方法2:直接定義為char * + 初始化 char * str1 = "you are welcome."; //方法3:先定義一個字符數組,和一個char *,把char *對象指向一個char 數組 char str2[STR_LEN + 1],*str3; str3 = str2; //方法4:先定義一個char *,后來可以指向一個字符串字面值 char *ptr; ptr = "you are welcome"; puts(ptr);return 0; }但是如果要使用scanf讀入char*,則必須先開辟足夠空間,也就是,必須先聲明為 char [STR_LEN + 1]類型,而不能申明為char *類型。
char *p;? //僅僅給指針p開辟了足夠存放一個指針的空間.而不能給字符串分配空間。如果利用p讀入,會引發錯誤:
#include <stdio.h> int main() { char *p; scanf("%s",p); printf("%s",p);return 0; }運行結果如下:按照要求輸入了? you aresdf后,輸出確是null
you arasdf (null)8.初始化字符串變量
c語言處理數組初始化式的時候,當數組初始化式被數組本身短的時候,余下的數組元素會被初始化為0(元素是int,float,double的情況),char 數組遵守同樣的規則,會以'\0'補充。
不論給char *,或者給char []類型賦值(值類型是字符串字面量),那么都會自動在結束時候以'\0'補充
#include <stdio.h> int main() { double d[12] = {0.0}; int i; for(i = 0; i!= 12; ++i) { printf("%f\n",d[i]); }return 0; } ~運行結果如下:
0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.0000009.字符數組和字符指針
相同點:任何接受字符數組或者字符指針的地方,這兩個都可以作實際參數。
不同點:
(1)字符數組可以修改某個字符的值,而字符指針不能修改字符串字面值。
(2)字符數組的名字是數組名,而字符指針是變量,可以在執行的時候指向其他字符串。
例如,char *p,這里p是一個指針變量,指向char對象。p的值是可以改變的,僅僅如此(p指向的對象的不能改變,區分*p = ...(不合法), 和p = ...(合法))
char *p;
p = "abcde";//合法,這里更改的是p的值。p是一個變量,當然可以更改了。
*p = "efghi";//不合法,這里要改變p指向的那個字符串字面量,會報錯。
?
10.字符串的讀寫
(1)讀
利用scanf或者fget();
特點:會忽略開始的后面的一切空白,例如輸入?? a?? bc def,那么會忽略開始的空格,最后把a讀入,后面的一些在內存中緩存,等待后續需要讀入的時候。
(2)寫
???????????????? printf("")會嚴格一個一個地輸出,直到遇到第一個'\0'為止,如果字符串末尾沒有'\0',會繼續寫出,直到遇到內存中的第一個'\0'為止。
??????????????? puts(),會在行末直接加一個'\n'(自動換行)
(3)自己編寫讀取字符串函數要解決的問題如下
?? (a)什么時候開始讀取(是否忽略開始的空白字符)(b)怎么結束’\n’,空格還是某個字符,結束字符是否要寫入字符串? (c)如果讀取的字符串太長,那么多余的字符直接忽,還是把它留給下一次的輸入操作。
例如,不忽略換行符,在第一個換行符結束,且換行符不存在字符串中,則如下編寫,代碼中的函數read():
#include <stdio.h> #define LEN 20 int read(char str[],int n); void print(char str[],int n); int main() { char array[LEN + 1] = {' '}; read(array,LEN); print(array,LEN+1);return 0; } int read(char str[],int n) { char ch; char *p = str; int i = 0; while((ch = getchar()) != '\n') {if(i < n){ *p ++ = ch;i++;} } *p = '\0'; return i;} void print(char str[],int n) { int i = 0; for(i = 0; i!= n; ++i){printf("%c",str[i]);} }?????????????????? 函數read()也可以如下簡單的編寫:
int read(char str[],int n) {int i = 0; char ch;while((ch = getchar()) != '\n'){if(i < n)str[i ++] = ch;}str[i] = '\0'; //terminates stringreturn i; //number of characters stored }scanf函數和gets函數會在末尾自動加空字符,然而,自己編寫函數要自己添加空字符。
?
?
?
?
?
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
- 上一篇: c语言指针输出两个数的最大值和最小值,并
- 下一篇: XHTML行内描述性元素(持续更新中)