5.5.1 字符數組與字符串區別
l C語言中沒有字符串這種數據類型,可以通過char的數組來替代;
l 字符串一定是一個char的數組,但char的數組未必是字符串;
l 數字0(和字符‘\0’等價)結尾的char數組就是一個字符串,但如果char數組沒有以數字0結尾,那么就不是一個字符串,只是普通字符數組,所以字符串是一種特殊的char的數組。
1 #include <stdio.h> 2 3 4 5 int main() 6 7 { 8 9 char c1[] = { 'c', ' ', 'p', 'r', 'o', 'g' }; //普通字符數組 10 11 printf("c1 = %s\n", c1); //亂碼,因為沒有’\0’結束符 12 13 14 15 //以‘\0’(‘\0’就是數字0)結尾的字符數組是字符串 16 17 char c2[] = { 'c', ' ', 'p', 'r', 'o', 'g', '\0'}; 18 19 printf("c2 = %s\n", c2); 20 21 22 23 //字符串處理以‘\0’(數字0)作為結束符,后面的'h', 'l', 'l', 'e', 'o'不會輸出 24 25 char c3[] = { 'c', ' ', 'p', 'r', 'o', 'g', '\0', 'h', 'l', 'l', 'e', 'o', '\0'}; 26 27 printf("c3 = %s\n", c3); 28 29 30 31 return 0; 32 33 } 34 35
5.5.2 字符串的初始化
1 #include <stdio.h> 2 3 4 5 // C語言沒有字符串類型,通過字符數組模擬 6 7 // C語言字符串,以字符‘\0’, 數字0 8 9 int main() 10 11 { 12 13 //不指定長度, 沒有0結束符,有多少個元素就有多長 14 15 char buf[] = { 'a', 'b', 'c' }; 16 17 printf("buf = %s\n", buf); //亂碼 18 19 20 21 //指定長度,后面沒有賦值的元素,自動補0 22 23 char buf2[100] = { 'a', 'b', 'c' }; 24 25 printf("buf2 = %s\n", buf2); 26 27 28 29 //所有元素賦值為0 30 31 char buf3[100] = { 0 }; 32 33 34 35 //char buf4[2] = { '1', '2', '3' };//數組越界 36 37 38 39 char buf5[50] = { '1', 'a', 'b', '0', '7' }; 40 41 printf("buf5 = %s\n", buf5); 42 43 44 45 char buf6[50] = { '1', 'a', 'b', 0, '7' }; 46 47 printf("buf6 = %s\n", buf6); 48 49 50 51 char buf7[50] = { '1', 'a', 'b', '\0', '7' }; 52 53 printf("buf7 = %s\n", buf7); 54 55 56 57 //使用字符串初始化,編譯器自動在后面補0,常用 58 59 char buf8[] = "agjdslgjlsdjg"; 60 61 62 63 //'\0'后面最好不要連着數字,有可能幾個數字連起來剛好是一個轉義字符 64 65 //'\ddd'八進制字義字符,'\xdd'十六進制轉移字符 66 67 // \012相當於\n 68 69 char str[] = "\012abc"; 70 71 printf("str == %s\n", str); 72 73 74 75 return 0; 76 77 }
5.5.3 字符串的輸入輸出
由於字符串采用了'\0'標志,字符串的輸入輸出將變得簡單方便。
1 #include <stdio.h> 2 3 4 5 int main() 6 7 { 8 9 char str[100]; 10 11 12 printf("input string1 : \n"); 13 14 scanf("%s", str);//scanf(“%s”,str)默認以空格分隔 15 16 printf("output:%s\n", str); 17 18 19 20 return 0; 21 22 } 23 24
5.5.4 強化訓練:字符串追加
1 #include <stdio.h> 2 3 4 5 int main() 6 7 { 8 9 char str1[] = "abcdef"; 10 11 char str2[] = "123456"; 12 13 char dst[100]; 14 15 16 17 int i = 0; 18 19 while (str1[i] != 0) 20 21 { 22 23 dst[i] = str1[i]; 24 25 i++; 26 27 } 28 29 30 31 int j = 0; 32 33 while (str2[j] != 0) 34 35 { 36 37 dst[i + j] = str2[j]; 38 39 j++; 40 41 } 42 43 dst[i + j] = 0; //字符串結束符 44 45 46 47 printf("dst = %s\n", dst); 48 49 50 51 return 0; 52 53 } 54 55
5.5.5 函數的調用:產生隨機數
當調用函數時,需要關心5要素:
l 頭文件:包含指定的頭文件
l 函數名字:函數名字必須和頭文件聲明的名字一樣
l 功能:需要知道此函數能干嘛后才調用
l 參數:參數類型要匹配
l 返回值:根據需要接收返回值
#include <time.h>
time_ttime(time_t *t);
功能:獲取當前系統時間
參數:常設置為NULL
返回值:當前系統時間, time_t 相當於long類型,單位為毫秒
#include <stdlib.h>
voidsrand(unsignedintseed);
功能:用來設置rand()產生隨機數時的隨機種子
參數:如果每次seed相等,rand()產生隨機數相等
返回值:無
#include <stdlib.h>
intrand(void);
功能:返回一個隨機數值
參數:無
返回值:隨機數
1 #include <stdio.h> 2 3 #include <time.h> 4 5 #include <stdlib.h> 6 7 8 9 int main() 10 11 { 12 13 time_t tm = time(NULL);//得到系統時間 14 15 srand((unsigned int)tm);//隨機種子只需要設置一次即可 16 17 18 19 int r = rand(); 20 21 printf("r = %d\n", r); 22 23 24 25 return 0; 26 27 } 28 29
5.5.6 字符串處理函數
1) gets()
#include <stdio.h>
char *gets(char *s);
功能:從標准輸入讀入字符,並保存到s指定的內存空間,直到出現換行符或讀到文件結尾為止。
參數:
s:字符串首地址
返回值:
成功:讀入的字符串
失敗:NULL
gets(str)與scanf(“%s”,str)的區別:
l gets(str)允許輸入的字符串含有空格
l scanf(“%s”,str)不允許含有空格
注意:由於scanf()和gets()無法知道字符串s大小,
必須遇到換行符或讀到文件結尾為止才接收輸入,因此容易導致字符數組越界(緩沖區溢出)的情況。
char str[100];
printf("請輸入str: ");
gets(str);
printf("str = %s\n", str);
2) fgets()
#include <stdio.h>
char *fgets(char *s, intsize, FILE *stream);
功能:從stream指定的文件內讀入字符,保存到s所指定的內存空間,
直到出現換行字符、讀到文件結尾或是已讀了size - 1個字符為止,最后會自動加上字符 '\0' 作為字符串結束。
參數:
s:字符串
size:指定最大讀取字符串的長度(size - 1)
stream:文件指針,如果讀鍵盤輸入的字符串,固定寫為stdin
返回值:
成功:成功讀取的字符串
讀到文件尾或出錯: NULL
fgets()在讀取一個用戶通過鍵盤輸入的字符串的時候,同時把用戶輸入的回車也做為字符串的一部分。
通過scanf和gets輸入一個字符串的時候,不包含結尾的“\n”,但通過fgets結尾多了“\n”。fgets()函數是安全的,不存在緩沖區溢出的問題。
char str[100];
printf("請輸入str: ");
fgets(str, sizeof(str), stdin);
printf("str = \"%s\"\n", str);
3) puts()
#include <stdio.h>
intputs(constchar *s);
功能:標准設備輸出s字符串,在輸出完成后自動輸出一個'\n'。
參數:
s:字符串首地址
返回值:
成功:非負數
失敗:-1
#include <stdio.h>
int main()
{
printf("hello world");
puts("hello world");
return 0;
}
4) fputs()
#include <stdio.h>
int fputs(constchar * str, FILE * stream);
功能:將str所指定的字符串寫入到stream指定的文件中, 字符串結束符 '\0' 不寫入文件。
參數:
str:字符串
stream:文件指針,如果把字符串輸出到屏幕,固定寫為stdout
返回值:
成功:0
失敗:-1
fputs()是puts()的文件操作版本,但fputs()不會自動輸出一個'\n'。
printf("hello world");
puts("hello world");
fputs("hello world", stdout);
5) strlen()
#include <string.h>
size_tstrlen(constchar *s);
功能:計算指定指定字符串s的長度,不包含字符串結束符‘\0’
參數:
s:字符串首地址
返回值:字符串s的長度,size_t為unsigned int類型
char str[] = "abcdefg";
int n = strlen(str);
printf("n = %d\n", n);
6) strcpy()
#include <string.h>
char *strcpy(char *dest, constchar *src);
功能:把src所指向的字符串復制到dest所指向的空間中,'\0'也會拷貝過去
參數:
dest:目的字符串首地址
src:源字符首地址
返回值:
成功:返回dest字符串的首地址
失敗:NULL
注意:如果參數dest所指的內存空間不夠大,可能會造成緩沖溢出的錯誤情況。
char dest[20] = "123456789";
char src[] = "hello world";
strcpy(dest, src);
printf("%s\n", dest);
7) strncpy()
#include <string.h>
char *strncpy(char *dest, constchar *src, size_tn);
功能:把src指向字符串的前n個字符復制到dest所指向的空間中,是否拷貝結束符看指定的長度是否包含'\0'。
參數:
dest:目的字符串首地址
src:源字符首地址
n:指定需要拷貝字符串個數
返回值:
成功:返回dest字符串的首地址
失敗:NULL
char dest[20] ;
char src[] = "hello world";
strncpy(dest, src, 5);
printf("%s\n", dest);
dest[5] = '\0';
printf("%s\n", dest);
8) strcat()
#include <string.h>
char *strcat(char *dest, constchar *src);
功能:將src字符串連接到dest的尾部,‘\0’也會追加過去
參數:
dest:目的字符串首地址
src:源字符首地址
返回值:
成功:返回dest字符串的首地址
失敗:NULL
char str[20] = "123";
char *src = "hello world";
printf("%s\n", strcat(str, src));
9) strncat()
#include <string.h>
char *strncat(char *dest, constchar *src, size_tn);
功能:將src字符串前n個字符連接到dest的尾部,‘\0’也會追加過去
參數:
dest:目的字符串首地址
src:源字符首地址
n:指定需要追加字符串個數
返回值:
成功:返回dest字符串的首地址
失敗:NULL
char str[20] = "123";
char *src = "hello world";
printf("%s\n", strncat(str, src, 5));
10) strcmp()
#include <string.h>
intstrcmp(constchar *s1, constchar *s2);
功能:比較 s1 和 s2 的大小,比較的是字符ASCII碼大小。
參數:
s1:字符串1首地址
s2:字符串2首地址
返回值:
相等:0
大於:>0
小於:<0
char *str1 = "hello world";
char *str2 = "hello mike";
if (strcmp(str1, str2) == 0)
{
printf("str1==str2\n");
}
else if (strcmp(str1, str2) > 0)
{
printf("str1>str2\n");
}
else
{
printf("str1<str2\n");
}
11) strncmp()
#include <string.h>
intstrncmp(constchar *s1, constchar *s2, size_tn);
功能:比較 s1 和 s2 前n個字符的大小,比較的是字符ASCII碼大小。
參數:
s1:字符串1首地址
s2:字符串2首地址
n:指定比較字符串的數量
返回值:
相等:0
大於: > 0
小於: < 0
char *str1 = "hello world";
char *str2 = "hello mike";
if (strncmp(str1, str2, 5) == 0)
{
printf("str1==str2\n");
}
else if (strcmp(str1, "hello world") > 0)
{
printf("str1>str2\n");
}
else
{
printf("str1<str2\n");
}
12) sprintf()
#include <stdio.h>
intsprintf(char *_CRT_SECURE_NO_WARNINGS, constchar *format, ...);
功能:根據參數format字符串來轉換並格式化數據,然后將結果輸出到str指定的空間中,直到出現字符串結束符 '\0' 為止。
參數:
str:字符串首地址
format:字符串格式,用法和printf()一樣
返回值:
成功:實際格式化的字符個數
失敗: - 1
char dst[100] = { 0 };
int a = 10;
char src[] = "hello world";
printf("a = %d, src = %s", a, src);
printf("\n");
int len = sprintf(dst, "a = %d, src = %s", a, src);
printf("dst = \" %s\"\n", dst);
printf("len = %d\n", len);
13) sscanf()
#include <stdio.h>
intsscanf(constchar *str, constchar *format, ...);
功能:從str指定的字符串讀取數據,並根據參數format字符串來轉換並格式化數據。
參數:
str:指定的字符串首地址
format:字符串格式,用法和scanf()一樣
返回值:
成功:參數數目,成功轉換的值的個數
失敗: - 1
char src[] = "a=10, b=20";
int a;
int b;
sscanf(src, "a=%d, b=%d", &a, &b);
printf("a:%d, b:%d\n", a, b);
14) strchr()
#include <string.h>
char *strchr(const char *s, int c);
功能:在字符串s中查找字母c出現的位置
參數:
s:字符串首地址
c:匹配字母(字符)
返回值:
成功:返回第一次出現的c地址
失敗:NULL
char src[] = "ddda123abcd";
char *p = strchr(src, 'a');
printf("p = %s\n", p);
15) strstr()
#include <string.h>
char *strstr(constchar *haystack, constchar *needle);
功能:在字符串haystack中查找字符串needle出現的位置
參數:
haystack:源字符串首地址
needle:匹配字符串首地址
返回值:
成功:返回第一次出現的needle地址
失敗:NULL
char src[] = "ddddabcd123abcd333abcd";
char *p = strstr(src, "abcd");
printf("p = %s\n", p);
16) strtok()
#include <string.h>
char *strtok(char *str, constchar *delim);
功能:來將字符串分割成一個個片段。當strtok()在參數s的字符串中發現參數delim中包含的分割字符時,
則會將該字符改為\0 字符,當連續出現多個時只替換第一個為\0。
參數:
str:指向欲分割的字符串
delim:為分割字符串中包含的所有字符
返回值:
成功:分割后字符串首地址
失敗:NULL
l 在第一次調用時:strtok()必需給予參數s字符串
l 往后的調用則將參數s設置成NULL,每次調用成功則返回指向被分割出片段的指針
char a[100] = "adc*fvcv*ebcy*hghbdfg*casdert";
char *s = strtok(a, "*");//將"*"分割的子串取出
while (s != NULL)
{
printf("%s\n", s);
s = strtok(NULL, "*");
}
17) atoi()
#include <stdlib.h>
intatoi(constchar *nptr);
功能:atoi()會掃描nptr字符串,跳過前面的空格字符,直到遇到數字或正負號才開始做轉換,
而遇到非數字或字符串結束符('\0')才結束轉換,並將結果返回返回值。
參數:
nptr:待轉換的字符串
返回值:成功轉換后整數
類似的函數有:
l atof():把一個小數形式的字符串轉化為一個浮點數。
l atol():將一個字符串轉化為long類型
char str1[] = "-10";
int num1 = atoi(str1);
printf("num1 = %d\n", num1);
char str2[] = "0.123";
double num2 = atof(str2);
printf("num2 = %lf\n", num2);