程序按功能划分可分为数值运算、符号处理和i/o操作三类,符号处理程序占相当大的比例,符号处理程序无处不在,编译器、浏览器、office套件等程序的主要功能都是符号处理。无论多复杂的符号处理都是由各种基本的字符串操作组成的,这里简单介绍如何用c语言的库函数做字符串初始化、取长度、拷贝、连接、比较、搜索等基本操作。
#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清零.
size_t
strlen (const char *s);
返回值: 字符串的长度.
strlen函数返回s所指的字符串的长度。该函数从s所指的第一个字符开始找'\0'字符,一旦找到就返回,返回的长度不包括'\0'字符在内。例如定义char buf[] = "hello";,则strlen(buf)的值是5,但要注意,如果定义char
buf[5] = "hello";,则调用strlen(buf)是危险的,会造成数组访问越界。
strcpy和strncpy函数, memcpy和memmove函数!
strcpy和strncpy函数,拷贝以'\0'结尾的字符串,strncpy还带一个参数指定最多拷贝多少个字节,此外,strncpy并不保证缓冲区以'\0'结尾。现在介绍memcpy和memmove函数.
void *memcpy (void *dest, const void *src, size_t n);
void *memmove (void *dest, const void *src, size_t 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却可以正确拷贝.
memmove可以这样实现:
void *
memmove (void *dest, const void *src, size_t n)
{
chartemp[n];
int i;
char *d = dest;
const char *s =src;
for ( i = 0; i < n; i++ )
temp[i] = s[i];
for ( i = 0; i < n; i++)
d[i] = temp[i];
returndest;
}
借助于一个临时缓冲区temp, 即使src和dest所指的内存区间有重叠也能正确拷贝.
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' 仍保留!!
memcmp, strcmp和strncmp函数.
strchr和strnchr函数.
strstr函数.
strtok和strtok_r函数.