
字符串是一种重要的数据类型,但是C语言并没有显式的字符串数据类型,因为字符串以字符串常量的形式出现或者存储于字符数组中。字符串常量适用于那些程序不会对它们进行修改的字符串。所有其他字符串都必须存储于字符数组或动态分配的内存中。本文描述处理字符串和字符的库函数,以及一些相关的,具有类似能力的,既可以处理字符串也可以处理非字符串数据的函数。
传递给fputs的缓冲区必须包含一个字符串,它的字符被写入到流中,这个字符串预期以nul字节结尾,所以该函数没有一个缓冲区长度参数。所以开启压缩指针模式后,对象头的_klass域得到了压缩,居然变成了32位系统时的长度4字节了,我们都知道32位的长度最多只能表示4g的内存,那么hostspot究竟是如何处理的呢。进行字符串连接后,字符串1的结尾符将自动被去掉,在结尾串末尾保留新字符串后面一个结尾符。
头文件string.h包含了字符串函数所需的圆形和声明。在程序中包含这个头文件确实是个好主意,因为有了它所包含的原型,编译器可以更好地为程序执行错误检查。
字符串的长度是它所包含的字符个数,不包含NUL字节。我们很容易对字符进行计数来计算字符串的长度。需要说明的是,如果strlen函数的参数不是一个以NUL字节结尾的字符序列,它将继续进行查找,直到发现一个NUL字节为止,这样strlen函数的返回值将是不确定数!
库函数strlen的源码如下:
size_t strlen(char const * string)
{
int length;
for (length = 0; *string++ != '\0'; ;)
{
length += 1;
}
return length;
}
注意:
strlen返回一个类型为size_t的值,它是一个无符号整数类型。在表达式中使用无符号可能导致不可预料的结果。
例如:
if ( strlen(x) >= strlen(y) )
{
...
}
if (strlen(x) - strlen(y) >= 0)
{
...
}
上面两个表达式看似相等,但事实上它们是不想等的。第一条语句是我们所预想的那样工作,但第2条语句的结果永远为真。因为strlen的结果是无符号,所以strlen(x)-strlen(y)的结果也是个无符号数,而无符号数都是大于等于“0”的。在表达式中如果同时包含了无符号和有符号数同样会产生奇怪的结果。
譬如,你想调用user32.dll中的messagebox函数,我们必须指明函数的名字messageboxa或messageboxw,以及库名字user32.dll,我们知道win32 api对每一个涉及字符串和字符的函数一般都存在两个版本,单字节字符的ansi版本和双字节字符的unicode版本。对于某个对象,其 调用存在多态行为的某个函数时,会先通过虚表指针得到虚表.再根据函数在虚表中的偏移来得到相应的函数指针,最后才会调用函数.最后总结一下: 一个对象创建后 ,会在内存中占用一定的空间, 如果对象有虚函数调用的话(ie 中的对象基本都有 ) ,其内存块开头的 4 字节 会指向一个 叫做 虚表的东西 , 当 对象调用虚函数时 首先会 取出 虚表指针 (即 开头的 4字节) ,再到 虚表处根据所调用函数对虚表的相对偏移找到函数指针 , 最终 跳到 函数指针处执行 .。传递给fputs的缓冲区必须包含一个字符串,它的字符被写入到流中,这个字符串预期以nul字节结尾,所以该函数没有一个缓冲区长度参数。
用于复制字符串的函数是strcpy,它的原型如下:
char *strcpy( char *dst, char const *src);
这个函数把参数src字符串复制到dst参数。如果参数src和dst在内存中出现重叠,其结果是未定义的。由于dst参数将进行修改,所以它必须是个字符数组或者是一个指向动态分配内存的数组指针,不能使用字符串常量。
utf-8,是对unicode编码的压缩和优化,他不再使用最少使用2个字节,而是将所有的字符和符号进行分类:ascii码中的内容用1个字节保存、欧洲的字符用2个字节保存strchr函数,中文字符用3个字节保存...。将源串strsource添加到目标串strdestination后面, 并在得到的新串后面加上null结束符. 源串strsource的字符会覆盖目标串strdestination后面的结束符null. 在字符串的复制或添加过程中没有溢出检查, 所以要保证目标串空间足够大. 不能处理源串与目标串重叠的情况. 函数返回strdestination值.。传递给fputs的缓冲区必须包含一个字符串,它的字符被写入到流中,这个字符串预期以nul字节结尾,所以该函数没有一个缓冲区长度参数。
例如:
char message[] = "message";
...
if (...)
{
strcpy( message, "Dif");
}如果条件为真并且复制顺利执行,数组将包含下面的内容:

