字符串、字符和字节

字符串基础

字符串就是一串零个或多个字符,并且以一个位模式为全0的NUL字节结尾。

字符串长度就是字符串中字符数。

size_t strlen( char const *string );

string为指针常量(const修饰string),指向的string是常量不能修改。size_t是无符号数,定义在stddef.h。

#include <stddef.h>
size_t strlen( char const *string ){
   int length;
   for( length = 0;*string++!= '\0';)
     length += 1;
    return length;
}

C语言遍历字符串: while(*string++!='\0'){}

if(strlen(x)>=strlen(y))
if(strlen(x)-strlen(y)>=0)

上面两句不等价,第二个恒真,无符合数-无符合数还是无符合数,恒大于0。尽量不重写库函数,把时间花在程序其他部分的算法改进上,寻找一种更好的算法比改良一种差劲的算法更有效率,复用已经存在的软件比重新开发一个效率更高。

不受限制的字符串函数

"不受限制的字符串函数"指那些在处理字符串时不会自动检查目标缓冲区大小的函数。

这类函数通常依赖于字符串中的终止符( '\0')来确定字符串的结束位置,如strcpy, strcat等。

复制字符串
char *strcpy( char *dst, char const *src);

函数把参数 src 字符串复制到 dst 参数。如果参数 src和 dst在内存中出现重叠,结果是未定义的。由于 dst 参数将进行修改,所以它必须是个字符数组或者是一个指向动态分配内存的数组的指针,不能使用字符串常量。目标参数的以前内容将被覆盖并丢失。由于新字符串是以 NUL字节结尾,所以老字符串最后剩余的几个字符也会被有效地删除。

char message[] ="Original message"; 
if(... ) strcpy(message,"Different");

message是字符数组。

C和指针:字符串_字符串

strcpy不能保证dst空间足够拷贝字符串。

char message[] = "Original message";
strcpy(message,"A different message");

第2个字符串太长了,无法容纳于message 字符数组中。strcpy 函数将侵占数组后面的部分内存空间,改写原先恰好存储在那里的变量。

连接字符串
char *strcat( char *dst, char const *src);

strcat 函数要求 dst 参数原先已经包含了一个字符串(可以是空字符串)。它找到这个字符串的末尾,并把 src字符串的一份拷贝添加到这个位置。如果src和 dst的位置发生重叠,其结果是未定义的。

strcpy(message,"Hello");
strcat(message,customer_name);
strcat(message,",how are you?" );

保证目标字符数组剩余的空间足以保存整个源字符串。

strcpy 和 strcat都返回它们第1个参数的一份拷贝,就是一个指向目标字符数组的指针。

字符串比较

比较两个字符串涉及对两个字符串对应的字符逐个进行比较,直到发现不匹配为止。那个最先

不匹配的字符中较“小”(字符集中的序数较小)的那个字符所在的字符串被认为“小

于”另外一个字符串。如果其中一个字符串是另外一个字符串的前面一部分,那么它也被认为“小

于”另外一个字符串,因为它的NUL结尾字节出现得更早(词典比较)。

int strcmp( char const *s1,char const *s2);

如果s1小于s2,strcmp 函数返回一个小于零的值。如果s1大于s2,函数返回一个大于零的值。

如果两个字符串相等,函数就返回零。

长度受限的字符串函数

这些函数接受一个显式的长度参数,用于限定进行复制或比较的字符数,防止长字符串从它们的目标数组溢出。

char *strncpy( char *dst, char const *src, size_t len);
char *strncat( char *dst, char const *src, size_t len);
int strncmp( char const *s1,char const *s2,size_t len);

如果源参数和目标参数发生重叠,strncpy 和 strncat的结果就是未定义。

和 strcpy 一样,strncpy 把源字符串的字符复制到目标数组。它总是正好向 dst写入 len个字符,如果strlen(src)的值小于len,dst数组就用额外的NUL字节填充len长度。如果 strlen(src)大于等于 len,只有len个字符被复制到dst中,结果不以 NUL字节结尾。

char buffer[BSIZE];
strncpy(buffer, name, BSIZE );
buffer[BSIZE-1]='\0';

