介绍:包含string.h里面所有函数的解释;字符串比较,复制、连接、查找、分解。
1.复制相关函数:
(1)memcpy函数
void * memcpy ( void * destination, const void * source, size_t num );
介绍:从 source指针地址(源指针)复制 num 个字节到 destination指针地址(目标指针)。
源指针和目标指针指向的对象的底层类型与此函数无关;结果是数据的二进制拷贝。
该函数不检查源中的任何终止null字符—它总是复制num字节。
为了避免溢出,目标指针和源参数指向的数组的大小至少应该是num字节,并且不应该重叠(对于重叠的内存块,memmove是一种更安全的方法)。
/* memcpy example */
#include <stdio.h>
#include <string.h>
struct {
char name[40];
int age;
} person, person_copy;//person, person_copy 为结构体成员如此只有这两个可以使用这两个成员可以使用这个结构体
int main ()
{
char myname[] = "Pierre de Fermat";
/* using memcpy to copy string: */
memcpy ( person.name, myname, strlen(myname)+1 );//把myname复制给person.name
person.age = 46;
/* using memcpy to copy structure: */
memcpy ( &person_copy, &person, sizeof(person) );
printf ("person_copy: %s, %d \n", person_copy.name, person_copy.age );
return 0;
}
/* memcpy example */ #include <stdio.h> #include <string.h> using namespace std; struct Person { char name[40]; int age; };//Person为一种结构体类型 int main() { char myname[] = "Pierre de Fermat"; Person person, person_copy;//person 与 person_copy为结构体Person的实例化对象 /* using memcpy to copy string: */ memcpy(person.name, myname, strlen(myname) + 1);//把myname复制给person.name person.age = 46; /* using memcpy to copy structure: */ memcpy(&person_copy, &person, sizeof(person)); printf("person_copy: %s, %d \n", person_copy.name, person_copy.age); return 0; }
(2)memmove函数
void * memmove ( void * destination, const void * source, size_t num );
介绍:将num字节的值从source指向的位置(源指针)复制到destination指向(目标指针)的内存块。复制的过程就像使用了一个中间缓冲区一样,允许目标和源重叠。
源指针和目标指针指向的对象的底层类型与此函数无关;结果是数据的二进制拷贝。
该函数不检查源中的任何终止null字符—它总是复制num字节。
为了避免溢出,目标指针和源参数指向的数组的大小至少应该是num字节。
/* memmove example */
#include <stdio.h>
#include <string.h>
int main ()
{
char str[] = "memmove can be very useful......";
memmove (str+20,str+15,11); // 为避免溢出 str 长度至少为32 = 20+11+1
puts (str);
return 0;
}
(3)strcpy函数
char * strcpy ( char * destination, const char * source );
介绍:将源(source)指向的char字符串复制到目标(destination)指向的数组中,包括终止的空字符(并在此停止)。
为了避免溢出,目标指向的数组的大小应该足够长,以包含与源相同的char字符串(包括终止的空字符),并且不应该在内存中与源重叠。
/* strcpy example */ #include <stdio.h> #include <string.h> #include<iostream> using namespace std; int main() { char str1[] = "Sample string"; char str2[40]; char str3[40]; strcpy(str2, str1); strcpy(str3, "copy successful"); /*strcpy_s(str2, str1); strcpy_s(str3, "copy successful");*/ //调试过程中系统提示,strcopy_s 更安全 printf("str1: %s\nstr2: %s\nstr3: %s\n", str1, str2, str3); system("pause"); return 0; }strcpy_s和strcpy()函数的功能几乎是一样的。strcpy函数,就象gets函数一样,它没有方法来保证有效的缓冲区尺寸,所以它只能假定缓冲足够大来容纳要拷贝的字符串。在程序运行时,这将导致不可预料的行为。用strcpy_s就可以避免这些不可预料的行为。
这个函数用两个参数、三个参数都可以,只要可以保证缓冲区大小。
(4)strncpy函数
char * strncpy ( char * destination, const char * source, size_t num );
介绍:将源(source)的第一个长为 num 字符复制到目标(destination)。如果源char字符串的末尾(由一个空字符表示)在num字符被复制之前被发现,那么目的地将被添加0,直到数字字符被写入到它为止。(如果num大于source字符串的长度,则在超过部分添0)。
如果源长于num,则在目标的末尾不隐式添加任何空字符。因此,在这种情况下,目标不应被视为空终止的C字符串(读取该字符串时将会溢出)。
目标指针和源指针不能重叠。
/* strncpy example */
#include <stdio.h>
#include <string.h>
#include<iostream>
using namespace std;
int main()
{
char str1[] = "To be or not to be";
char str2[40];
char str3[40];
/* copy to sized buffer (overflow safe): */
strncpy(str2, str1, sizeof(str2));
/* partial copy (only 5 chars): */
strncpy(str3, str2, 5);
str3[5] = '\0'; /* null character manually added */
/* copy to sized buffer (overflow safe): */
//strncpy_s(str2, str1, sizeof(str2));
///* partial copy (only 5 chars): */
//strncpy_s(str3, str2, 5);
//str3[5] = '\0';/* null character manually added */ //调试过程提示用strncpy_s 更安全
puts(str1);
puts(str2);
puts(str3);
system("pause");
return 0;
}
使用strncpy_s, 微软做了安全检测,防止缓冲越界,与strcpy 与 strcpy_s情况差不多。
2:字符换串联,连结
(1)strcat函数
char * strcat ( char * destination, const char * source );
介绍:将源(source)字符串的副本附加到目标(destination)字符串。目标中的终止null字符由源的第一个字符覆盖,而在目标的连接中所形成的新字符串的末尾包含一个空字符。
目标指针和源指针不能重叠。
/* strcat example */
#include <stdio.h>
#include <string.h>
#include<iostream>
using namespace std;
int main()
{
char str[80];
strcpy(str, "these ");
strcat(str, "strings ");
strcat(str, "are ");
strcat(str, "concatenated.");
/*strcpy_s(str, "these ");
strcat_s(str, "strings ");
strcat_s(str, "are ");
strcat_s(str, "concatenated.");*/ //使用跟安全的函数
puts(str);
system("pause");
return 0;
}
(2)strncat函数
介绍:将源的第一个num字符附加到目标,以及一个终止的空字符。
如果源中的char字符串的长度小于num,则只复制到终止空字符之前的内容。
#include<iostream> using namespace std; /* strncat example */ #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);*/ strcpy_s(str1, "To be "); strcpy_s(str2, "or not to be"); strncat_s(str1, str2, 6); //使用安全类型 puts(str1); system("pause"); return 0; }
3.比较
(1)memcmp函数
int memcmp ( const void * ptr1, const void * ptr2, size_t num );
解释:将ptr1所指向的内存块的第一个num字节与ptr2所指向的第一个num字节进行比较,如果它们都匹配,则返回0;如果不匹配,则返回与0不同的值,表示哪个值更大。<0,表示ptr1<ptr2;>0,表示ptr1>ptr2;
与strcmp不同,函数在找到null字符后不会停止比较。
#include<iostream> using namespace std; /* memcmp example */ #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); system("pause"); return 0; }
(2)strcmp函数
int strcmp ( const char * str1, const char * str2 );
解释:比较char字符串str1和char字符串str2。
这个函数开始比较每个字符串的第一个字符。如果它们彼此相等,它将继续执行以下对,直到字符不同或到达终止的空字符为止。
这个函数执行字符的二进制比较。对于考虑特定于地区的规则的函数,请参见strcoll。
返回值:0表示str1 = str2;<0 str1<str2 ; >0 str1 > str2;
#include<iostream> using namespace std; #include <stdio.h> #include <string.h> int main() //输入apple时跳出循环 { char key[] = "apple"; char buffer[80]; do { printf("Guess my favorite fruit? "); fflush(stdout); scanf("%79s", buffer); } while (strcmp(key, buffer) != 0); puts("Correct answer!"); system("pause"); return 0; }
(3)strcoll函数
int strcoll ( const char * str1, const char * str2 );
解释:将C字符串str1与C字符串str2进行比较,两者都根据当前选择的C语言环境的LC_COLLATE类别进行适当解释。
这个函数开始比较每个字符串的第一个字符。如果它们彼此相等,则继续使用下面的一对,直到字符不同,或者直到到达表示字符串结束的空字符为止。这个函数的行为取决于所选C语言环境的LC_COLLATE类别。
(4)strncmp函数
int strncmp ( const char * str1, const char * str2, size_t num );
解释:将C字符串str1与C字符串str2的num个字符进行比较。
这个函数开始比较每个字符串的第一个字符。如果它们彼此相等,它将继续执行以下对,函数结束条件:(1)直到字符不同,(2)直到到达终止的空字符为止,(3)或者直到两个字符串中的num字符匹配为止。(无论哪个是第一个)
返回值:0表示str1 = str2;<0 str1<str2 ; >0 str1 > str2;
#include<iostream> using namespace std; /* strncmp example */ #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]); } system("pause"); return 0; }
(5)strxfrm函数
size_t strxfrm ( char * destination, const char * source, size_t num );解释:根据当前语言环境转换源指向的char字符串,并将转换后的字符串的第一个num字符串复制到目标,返回其长度。
另一种方法是,通过为目标指定一个空指针,为num指定一个零,该函数只能用于检索长度。
目标指针和源指针不能重叠。
#include<iostream> using namespace std; /* strncmp example */ #include <stdio.h> #include <string.h> int main() { char str[][5] = { "R2D2" , "C3PO" , "R2A6" }; int n; puts("Looking for R2 astromech droids..."); n = strxfrm(NULL, str[0], 0); cout << n << endl;//str[0] 的字符串长度为 n + 1 system("pause"); return 0; }
搜索:
(1)memchr函数
const void * memchr ( const void * ptr, int value, size_t num ); void * memchr ( void * ptr, int value, size_t num );
解释:在 ptr 所指向的内存块的第一个num字节中搜索第一次出现 value (被解释为无符号字符),并返回一个指向它的指针。
ptr数组上选中每个字节 和 value 都被解释为 unsigned char,来进行比较。
#include<iostream> using namespace std; /* memchr example */ #include <stdio.h> #include <string.h> int main() //寻找str中的p位置 { char * pch; char str[] = "Example string"; pch = (char*)memchr(str, 'p', strlen(str)); if (pch != NULL) printf("'p' found at position %d.\n", pch - str + 1); else printf("'p' not found.\n"); system("pause"); return 0; }
(2)strchr函数
const char * strchr ( const char * str, int character ); char * strchr ( char * str, int character );
介绍:返回:character在 str第一次出现的地方。
终止的空字符被认为是 char 字符串的一部分。 因此,它也可以被定位以检索指向字符串结尾的指针。
#include<iostream> using namespace std; /* strchr example */ #include <stdio.h> #include <string.h> int main() // 输出str中所有s的位置。 { char str[] = "This is a sample string"; char * pch; printf("Looking for the 's' character in \"%s\"...\n", str); pch = strchr(str, 's'); while (pch != NULL) { printf("found at %d\n", pch - str + 1); pch = strchr(pch + 1, 's'); } system("pause"); return 0; }
(3)strcspn函数
size_t strcspn ( const char * str1, const char * str2 );介绍:扫描str1以查找第一次出现任何字符属于str2,并返回在第一次出现之前读取的str1的字符数。
搜索包括终止空字符。 因此,如果在str1中找不到str2的任何字符,函数将返回str1的长度。
#include<iostream> using namespace std; /* strcspn example */ #include <stdio.h> #include <string.h> int main() { char str[] = "fcba73"; char keys[] = "1234567890"; int i; i = strcspn(str, keys); printf("The first number in str is at position %d.\n", i + 1); system("pause"); return 0; }
(4)strpbrk函数
const char * strpbrk ( const char * str1, const char * str2 ); char * strpbrk ( char * str1, const char * str2 );
介绍:返回str1中第一个出现在str2中的任何字符的指针,如果没有匹配(即str1中不含有str2中的任何字符),则返回空指针。
搜索不包括任何字符串的终止空字符,但在那里结束。
#include<iostream> using namespace std; /* strpbrk example */ #include <stdio.h> #include <string.h> int main() //测试str 中出现 key 中字符的情况 i i a a e i { char str[] = "This is a sample string"; char key[] = "aeiou"; char * pch; printf("Vowels in '%s': ", str); pch = strpbrk(str, key); while (pch != NULL) { printf("%c ", *pch); pch = strpbrk(pch + 1, key); } printf("\n"); system("pause"); return 0; }
(5)strrchr函数
const char * strrchr ( const char * str, int character ); char * strrchr ( char * str, int character );
介绍:返回character 在str 最后一次出现的指针。
终止空字符被认为是 char 字符串的一部分。 因此,它也可以位于检索指向字符串结尾的指针。
#include<iostream> using namespace std; /* strrchr example */ #include <stdio.h> #include <string.h> int main() //输出s在str中最后一次出现的位置 { char str[] = "This is a sample string"; char * pch; pch = strrchr(str, 's'); printf("Last occurence of 's' found at %d \n", pch - str + 1); system("pause"); return 0; }
(6)strspn函数
size_t strspn ( const char * str1, const char * str2 );
介绍:返回str2包含的字符在str1中出现过多少次。
搜索不包括任何字符串的终止空字符,但在那里结束。
#include<iostream> using namespace std; /* strspn example */ #include <stdio.h> #include <string.h> int main() { int i; char strtext[] = "129th"; char cset[] = "1234567890"; i = strspn(strtext, cset);//strtext中1 2 9来自cset printf("The initial number has %d digits.\n", i); system("pause"); return 0; }
(7)strstr函数
const char * strstr ( const char * str1, const char * str2 ); char * strstr ( char * str1, const char * str2 );
介绍:返回str1中第一次出现str2的指针,如果str2不是str1的一部分,则返回空指针。
匹配过程不包括终止空字符,但它停在那里。
#include<iostream> using namespace std; /* strstr example */ #include <stdio.h> #include <string.h> int main() //用sample 替换 simple { char str[] = "This is a simple string"; char * pch; pch = strstr(str, "simple"); strncpy(pch, "sample", 6); puts(str); system("pause"); return 0; }
(8)strtok函数
char * strtok ( char * str, const char * delimiters );
介绍:将字符串拆分为令牌,对此函数的一系列调用将str分割为令牌,这些有delimiters中的任意部分分隔成一系列令牌。
在第一次调用时,函数需要一个C字符串作为str的参数,其第一个字符用作扫描令牌的起始位置。 在随后的调用中,函数需要一个空指针,并将最后一个标记结束后的位置用作新的扫描起始位置。
为了确定一个标记的开始和结束,函数首先从delimiters中不包含的第一个字符的起始位置开始扫描(这成为标记的开始)。 然后从delimiters的第一个字符的标记开始扫描,这将成为标记的结尾。 如果找到终止空字符,扫描也会停止。
该标记的这一端自动被一个空字符替换,并且该标记的开始由该函数返回。
一旦在strtok的调用中发现了str的终止空字符,则对此函数的所有后续调用(使用空指针作为第一个参数)将返回一个空指针。
找到最后一个标记的位置由函数内部保存,以便在下次调用时使用(不需要特定的库实现来避免数据竞争)。
#include<iostream> using namespace std; /* strtok example */ #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, " ,.-"); } /*char str[] = "- This, a sample string."; // 安全类型调试 char * pch; char* buf; printf("Splitting string \"%s\" into tokens:\n", str); pch = strtok_s(str, " ,.-",&buf); printf("%s\n", pch); printf("buf %s\n", buf); while (pch != NULL) { printf("%s\n", pch); printf("buf %s\n", buf); pch = strtok_s(NULL, " ,.-", &buf); }*/ system("pause"); return 0; }
其它
(1)memset函数
void * memset ( void * ptr, int value, size_t num );解释:将由ptr指向的内存块的第一个num字节设置为指定的 value(转换为unsigned char)。
#include<iostream> using namespace std; /* memset example */ #include <stdio.h> #include <string.h> int main() { char str[] = "almost every programmer should know memset!"; memset(str, '-', 6); puts(str); int test[10]; memset(test, 56, 10 *sizeof(char) ); for (int i = 0; i < 10; i++) { cout << test[i] << endl; } system("pause"); return 0; }
测试发现memset函数用来内存块清零效果不错,统一赋值操作只适合char数组。
(2)strerror函数
char * strerror ( int errnum );
介绍:解释errnum的值,生成一个字符串,其中包含描述错误条件的消息,就像通过库函数设置为errno一样。
返回的指针指向一个静态分配的字符串,不能被程序修改。 对该函数的进一步调用可能会覆盖其内容(特定的库实现不需要避免数据竞争)。
由strerror生成的错误字符串可能特定于每个系统和库实现。
#include<iostream> using namespace std; /* strerror example : error list */ #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)); system("pause"); return 0; }
(3)strlen函数
size_t strlen ( const char * str );
介绍:返回 char 字符串str的长度。
char 字符串的长度由终止空字符确定:char 字符串的长度与字符串开头与终止空字符(不包括终止空字符本身)之间的字符数。
这不应该与包含该字符串的数组的大小相混淆。
#include<iostream> using namespace std; /* strlen example */ #include <stdio.h> #include <string.h> int main() { char szInput[256]; printf("Enter a sentence: "); gets_s(szInput); printf("The sentence entered is %u characters long.\n", (unsigned)strlen(szInput)); system("pause"); return 0; }