第一个NUL字节后面的几个字符再也无法被字符串函数访问,因此从任何角度实现看,它们都已经是丢失的了。
注意:
程序员必须保证目标字符数组的空间足以容纳需要复制的字符串。如果字符串比数组长,多余的字符仍被复制,它们将覆盖原先存储于数组后面的内存空间的值。strcpy无法解决这个问题,因为它无法判断目标字符数组的长度。
strcat函数可以实现一个字符串添加到另一个字符串的后面。函数原型如下:
当然内联函数定义也可以放在源文件中,但此时只有定义的那个源文件可以用它,而且必须为每个源文件拷贝一份定义(即每个源文件里的定义必须是完全相同的),当然即使是放在头文件中,也是对每个定义做一份拷贝,只不过是编译器替你完成这种拷贝罢了。c 当然内联函数定义也可以放在源文件中,但此时只有定义的那个源文件可以用它,而且必须为每个源文件拷贝一份定义(即每个源文件里的定义必须是完全相同的),当然即使是放在头文件中,也是对每个定义做一份拷贝,只不过是编译器替你完成这种拷贝罢了。将源串strsource开始的count个字符添加到目标串strdest后. 源串strsource的字符会覆盖目标串strdestination后面的结束符null. 如果count大于源串长度, 则会用源串的长度值替换count值. 得到的新串后面会自动加上null结束符. 与strcat函数一样, 本函数不能处理源串与目标串重叠的情况. 函数返回strdestination值.。
下面是这个函数的常见用法:
strcpy( message, "hello"); strcpy( message, customer_name);
注意:程序员必须保证目标字符数组剩余的空间足以保存整个src源字符串。
库函数strcmp的原型如下:
int strcmp( char const *s1, char const *s2);
字符串比较的规则:
(3)两串串值相等(即两串长度相等且对应位置上的字符相同)。比较字符串string1和string2大小,只比较前面count个字符. 比较过程中, 任何一个字符串的长度小于count, 则count将被较短的字符串的长度取代. 此时如果两串前面的字符都相等, 则较短的串要小.。若相等,再比较模式串的第一个字符,若第一个字符也相等,则从模式串的第二个字符开始,向右比较,直至相等或失败。
1. s1小于s2,函数返回负整数;
2. s1大于s2,函数返回正整数;
3. s1等于s2,函数返回0;
注意:比较两个字符串更好的方法是把返回值与零进行比较。
if ( 0 == strcmp(str1,str2))
{
...
}
注意:
由于strcmp并不修改它的任一个参数,所以不存在溢出字符数组的危险。strcmp函数的字符串参数也必须以一个NUL字节结尾。如果不是,strcmp就可能对参数后面的字节进行比较,这个比较结果无意义!

