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