陕西手机网站建设公司长沙百度首页排名
初始化字符串
#include <string.h>void *memset(void *s, int c, size_t n);
返回值:s指向哪,返回的指针就指向哪
memset
函数把s
所指的内存地址开始的n
个字节都填充为c
的值。通常c
的值为0,把一块内存区清零。例如定义char buf[10];
,如果它是全局变量或静态变量,则自动初始化为0(位于.bss
段),如果它是函数的局部变量,则初值不确定,可以用memset(buf, 0, 10)
清零,由malloc
分配的内存初值也是不确定的,也可以用memset
清零。
取字符串长度
#include <string.h>size_t strlen(const char *s);
返回值:字符串的长度
strlen
函数返回s
所指的字符串的长度。该函数从s
所指的第一个字符开始找'\0'
字符,一旦找到就返回,返回的长度不包括'\0'
字符在内。例如定义char buf[] = "hello";
,则strlen(buf)
的值是5,但要注意,如果定义char buf[5] = "hello";
,则调用strlen(buf)
是危险的,会造成数组访问越界。
拷贝字符串
#include <string.h>
char *strcpy(char *dest, const char *src);
char *strncpy(char *dest, const char *src, size_t n);void *memcpy(void *dest, const void *src, size_t n);
void *memmove(void *dest, const void *src, size_t n);
返回值:dest指向哪,返回的指针就指向哪
strcpy
在拷贝字符串时会把结尾的'\0'
也拷到dest
中,因此保证了dest
中是以'\0'
结尾的字符串。但另外一个要注意的问题是,strcpy
只知道src
字符串的首地址,不知道长度,它会一直拷贝到'\0'
为止,所以dest
所指向的内存空间要足够大,否则有可能写越界。
strncpy
的参数n
指定最多从src
中拷贝n
个字节到dest
中,换句话说,如果拷贝到'\0'
就结束,如果拷贝到n
个字节还没有碰到'\0'
,那么也结束,调用者负责提供适当的n
值,以确保读写不会越界,比如让n
的值等于dest
所指向的内存空间的大小。
memcpy
函数从src
所指的内存地址拷贝n
个字节到dest
所指的内存地址,和strncpy
不同,memcpy
并不是遇到'\0'
就结束,而是一定会拷贝完n
个字节。这里的命名规律是,以str
开头的函数处理以'\0'
结尾的字符串,而以mem
开头的函数则不关心'\0'
字符,或者说这些函数并不把参数当字符串看待,因此参数的指针类型是void *
而非char *
。
memmove
也是从src
所指的内存地址拷贝n
个字节到dest
所指的内存地址,虽然叫move但其实也是拷贝而非移动。但是和memcpy
有一点不同,memcpy
的两个参数src
和dest
所指的内存区间如果重叠则无法保证正确拷贝,而memmove
却可以正确拷贝。假设定义了一个数组char buf[20] = "hello world\n";
,如果想把其中的字符串往后移动一个字节(变成"hhello world\n"
),调用memcpy(buf + 1, buf, 13)
是无法保证正确拷贝的。
连接字符串
#include <string.h>char *strcat(char *dest, const char *src);
char *strncat(char *dest, const char *src, size_t n);
返回值:dest指向哪,返回的指针就指向哪
strcat
把src
所指的字符串连接到dest
所指的字符串后面
比较字符串
#include <string.h>int memcmp(const void *s1, const void *s2, size_t n);
int strcmp(const char *s1, const char *s2);
int strncmp(const char *s1, const char *s2, size_t n);
返回值:负值表示s1小于s2,0表示s1等于s2,正值表示s1大于s2
memcmp
从前到后逐个比较缓冲区s1
和s2
的前n
个字节(不管里面有没有'\0'
),如果s1
和s2
的前n
个字节全都一样就返回0,如果遇到不一样的字节,s1
的字节比s2
小就返回负值,s1
的字节比s2
大就返回正值。
strcmp
把s1
和s2
当字符串比较,在其中一个字符串中遇到'\0'
时结束,按照上面的比较准则,"ABC"
比"abc"
小,"ABCD"
比"ABC"
大,"123A9"
比"123B2"
小。
strncmp
的比较结束条件是:要么在其中一个字符串中遇到'\0'
结束(类似于strcmp
),要么比较完n
个字符结束(类似于memcmp
)。例如,strncmp("ABCD", "ABC", 3)
的返回值是0,strncmp("ABCD", "ABC", 4)
的返回值是正值。
搜索字符串
#include <string.h>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
第一次出现的位置就返回,函数名中间多了一个字母r可以理解为Right-to-left。
#include <string.h>char *strstr(const char *haystack, const char *needle);
返回值:如果找到子串,返回值指向子串的开头,如果找不到就返回NULL
strstr
在一个长字符串中从前到后找一个子串(Substring),找到子串第一次出现的位置就返回,返回值指向子串的开头,如果找不到就返回NULL。这两个参数名很形象,在干草堆haystack
中找一根针needle
,按中文的说法叫大海捞针,显然haystack
是长字符串,needle
是要找的子串。
分割字符串
#include <string.h>char *strtok(char *str, const char *delim);
char *strtok_r(char *str, const char *delim, char **saveptr);
返回值:返回指向下一个Token的指针,如果没有下一个Token了就返回NULL
参数str
是待分割的字符串,delim
是分隔符,可以指定一个或多个分隔符,strtok
遇到其中任何一个分隔符就会分割字符串。
第一次调用要把字符串首地址传给strtok
的第一个参数,以后每次调用第一个参数只要传NULL
就可以了,strtok
函数自己会记住上次处理到字符串的什么位置(显然这是通过strtok
函数中的一个静态指针变量记住的)。
strtok_r
函数则不存在这个问题,它的内部没有静态变量,调用者需要自己分配一个指针变量来维护字符串中的当前处理位置,每次调用时把这个指针变量的地址传给strtok_r
的第三个参数,告诉strtok_r
从哪里开始处理,strtok_r
返回时再把新的处理位置写回到这个指针变量中(这是一个Value-result参数)。
char msg[80] = "0xb9:0x17//xxxx"; //分割 : //char *next, *sub_next;char *token, *sub_token;for (char *str1 = msg;; str1 = next){token = strtok_r(str1, "//", &next);printf("token=%s next=%s\n", token, next);if (next == NULL)break;if (0 == strlen(next))break;for (char *str2 = token;; str2 = sub_next){sub_token = strtok_r(str2, ":", &sub_next);printf("sub_token=%s sub_next=%s\n", sub_token, sub_next);if (sub_next == NULL)break;if (0 == strlen(sub_next))break;}}