标准库函数还包含了一些函数,这些函数接受一个显式的长度参数,用于限定进行复制或比较的字符数。这些函数提供了一种方便的机制,可以防止难以预料的长字符串从它们的目标数组溢出。
这些函数的原型如下所示,和不受限制版本一样,如果源参数和目标参数发生重叠,strncpy和strncat的结果都是未定义。
char *strncpy(char *dst, char const *src, size_t len ); char *strncat(char *dst, char const *src, size_t len ); char *strncmp(char const *s1, char const *s2, size_t len );
和strcpy一样,strncpy把源字符串的字符复制到目标数组。但它总是向dsr写入len个字符。如果strlen(src)的值小于len,dst数组就用额外的NUL字节填充到len长度。如果strlen(src)的值大于或等于len,那么只有len个字符被复制到dst中。此时,它的结果将可能不会以NUL字节结尾。
例如:
char dst[10]; char src[] = "abcdefghijklmn"; strncpy(dst, src,5); //dst字符数组不是以NUL结尾,len是23,是个随机数 int len = strlen(dst);
警告:
strncpy调用的结果可能不是一个字符串,因此字符串必须是以NUL字节结尾。如果在一个需要字符串的地方(例如:strlen函数参数)使用了没有以NUL字节结尾的字符序列,会发生什么情况呢?strlen函数不知道NUL字节是没有的,所以它将继续一个字符一个字符的查找,知道发现NUL字节为止。或者如果函数试图访问系统分配给这个程序以,程序就会崩溃。
这个问题只有当你使用strncpy函数创建字符串,然后或者对它们使用str开头的库函数,或者在printf中使用%s格式打印它们时才会发生。考虑如下代码:
char buffer[BSIZE]; ... strncpy(buffer,name,BSIZE); buffer[BSIZE-1] = '\0';如果strlen(name)小于BSIZE,之后的赋值语句不起作用。但是,name长度很长,这条赋值语句可以保证buffer中的字符串是以NUL字节结尾。以后对这个数组使用strlen等其它函数就会正常工作。
array 字节数组分配空间时每个字符占一个字节,不够四个字符时按四字节对齐存放。该数组中因为只有ABCD四中字母,要求只遍历一次,那么反向从后往前遍历的话,每次记录每个字符出现的次数,并查看比当前字符小的字符出现多少次,即可计算出当前字符与其后面字符已有多少逆序对,以此方法累加直至第一个字符。按照以前两个字符串找两者的最长公共子串的思路类似,可以把所有串拼接到一起,这里为了避免讨论lcp跨越多个串需需要特别处理的问题用不同的字符把所有串隔开(因为char只有128位,和可能不够用,更推荐设置成某一特殊字符,在后缀数组初始化的时候在对其映射的int值做处理)。
1.4.3 strncmp
strncmp用于比较两个字符串,但它最多比较len个字节。如果两个字符串在第len个字符之前存在不等的字符,这个函数停止比较,返回结果。如果两个字符串的前len个字符相等,函数就返回零。
标准库中存在许多函数,它们用各种不同的方法查找字符串。
在一个字符串中查找一个特定字符最容易的方法是使用strchr和strchr函数,它们的原型如下:
char *strchr( char const *str, int ch); char *strrchr( char const *str, int ch);
它们的第二个参数是一个整型值。但是,它包含了一个字符值(ASCII)。strchr在字符串中str查找字符ch第1次出现的位置,找到后函数返回一个指向该位置的指针。如果该字符并不存在于字符串中,函数就返回一个NUL指针。
strrchr的功能与strchr基本一致,只是它所返回的是一个指向字符串中该字符最后一次出现的位置(r:最右边)。
例如:

char src[] = "abc12def12";
printf("the first = %s\n",strchr(src,49));//strchr(src,'1')
strprk是个更为常见的函数,它是查找任何一组字符第一次在字符串中出现的位置,它的原型如下:
char *strpbrk( char const *str, char const *group);
这个函数返回一个指向str中第1个匹配group中任何一个字符的字符位置。如果未找到函数返回一个NULL指针。例如:
char src[] = "123qaz!@#";
char group[] = "aq!";
printf("location = %s\n",strpbrk(src,group));//qaz!@#,group中的字符第1次出现的位置是q
为了在字符串中查找一个子串,我们可以使用strstr函数,它的原型如下:
char *strstr( char const *s1, char const *s2 );
查找任何一个不包含在strcharset串中的字符 (字符串结束符null除外) 在string串中首次出现的位置指针. 返回一个指针, 指向非strcharset中的字符在string中首次出现的位置.。}[/php]php strrchr() 函数定义和用法strrchr() 函数查找字符在指定字符串中从后面开始的第一次出现的位置,如果成功,则返回指向该位置的指针,如果失败,则返回 false。//函数返回一个指针,它指向字符ch 在字符串str末次出现的位置,如果匹配失败,返回null。
strspn和strcspn函数用于在字符串的起始位置对字符计数。它们的函数原型如下:
size_t strspn( char const *str, char const *group ); size_t strcspn( char const *str, char const *group );
一个字符串常常包含几个单独的部分,它们彼此分隔开来。每次为了处理这些部分,你首先必须把它们从字符串中抽取出来。这个任务正是strtok函数所实现的功能。它从字符串中隔离各个单独的称为标记(token)的部分,并丢弃分割符。它的原型如下:
char *strtok( char *str, char const *sep);
查找任何一个不包含在strcharset串中的字符 (字符串结束符null除外) 在string串中首次出现的位置指针. 返回一个指针, 指向非strcharset中的字符在string中首次出现的位置.。在开始时,指针指向第一个字符,在读入第一个字符'i'后,指针就移到下一个字符('i'后面的空格),所以getline函数从空格读起,遇到就停止,把字符串" like c++."存放到ch[0]开始的10个数组元素中,然后用"cout<
本文来自电脑杂谈,转载请注明本文网址:
https://www.pc-fly.com/a/jisuanjixue/article-118074-1.html
美国佬是想再来一轮冷战啊