前言
C语言对字符和字符串的使用极其频繁,C语言有字符类型但没有字符串类型,通常将字符串放在常量字符串和字符数组中,通常引用字符串函数来处理字符串的相关操作。
一、函数介绍
1.1 strlen
size_t strlen ( const char * str );
字符串长度函数,字符串以'\0'作为结束标志,strlen计算不包括‘\0’的字符串长度(或者说字符串中字符的个数),函数的返回值为无符号数。不能通过长度相减的正负来判断字符串的长短。
示例
#include <stdio.h> #include <string.h> int main () { char szInput[256]; printf ("请输入一个字符串: "); gets (szInput); printf ("字符串长度(单位为元素长度)为 %u。\n",(unsigned)strlen(szInput)); return 0; }
输出
请输入一个字符串: just testing
字符串长度(单位为元素长度)为 12 。
1.2 strcpy
char* strcpy ( char * destination , const char * source);
字符串 复制函数,原字符串必须以 '\0' 结束,函数会将原字符串的‘\0’拷贝到目标字符串变量中,目标字符串变量的空间要足够大,目标字符串变量空间可以变化。
示例
#include <stdio.h> #include <string.h> int main () { char str1[]="Sample string"; char str2[40]; char str3[40]; strcpy (str2,str1); strcpy (str3,"copy successful"); printf ("str1: %s\nstr2: %s\nstr3: %s\n",str1,str2,str3); return 0; }
输出:
str1: Sample string
str2: Sample string
str3: copy successful
1.3 strcat
char * strcat ( char * destination , const char * source );
字符串连接函数,目标字符串中的'\0'被 原字符串的第一个字符覆盖,并且在 目标字符串中由两者串联形成的新字符串的末尾包含一个‘\0’,目标字符串变量空间足够大且可以改变。
示例
#include <stdio.h> #include <string.h> int main () { char str[80]; strcpy (str,"these "); strcat (str,"strings "); strcat (str,"are "); strcat (str,"concatenated."); puts (str); return 0; }
输出
these strings are concatenated.
1.4 strcmp
int strcmp ( const char * str1 , const char * str2 );
字符串比较函数,此函数开始比较每个字符串的第一个字符。如果它们彼此相等,则继续以下对,直到字符不同或达到‘\0’。
返回值 | 说明 |
<0 | 第一个不匹配的字符在 str1 中的值低于 str2 中的值 |
0 | 两个字符串的内容相等 |
>0 | 第一个不匹配的字符在 PTR1 中的值大于在 PTR2 中的值 |
示例
#include <stdio.h> #include <string.h> int main () { char key[] = "apple"; char buffer[80]; do { printf ("Guess my favorite fruit? \n"); scanf ("%79s",buffer); } while (strcmp (key,buffer) != 0); puts ("Correct answer!"); return 0; }
输出
Guess my favourite fruit?
orange
Guess my favourite fruit?
apple
Correct answer!
1.5 strncpy
char * strncpy ( char * destination , const char * source , size_t num );
从字符串中复制字符函数, 从原字符串的第一个字符开始拷贝num个字符到目标字符串变量中,如果原字符串的长度小于num,则拷贝完原字符串之后,在目标字符串的后边追加 0 ,直到 num个, 如果原字符串长度超过 num,则不会在目标字符串末尾隐式附加‘\0’。
示例
#include <stdio.h> #include <string.h> int main () { char str1[]= "To be or not to be"; char str2[40]; char str3[40]; strncpy ( str2, str1, sizeof(str2) ); strncpy ( str3, str2, 5 ); str3[5] = '\0'; puts (str1); puts (str2); puts (str3); return 0; }
输出
To be or not to be
To be or not to be
To be
1.6 strncat
char * strncat ( char * destination , const char * source , size_t num );
从字符串追加字符函数,将原字符串的第一个数字字符追加到目标字符串,外加一个‘\0’。如果原字符串的长度小于 num,则只有复制‘\0’之前的内容。
示例
#include <stdio.h> #include <string.h> int main () { char str1[20]; char str2[20]; strcpy (str1,"To be "); strcpy (str2,"or not to be"); strncat (str1, str2, 6); puts (str1); return 0; }
输出
To be or not
1.7 strncmp
int strncmp ( const char * str1 , const char * str2 , size_t num );
比较两个字符串中的字符函数,此函数开始比较每个字符串的第一个字符。如果它们彼此相等,则继续使用以下对,直到字符不同,直到达到终止的空字符,或者直到两个字符串中的 num 字符匹配,以先发生者为准。
返回值 | 说明 |
<0 | 第一个不匹配的字符在 str1 中的值低于 str2 中的值 |
0 | 两个字符串的内容相等 |
>0 | 第一个不匹配的字符在 str1 中的值大于在 str2 中的值 |
示例
#include <stdio.h> #include <string.h> int main () { char str [][ 5 ] = { "R2D2" , "C3PO" , "R2A6" }; int n ; puts ( "Looking for R2 astromech droids..." ); for ( n = 0 ; n < 3 ; n ++ ) if ( strncmp ( str [ n ], "R2xx" , 2 ) == 0 ) { printf ( "found %s\n" , str [ n ]); } return 0 ; }
输出
Looking for R2 astromech droids...
found R2D2
found R2A6
1.8 strstr
char * strstr ( const char * str1 , const char * str2 );
查找子字符串函数, 如果 str2 不是str1,返回指向 str2 中第一次出现的 str1 的指针或者说返回str1中第一次出现str2的首地址,如果 str2 不是 str1 的一部分,则返回一个空指针。
示例
#include <stdio.h> #include <string.h> int main () { char str [] = "This is a simple string" ; char * pch ; pch = strstr ( str , "simple" ); strncpy ( pch , "sample" , 6 ); puts ( str ); return 0 ; }
输出
This is a sample string
1.9 strtok
char * strtok ( char * str , const char * sep );
- sep参数是个字符串,定义了用作分隔符的字符集合 。
- 第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标记。
- strtok函数找到str中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针。(注:strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时 拷贝的内容并且可修改。)
- strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置。
- strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标记。
- 如果字符串中不存在更多的标记,则返回 NULL 指针。
示例
#include <stdio.h> #include <string.h> int main () { char str [] = "- This, a sample string." ; char * pch ; printf ( "Splitting string \"%s\" into tokens:\n" , str ); pch = strtok ( str , " ,.-" ); while ( pch != NULL ) { printf ( "%s\n" , pch ); pch = strtok ( NULL , " ,.-" ); } return 0 ; }
输出
Splitting string "- This, a sample string." into tokens:
This
a
sample
string
1.10 strerror
char * strerror ( int errnum );
函数用来获取指向错误消息字符串的指针
示例
#include <stdio.h> #include <string.h> #include <errno.h> // 必须包含的头文件 int main () { FILE * pFile; pFile = fopen ("unexist.ent","r"); if ( pFile == NULL ) printf ( "Error opening file unexist.ent: %s\n" , strerror ( errno )); //errno: Last error number return 0 ; }
输出
Error opening file unexist.ent: No such file or directory
1.11 memcpy
void * memcpy ( void * destination , const void * source , size_t num );
复制内存块函数 memcpy 从 source 的位置开始向后复制 num 个字节的数据到 destination的内存位置。 这个函数在遇到 '\0' 的时候并不会停下来。如果 source 和 destination 有任何的重叠,复制的结果都是未定义的, memcpy用于不重叠的内存拷贝 。
示例
#include <stdio.h> #include <string.h> struct { char name [ 40 ]; int age ; } person , person_copy ; int main () { char myname [] = "Pierre de Fermat" ; memcpy ( person . name , myname , strlen ( myname ) + 1 ); person . age = 46 ; memcpy ( & person_copy , & person , sizeof ( person ) ); printf ( "person_copy: %s, %d \n" , person_copy . name , person_copy . age ); r eturn 0 ; }
输出
person_copy: Pierre de Fermat, 46
1.12 memmove
void * memmove ( void * destination , const void * source , size_t num );
移动内存块函数memmove 和memcpy的差别就是memmove函数处理的原内存块和目标内存块是可以重叠的。如果原空间和目标空间出现重叠,就得使用memmove函数处理。
示例
#include <stdio.h> #include <string.h> int main () { char str [] = "memmove can be very useful......" ; memmove ( str + 20 , str + 15 , 11 ); puts ( str ); return 0 ; }
输出
memmove can be very very useful.
1.13 memcmp
int memcmp ( const void * ptr1 , const void * ptr2 , size_t num );
比较两个内存块函数将ptr1指向的内存块的前num字节数与 ptr2 指向 的第一个字节 数进行比较。
返回值 | 说明 |
< | 两个内存块中不匹配的第一个字节在 ptr1 中的值低于 ptr2 中的值(如果评估为无符号字符值) |
=0 | 两个内存块的内容相等 |
>0 | 两个内存块中不匹配的第一个字节在 ptr1 中的值大于在 ptr2 中的值(如果评估为无符号字符值) |
#include <stdio.h> #include <string.h> int main () { char buffer1 [] = "DWgaOtP12df0" ; char buffer2 [] = "DWGAOTP12DF0" ; int n ; n = memcmp ( buffer1 , buffer2 , sizeof ( buffer1 ) ); if ( n > 0 ) printf ( "'%s' is greater than '%s'.\n" , buffer1 , buffer2 ); else if ( n < 0 ) printf ( "'%s' is less than '%s'.\n" , buffer1 , buffer2 ); else printf ( "'%s' is the same as '%s'.\n" , buffer1 , buffer2 ); return 0 ; }
输出
'DWgaOtP12df0' is greater than 'DWGAOTP12DF0'.
额外介绍一个函数memset,void* memset(void*dest ,vallue,num),将dest中前num个字节的值设为value。
示例
#include<stdio.h> #include<string.h> int main() { char str[] = "hello world!"; memset(str + 1, 'A', 4); puts(str); return 0; }
hAAAA world!