字符串的初始化方法
1、char str[10] = { 'H', 'e', 'l', 'l', 'o', '\0' };
2、char str[10] = "Hello";
char str[] = "linguoyuan\n";
字符串處理在程序中很常見,C庫也提供了很多字符串的處理函數,它們有一個共同特點就是都要包含頭文件string.h。
1、計算字符串長度:strlen、sizeof
頭文件:string.h
格式:strlen (字符數組名)
功能:計算字符串s的(unsigned int型)長度,不包括'\0'在內
說明:返回s的長度,不包括結束符'\0'。
與此有點類似有sizeof,但它和strlen函數不一樣,它只是一個操作符,而且sizeof()返回的是所聲明的變量的內存大小,eg:char str[10] = "lin"; strlen(str)返回3,而sizeof(str)返回的是10。
上面是對靜態數組處理的結果,如果是對指針,結果就不一樣了
char* ss = "0123456789";
sizeof(ss) 結果 4 ===》ss是指向字符串常量的字符指針,sizeof 獲得的是一個指針的之所占的空間,應該是
長整型的,所以是4
sizeof(*ss) 結果 1 ===》*ss是第一個字符其實就是獲得了字符串的第一位'0' 所占的內存空間,是char類型的,占了 1 位
strlen(ss)= 10 >>>> 如果要獲得這個字符串的長度,則一定要使用 strlen
sizeof返回對象所占用的字節大小.
strlen返回字符個數.
所以注意下面的情況:
(1)
char Array[3] = {'0'};
sizeof(Array) == 3;
char *p = Array;
sizeof(p) == 1;//sizeof(p)結果為4
在傳遞一個數組名到一個函數中時,它會完全退化為一個指針
(2)
char q[]="abc";
char p[]="a\n";
sizeof(q),sizeof(p),strlen(q),strlen(p);
結果是 4 3 3 2
2、復制字符串函數:strcpy、strncpy、memcpy、memmove
(1)原型:char *strcpy(char *dest,char *src);
頭文件:string.h
功能:把從src地址開始且含有NULL結束符的字符串賦值到以dest開始的地址空間
說明:src和dest所指內存區域不可以重疊且dest必須有足夠的空間來容納src的字符串。
返回指向dest的指針。
(2)strncpy與strcpy的不同之處就是帶一個參數指定最多拷貝多少個字節。
(3)
void *memcpy(void *dest, const void *src, size_t n);
memcpy函數從src所指的內存地址拷貝n個字節到dest所指的內存地址,和strncpy不同,memcpy並不是遇到'\0'就結束,而是一定會拷貝完n個字節。注意:src和dest所指內存區域不能重疊,函數返回指向destin的指針
void *memmove(void *dest, const void *src, size_t n);
memmove也是從src所指的內存地址拷貝n個字節到dest所指的內存地址,雖然叫move但其實也是拷貝而非移動。但是和memcpy有一點不同,memcpy的兩個參數src和dest所指的內存區間如果重疊則無法保證正確拷貝,而memmove卻可以正確拷貝。
3、比較字符串:strcmp、memcmp、strncmp
(1)strcmp
功能:比較字符串s1和s2。
原型:strcmp(const char *s1,const char * s2)
當s1<s2時,返回值<0
當s1=s2時,返回值=0
當s1>s2時,返回值>0
兩個字符串自左向右逐個字符相比(按ASCII值大小相比較),直到出現不同的字符或遇'\0'為止。
以下是一個實現strcmp的例子:
#include<stdio.h>
int mystrcpy(char s1[],char s2[])
{
int i;
for(i=0;s1[i]==s2[i];i++)
if(s1[i]=='\0')
return 0;
if(s1[i]-s2[i]>0)
return 1;
else
return -1;
}
int main(int argc,char*argv[])
{
char s1[]="linguoyuan";
char s2[]="xingwenpeng";
int i=mystrcpy(s1,s2);
printf("%d\n",i);
return 0;
}
(2)memcmp從前到后逐個比較緩沖區s1和s2的前n個字節(不管里面有沒有'\0'),如果s1和s2的前n個字節全都一樣就返回0,如果遇到不一樣的字節,s1的字節比s2小就返回負值,s1的字節比s2大就返回正值。
(3)strncmp與strcmp的唯一區別是即使兩個字符串還沒遇到'\0',比較到了n個字符,也已樣返回。
4、連接字符串:strcat、strncat
原型:
char *strcat(char *dest, const char *src);
char *strncat(char *dest, const char *src, size_t n);
返回值:dest指向哪,返回的指針就指向哪
strcat把src所指的字符串連接到dest所指的字符串后面
char d[10] = "foo";
char s[10] = "bar";
strcat(d, s);
printf("%s %s\n", d, s);
調用strcat函數后,緩沖區s的內容沒變,緩沖區d中保存着字符串"foobar",注意原來"foo"后面的'\0'被連接上來的字符串"bar"覆蓋掉了,"bar"后面的'\0'仍保留。
strcat和strcpy有同樣的問題,調用者必須確保dest緩沖區足夠大,否則會導致緩沖區溢出錯誤。strncat函數通過參數n指定一個長度,就可以避免緩沖區溢出錯誤。注意這個參數n的含義和strncpy的參數n不同,它並不是緩沖區dest的長度,而是表示最多從src緩沖區中取n個字符(不包括結尾的'\0')連接到dest后面。如果src中前n個字符沒有出現'\0',則取前n個字符再加一個'\0'連接到dest后面,所以strncat總是保證dest緩沖區以'\0'結尾,這一點又和strncpy不同,strncpy並不保證dest緩沖區以'\0'結尾。所以,提供給strncat函數的dest緩沖區的大小至少應該是strlen(dest)+n+1個字節,才能保證不溢出。(這是宋老師書的例子)。
5、搜索字符或字符串:strchr、strrchr
原型:
char *strchr(const char *s, int c);
char *strrchr(const char *s, int c);
返回值:如果找到字符c,返回字符串s中指向字符c的指針,如果找不到就返回NULL
strchr在字符串s中從前到后查找字符c,找到字符c第一次出現的位置時就返回,返回值指向這個位置,如果找不到字符c就返回NULL。strrchr和strchr類似,但是從右向左找字符c,找到字符c第一次出現的位置就返回
char *strstr(const char *haystack, const char *needle);
返回值:如果找到子串,返回值指向子串的開頭,如果找不到就返回NULL
strstr在一個長字符串中從前到后找一個子串(Substring),找到子串第一次出現的位置就返回,返回值指向子串的開頭,如果找不到就返回NULL。
6、分割字符串:strtok
char *strtok(char *str, const char *delim);
參數str是待分割的字符串,delim是分隔符
以下是一個使用strtok來一個字符串分割成整數:
#include <stdio.h>
#include <string.h>
void main(void)
{
char a[1024];
int b;
char* c;
fgets(a,sizeof(a),stdin);
b = atoi(strtok(a," "));
printf("%d\n",b);
while( (c = strtok(NULL," ")) != NULL )
{
b = atoi(c);
printf("%d\n",b);
}
}
注意:
strtok函數中有一個靜態指針變量記住上次處理到字符串中的什么位置,所以不需要每次調用時都把字符串中的當前處理位置傳給strtok。
下面是一些平時練習字符串的例子。
////////刪除字符串里的某一個字符///////////
1 #include<stdio.h>
2 void delet_char(char*str,char ch)
3 {
4 int i,j;
5 char s[3];
6 for(i=j=0;str[i];i++)
7 if(str[i]!=ch)
8 s[j++]=str[i];
9 printf("%s\n",s);
10 }
11 int main(int argc,char*argv[])
12 {
13 char ch='b';
14 char str[]="abc";
15
16 printf("%s\n",str);
17 delet_char(str,ch);
18
19 return 0;
20 }
//////////////////////////////////////////
1
2 #include<stdio.h>
3 int main(int argc,char*argv[])
4 {
5 char a,b;
6 int i=0;
7 int j;
8
9 a=getchar();
10 char buf[10];
11
12 while(a!='\n')
13 {
14 buf[i]=a;
15 a=getchar();
16 i++;
17 }
18 buf[i]='\0';
19 printf("shuru:%s\n",buf);
20
21 for(j=i-1,i=0;i<j;j--,i++)
22 {
23 b=buf[j];
24 buf[j]=buf[i];
25 buf[i]=b;
26 }
27 printf("shuchu:%s\n",buf);
28 }
//////////三種方法實現字符串復制////////////
1 #include<stdio.h>
2 #include<string.h>
3
4 int main(int argc,char*argv[])
5 {
6 char s1[]="Hello World!";
7 char s2[20];
8 int i=0;
9
10 while(s1[i])
11 s2[i++]=s1[i];
12 s2[i]='\0';
13 printf("while:%s\n",s2);
14 for(i=0;i<strlen(s1);i++)
15 s2[i]=s1[i];
16 printf("for:%s\n",s2);
17 strcpy(s2,s1);
18 printf("strcpy:%s\n",s2);
19 return 0;
20 }
/////////////////mystrncpy/////////////
1 #include<stdio.h>
2 #include<string.h>
3 #include<stdlib.h>
4 #define N 20
5 char*my_strncpy(char dest[],char src[],int count)
6 {
7 char*tmp = dest; //注意傳進來的是地址
8 if(count<=0||N<count)
9 {
10 printf("Usage count or Space not enough!\n");
11 return NULL;
12 }
13 while(count&&(*tmp = *src))
14 {
15 tmp++;
16 src++;
17 count--;
18 }
19 printf("count=%d\n",count);
20 if(count)
21 while(count)
22 {
23 printf("in while,count=%d\n",count);
24 *tmp++ = '\0';
25 count--;
26 }
27 return dest;
28 }
29
30 int main(int argc,char*argv[])
31 {
32 char dest[N] = {'\0'};
33 char src[15] = "Hello!";
34 if(argc!=2)
35 {
36 printf("You need input a number!\n");
37 return 0;
38 }
39 printf("After my_strncpy,dest=%s\n",my_strncpy(dest,src,atoi(argv[1])));
40 return 0;
41 }
////////////////將字符串中的某個字母轉化為大寫字母//////
1 #include<stdio.h>
2 #define N 20
3 int main(int argc,char*argv[])
4 {
5 char a[N]="I like this game";
6 int num=0;
7 int i;
8 for(i=0;i<N;i++)
9 if(a[i]>='a'&&a[i]<='z'&&a[i]=='g')
10 {
11 a[i]='g'-32;
12 num++;
13 }
14 if(num)
15 printf("After converse,the new string:%s\n",a);
16 else
17 printf("Has not character'e'need to converse!\n");
18 return 0;
19 }