在字符串最后手动添上'\0'。

  • strncat 总是在结果字符串后面添加一个NUL字节。
  • strncmp也用于比较两个字符串,但它最多比较 len个字节。如果两个字符串在第 len个字符之前存在不相等的字符,这个函数就像 strcmp 一样停止比较,返回结果。

字符串查找基础

查找一个字符

字符串中查找一个特定的字符

char* strchr( char const *str, int ch);
char* strrchr( char const *str, int ch );

strchr在字符串 str 中查找字符ch第1次出现的位置,找到后函数返回一个指向该位置的指针。如果该字符并不存在于字符串中,函数就返回一个NULL指针。

strrchr返回一个指向字符串中该字符最后一次出现的位置(最右边那个)。

查找任何几个字符
char *strpbrk( char const *str,char const *group);

返回一个指向 str 中第1个匹配group 中任何一个字符的字符位置。如果未找到匹配,函数返回一个NULL指针。 (任何几个:只要找到一个字符在group中即可)

查找一个子串
char *strstr( char const *s1, char const *s2 );

在s1中查找整个s2第1次出现的起始位置,并返回一个指向该位置的指针。如果s2并没有完整地出现在s1的任何地方,函数将返回一个NULL指针。如果第2个参数是一个空字符串,函数就返回s1。

高级字符串查找

strspn和 strcspn函数用于在字符串的起始位置对字符计数。

查找一个字符串前缀
size_t strspn( char const *str, char const *group);
size_t strcspn( char cosnt *str, char const *group );

strspn 函数计算从 str 开始直到遇到不属于 group 中的字符为止的字符数量。

strcspn 函数计算从 str 开始直到遇到属于 group 中的字符为止的字符数量。

查找标记
char *strtok( char *str, char const *sep);

解析由特定分隔符分隔的字符串。从字符串中隔离各个单独的称为标记(token)的部分,并丢弃分隔符。如果strtok 函数的第1个参数不是NULL,函数将找到字符串的第1个标记,strtok 同时将保存在字符串中的位置。如果strtok 函数的第1个参数是NULL,函数就在同一个字符串中从这个被保存的位置开始像前面一样查找下一个标记。如果字符串内不存在更多的标记,strtok 函数就返回一个NULL指针。

错误信息
char *strerror( int error_number );

strerror 函数把其中一个错误代码作为参数并返回一个指向用于描述错误的字符串的指针。

字符操作
字符分类

C和指针:字符串_c语言_02

常用:isdigit、islower、isupper

字符转换
int tolower( int ch );
int toupper( int ch);

toupper 函数返回其参数的对应大写形式,tolower 函数返回其参数的对应小写形式。

如果函数的参数并不是一个处于适当大小写状态的字符,函数将不修改参数直接返回。

内存操作
void *memcpy( void *dst, void const *src, size_t length);
void *memmove( void *dst, void const *src, size_t length);
void *memcmp( void const *a, void const *b, size_t length);
void *memchr( void const *a, int ch, size_t length);
void *memset( void *a, int ch, size_t length);

memcpy 从src的起始位置复制 length个字节到 dst的内存起始位置。你可以用这种方法复制任何类型的值,第3个参数指定复制值的长度(以字节计)。如果src和 dst 以任何形式出现了重叠,结果是未定义的。前两个参数并不需要使用强制类型转换,因为在函数的原型中,参数的类型是 void*型指针,任何类型的指针都可以转换为void*型指针。

memmove函数的行为和 memcpy 差不多,只是源和目标操作数可以重叠。它不需要以下面这种方式实现,不过memmove 的结果和这种方法的结果相同,把源操作数复制到一个临时位置,临时位置不会与源或目标操作数重叠,再把它从这个临时位置复制到目标操作数。memmove 通常无法使用某些机器所提供的特殊的字节-字符串处理指令来实现,所以它可能比memcpy慢一些???

memcmp 对两段内存的内容进行比较,这两段内存分别起始于 a和b,共比较 length 个字节。

这些值按照无符号字符逐字节进行比较,函数的返回类型和 strcmp 函数一样——负值表示a小于b,

正值表示a大于b,零表示a等于b。

memchr从 a的起始位置开始查找字符ch第1次出现的位置,并返回一个指向该位置的指针,它共查找length个字节。如果在这length个字节中未找到该字符,函数就返回一个NULL指针。

memset函数把从 a开始的length个字节都设置为字符值ch。