#include <stdio.h> #include <string.h> #include <strings.h> #include <stdlib.h> #include <ctype.h> char *strupr_t(char *str) { char *orign=str; for (; *str!='\0'; str++) *str = toupper(*str); return orign; } char *strlowr_t(char *str) { char *orign=str; for (; *str!='\0'; str++) *str = tolower(*str); return orign; } //字符串拷贝(strcpy, strncpy) void testStrCpy(){ char dest[1024] = {0}; char *str = "abcde"; //strcpy()函数会将源字符串中的结束符('\0')也拷贝到目的字符串中。 //注意,strcpy()可能会导致溢出。 strcpy(dest,str); printf("%s\n", dest); char dest2[7] = {0}; char *src2 = "abcde"; dest2[5] = 'A'; //该函数从源字符串中拷贝n个字符到目的字符串;如果源字符串长度不足,则用 NULL 填充,以保证将n个字符写入目的字符串中;如果源字符串中前n个字符不包含字符串结束符,函数不会为目的字符串添加上结束符。 //所以如果有需要,应该在拷贝后自己在目的字符串尾部添加结束符。 strncpy(dest2, src2, 5); printf("%s\n", dest2); } void testStrCmp() { char *s11 = "abcde"; char *s12 = "abcef"; char *s13 = "ad"; //从这个结果可以发现,strcmp()是根据字典序来对字符串进行比较的。进一步的,还可以发现strcmp()的返回值是比较过程中最后一次比较时两个字符的值的差 printf("compare(%s, %s) -> %d\n", s11, s12, strcmp(s11, s12)); printf("compare(%s, %s) -> %d\n", s12, s13, strcmp(s12, s13)); printf("compare(%s, %s) -> %d\n", s11, s13, strcmp(s11, s13)); char *s21 = "abcde"; char *s22 = "abcfg"; char *s23 = "ad"; //和strcmp()的区别是,strncmp()只对s1和s2的前n个字节进行比较。 printf("compare(%s, %s, 4) -> %d\n", s21, s22, strncmp(s21, s22, 4)); printf("compare(%s, %s, 2) -> %d\n", s21, s23, strncmp(s21, s23, 2)); printf("compare(%s, %s, 3) -> %d\n", s22, s23, strncmp(s22, s23, 3)); char *s31 = "AbcdE"; char *s32 = "abcdE"; //使用strcasecmp()应该包含 strings.h 而不是 string.h //strcasecmp()在比较时不区分大小写 //strncasecmp()之于strcasecmp()就如strncmp()之于strcmp() printf("compare(%s, %s) with case -> %d\n", s31, s32, strcmp(s31, s32)); printf("compare(%s, %s) ignore case -> %d\n", s31, s32, strcasecmp(s31, s32)); } void testStrCat() { char dest[1024] = "hello "; char *src = "world!"; //strcat()首先会覆盖掉目的字符串的结束符,然后把源字符串的内容追加到后面,并在最后添加结束符。如果目的字符串缓冲区长度不够,将导致溢出。 //strcat()在操作完成后,返回目的字符串的首地址,这样可以方便地进行链式操作。 printf("%s\n", strcat(dest, src)); char dest2[1024] = "hello "; char *src2 = "world!kkkkaaaa"; //strncat()将最多n个字节的内容追加到目的字符串尾部,并且会在追加后添加终止符号。 //同strcat()一样,它返回目的字符串的首地址。 printf("%s\n", strncat(dest2, src2,6)); } void testStrSearch() { char *s1 = "hello world!"; char c = 'l'; //strchr()返回一个字符指针,指向指定字符在指定字符串中第一次出现的位置。如果在指定字符串中没有找到指定字符,则返回 NULL 。该函数的第二个参数按理来说应当是一个字符,不过标准库中确实是int类型。 printf("%s\n", strchr(s1, c)); //strrchr()和strchr()类似,但它返回的是指定字符在指定字符串中最后一次出现的位置。如果未找到,同样返回 NULL 。 printf("%s\n", strrchr(s1, c)); //strchrnul()的功能和strchr()只有细微的区别,那就是,当没有找到指定字符时,strchrnul()不返回 NULL ,而是返回字符串结束符的位置。 //这里由于strchrnul()的特性,没办法通过打印字符串来了解strchrnul()的操作 //'strchrnull' is invalid in C99 //printf("%p, %p\n", s1, strchrnull(s1, 'f')); char *accept = "wo"; //strpbrk()和strchr()的区别在于,strchr()是从字符串里搜索 一个字符 ,而strpbrk()则是在字符串里搜索 一个字符集中的字符 ,看第二个参数就明白了。strpbrk()遍历字符串,如果发现某个字符在指定的 字符集 中,则立即返回指向该字符的指针。如果最后没有找到任何在指定字符集中的字符,则返回 NULL 。 printf("%s\n", strpbrk(s1, accept)); } void testStrSplit() { char s[1024] = "abc;lsdk:lskdj,;slsj"; char *delm = ";:,"; char *result = NULL; int len = strlen(s); int i = 0; //strtok()根据第二个参数指定的分隔符(可能存在多个不同的分隔符)将指定字符串分割成多个子串。通过多次调用strtok(),可以依次获得字符串的多个子串的首地址。要注意的是,除了第一次调用时将待分割字符串作为第一个参数,后续的调用要将第一个参数置为 NULL 。当字符串已经无法再分割时,strtok()返回 NULL 。 //除了上面说过的strtok()的用法外,还要注意的是,作为待分割的字符串,它必须是 可更改的 。否则虽然可以通过编译,但运行会出错。要理解这个现象,首先要了解strtok()的内部机制。 result = strtok(s, delm); while (result != NULL) { printf("Source:%s, Sub:%s\n", s, result); result = strtok(NULL, delm); } } /* T o b e o r n o t t o b e 84 111 32 98 101 32 111 114 32 110 111 116 32 116 111 32 98 101 84 111 0 98 101 32 111 114 32 110 111 116 32 116 111 32 98 101 84 111 0 98 101 0 111 114 32 110 111 116 32 116 111 32 98 101 84 111 0 98 101 0 111 114 0 110 111 116 32 116 111 32 98 101 84 111 0 98 101 0 111 114 0 110 111 116 0 116 111 32 98 101 84 111 0 98 101 0 111 114 0 110 111 116 0 116 111 0 98 101 84 111 0 98 101 0 111 114 0 110 111 116 0 116 111 0 98 101 可以看到,s中的分隔符,逐次地被置为'\0'即字符串结束符。这就是strtok()分割字符串的内部原理了。而strtok()返回的指针,其实就是s中各个子串的起始位置了。如果s指向的内容是无法被修改的,那么strtok()自然也就无法将原先的分隔符置为字符结束符了。 当然了,由于源字符串会被修改,在实际中,如果需要,可以用strdup()来建立一个源字符串的副本。 */ void testStrSplit2() { char s[64] = "To be or not to be"; char *delm = " "; char *result = NULL; int i =0,len = strlen(s); for (i =0;i<len;i++){ printf("%c ", s[i]); } printf("\n"); for (i=0;i<len;i++){ printf("%d ",(int)s[i]); } printf("\n"); result = strtok(s, delm); while (result != NULL){ for (i=0;i<len;i++){ printf("%d ",(int)s[i]); } printf("\n"); result = strtok(NULL, delm); } } void testStrSplit3() { char s[64] = "Hello World"; char *delm = " "; char *result = NULL, *ptr = NULL; printf("Source:%p\n", s); //char *strtok_r(char *str, const char *delim, char **saveptr); //strtok_r()是Linux下的strtok()的可重入版本(线程安全版本),它比strtok()多了一个参数 saveptr ,这个参数用于在分割字符串时保存上下文。 result = strtok_r(s, delm, &ptr); while (result != NULL){ printf("Result:%p\t", result); printf("Saveptr:%p\t", ptr); printf("---%s\t", result); printf("---%s\n", ptr); //可以看到,saveptr这个指针在每次调用strtok_r()后就指向了未分割的部分的首地址。相对地,strtok()则是在内部有一个静态缓冲区,通过这个静态缓冲区来记录未处理的起始位置,所以strtok()不是线程安全的。 result = strtok_r(NULL, delm, &ptr); } } //因为和strtok()的这个不同之处,strsep不需要区分第一次调用后后续的连续调用,可以用统一的操作来对字符串进行分割。 void testStrSplit4() { char s[64] = "To be or not to be"; char *source = s; char *delm = " "; char *result = NULL; while (source != NULL){ printf("Source: %s | ", source); result = strsep(&source,delm); printf("result: %s | ", result); } } void testStrMatch() { char *s = "To be or not to be."; char *p = "be"; //strstr()返回字符串needle在字符串haystack中第一次出现的位置;如果没有匹配,则返回 NULL 。 printf("%s\n", strstr(s, p)); } void testStrDup() { char *s = "aabbccddee"; char *dup = strdup(s); //strdup()调用malloc()分配一块内存并将字符串s的内容拷贝进去,产生s的副本。要注意的是,在最后应该调用free()来释放副本。 printf("%s\n",dup); free(dup); char *s1 = "poiuytrewq"; //strndup()和strdup()类似,但最多只拷贝s的前n个字节。如果s的长度大于n,还会在副本后添加终止符。 char *dup1 = strndup(s1, 4); printf("%s\n",dup1); free(dup1); //strdupa()和strdup()类似,但在分配内存时,它使用alloca()而不是malloc()。 //strndupa()之于strdupa()就如strndup()之于strdup(),不再赘述。 } /* 函数名: swab 功 能: 交换字节 用 法: void swab (char *from, char *to, int nbytes); */ void testStringSwab() { char source[15] = "rFna koBlrna d"; char target[15]; swab(source,target,strlen(source)); printf("%s\n",target); } /* 函数名: strupr 功 能: 将串中的小写字母转换为大写字母 用 法: char *strupr(char *str); */ void testStrUpper() { char string[100] = "abcdefghijklmnopqrstuvwxyz"; char *ptr; /* converts string to upper case characters */ ptr = strupr_t(string); printf("%s\n", ptr); } /* 函数名: strtol 功 能: 将串转换为长整数 用 法: long strtol(char *str, char **endptr, int base); */ void testStrtol() { char *string = "87654321", *endptr; long lnumber; /* strtol converts string to long integer */ lnumber = strtol(string, &endptr, 10); printf("string = %s long = %ld\n", string, lnumber); } /* 函数名: strtod 功 能: 将字符串转换为double型值 用 法: double strtod(char *str, char **endptr); */ void testStrtod() { char input[80], *endptr; double value; printf("Enter a floating point number:"); gets(input); value = strtod(input, &endptr); printf("The string is %s the number is %lf\n", input, value); } /* 函数名: strspn 功 能: 在串中查找指定字符集的子集的第一次出现 用 法: int strspn(char *str1, char *str2); */ void testStrspan() { char *string1 = "1234567890"; char *string2 = "123DC8"; int length; length = strspn(string1, string2); printf("Character where strings differ is at position %d\n", length); } /* 函数名: strset 功 能: 将一个串中的所有字符都设为指定字符 用 法: char *strset(char *str, char c); */ // void testStrset() // { // char string[10] = "123456789"; // char symbol = 'c'; // printf("Before strset(): %s\n", string); // strset(string, symbol); // printf("After strset(): %s\n", string); // } /* 函数名: strnset 功 能: 将一个串中的n个字符都设为指定字符 用 法: char *strnset(char *str, char ch, unsigned n); */ // void testStrnset() // { // char *string = "abcdefghijklmnopqrstuvwxyz"; // char letter = 'x'; // printf("string before strnset: %s\n", string); // strnset(string, letter, 13); // printf("string after strnset: %s\n", string); // } void strrev(char *head) { if (!head) return; char *tail = head; // find the 0 terminator, like head+strlen while(*tail) ++tail; // tail points to the last real char --tail; // head still points to the first for( ; head < tail; ++head, --tail) { // walk pointers inwards until they meet or cross in the middle char h = *head, t = *tail; *head = t; // swapping as we go *tail = h; } } void reverse(char s[]) { int length = strlen(s) ; int c, i, j; for (i = 0, j = length - 1; i < j; i++, j--) { c = s[i]; s[i] = s[j]; s[j] = c; } } /* 函数名: strrev 功 能: 串倒转 用 法: char *strrev(char *str); */ void testStrrev() { char forward[15] = "string"; printf("Before strrev(): %s\n", forward); strrev(forward); printf("After strrev(): %s\n", forward); reverse(forward); printf("After reverse(): %s\n", forward); } /* 函数名: strcspn 功 能: 在串中查找第一个给定字符集内容的段 用 法: int strcspn(char *str1, char *str2); */ void testStrcspn() { char *string1 = "1234567890"; char *string2 = "747DC8"; int length; length = strcspn(string1, string2); printf("Character where strings intersect is at position %d\n", length); } /* atof(将字符串转换成浮点型数) atoi(将字符串转换成整型数) atol(将字符串转换成长整型数) strtod(将字符串转换成浮点数) strtol(将字符串转换成长整型数) strtoul(将字符串转换成无符号长整型数) toascii(将整型数转换成合法的ASCII 码字符) toupper(将小写字母转换成大写字母) tolower(将大写字母转换成小写字母) atof(将字符串转换成浮点型数) */ int main(int argc, char *argv[]) { testStrCpy(); testStrCmp(); testStrCat(); testStrSearch(); testStrSplit(); testStrSplit2(); testStrSplit3(); testStrSplit4(); testStrMatch(); testStrDup(); testStrspan(); // testStrset(); // testStrnset(); testStrrev(); testStrcspn(); testStrtod(); testStrtol(); testStrUpper(); return 0; }