文章目录 一、求字符串长度 二、长度不受限制的字符串函数 三、长度受限制的字符串函数 四、字符串查找 五、错误信息报告 六、字符分类函数 七、内存操作函数
一、求字符串长度
strlen
功能:获取字符串长度 参数:c字符串(str) 返回值:字符串长度(无符号整形size_t) 字符串将 ‘\0’ 作为结束标志,strlen函数返回的是在字符串中 ‘\0’ 前面出现的字符个数(不包含 ‘\0’ )。
例子
# include <stdio.h>
# include <string.h>
int main ( )
{ const char * str1 = "abcdef" ; const char * str2 = "bbb" ; printf ( "%d\n" , strlen ( str1) ) ; printf ( "%d\n" , strlen ( str2) ) ; if ( strlen ( str2) - strlen ( str1) > 0 ) { printf ( "str2>str1\n" ) ; } else { printf ( "srt1>str2\n" ) ; } return 0 ;
}
模拟实现
计数器方式
int my_strlen ( char * str)
{ int len = 0 ; while ( * str) { str++ ; len++ ; } return len;
}
不创建临时变量
int my_strlen ( const char * str)
{ if ( * str == '\0' ) return 0 ; else return 1 + my_strlen ( str + 1 ) ;
}
指针-指针
int my_strlen ( char * s)
{ char * p = s; while ( * p!= '\0' ) { p++ ; } return p - s;
}
二、长度不受限制的字符串函数
strcpy
功能:复制字符串 参数:目的字符串(destination)源字符串(source) 返回值:目的字符串 源字符串必须以 ‘\0’ 结束 会将源字符串中的 ‘\0’ 拷贝到目标空间 目标空间必须足够大,以确保能存放源字符串 目标空间必须可变
例子
# include <stdio.h>
# include <string.h> int main ( )
{ char str1[ ] = "Sample string" ; char str2[ 40 ] ; char str3[ 40 ] ; strcpy ( str2, str1) ; strcpy ( str3, "copy successful" ) ; printf ( "str1: %s\nstr2: %s\nstr3: %s\n" , str1, str2, str3) ; return 0 ;
}
模拟实现
char * my_strcpy ( char * dest, const char * src)
{ char * ret = dest; assert ( src != NULL ) ; assert ( dest != NULL ) ; while ( * dest++ = * src++ ) { } return ret;
}
strcat
功能:连接字符串 参数:目的字符串(destination)源字符串(source) 返回值:目的字符串 将源字符串的副本追加到目标字符串。目标中的终止空字符被源的第一个字符覆盖,并且在目标中由两者串联形成的新字符串的末尾包含一个空字符。 目的地和来源不得重叠。
例子
# include <stdio.h>
# include <string.h> int main ( )
{ char str[ 80 ] ; strcpy ( str, "these " ) ; strcat ( str, "strings " ) ; strcat ( str, "are " ) ; strcat ( str, "concatenated." ) ; puts ( str) ; return 0 ;
}
模拟实现
char * my_strcat ( char * dest, const char * src)
{ char * ret = dest; assert ( dest) ; assert ( src) ; while ( * dest) { dest++ ; } while ( * dest++ = * src++ ) { } return ret;
}
strcmp
功能:比较两个字符串 参数:要比较的字符串1(str1)要比较的字符串2(str2) 返回值:
返回值 表明 <0 第一个不匹配的字符在 PTR1 中的值低于 PTR2 中的值 0 两个字符串的内容相等 >0 第一个不匹配的字符在 PTR1 中的值大于在 PTR2 中的值
此函数开始比较每个字符串的第一个字符。如果它们彼此相等,则继续下一对,直到字符不同或达到终止空字符
例子
# include <stdio.h>
# include <string.h> int main ( )
{ int ret = strcmp ( "bbq" , "bcq" ) ; if ( ret > 0 ) printf ( ">\n" ) ; printf ( "%d\n" , ret) ; return 0 ;
}
模拟实现
int my_strcmp ( const char * str1, const char * str2)
{ assert ( str1 && str2) ; while ( * str1 == * str2) { if ( * str1 == '\0' ) return 0 ; str1++ ; str2++ ; } return ( * str1 - * str2) ;
}
三、长度受限制的字符串函数
strncpy
功能:从字符串中复制字符 参数:目的字符串(destination)源字符串(source)要从源中复制的最大字符数(num) 返回值:目的字符串 拷贝num个字符从源字符串到目标空间 如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num个 如果源长度超过 num,则不会在目标末尾隐式附加空字符。因此,在这种情况下,不应将目标视为以空结尾的 C 字符串(这样读取它会溢出) 目的地和来源不得重叠
例子
# include <stdio.h>
# include <string.h> int main ( )
{ char str1[ ] = "To be or not to be" ; char str2[ 40 ] ; char str3[ 40 ] ; strncpy ( str2, str1, sizeof ( str2) ) ; strncpy ( str3, str2, 5 ) ; str3[ 5 ] = '\0' ; puts ( str1) ; puts ( str2) ; puts ( str3) ; return 0 ;
}
strncat
功能:从字符串追加字符 参数:目的字符串(destination)源字符串(source)要追加的最大字符数(num) 返回值:目的字符串 将源的第一个数字字符追加到目标,外加一个终止空字符 如果源中 C 字符串的长度小于 num,则仅复制终止空字符之前的内容 目标空间必须足够大以包含串联的结果字符串,包括其他 null 字符
例子
# 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 ) ; puts ( str1) ; return 0 ;
}
strncmp
功能:比较两个字符串的字符 参数:要比较的字符串1(str1)要比较的字符串2(str2)要比较i的最大字符数(num) 返回值:
返回值 表明 <0 不匹配的第一个字符在 str1 中的值低于 str2 中的值 0 两个字符串的内容相等 >0 第一个不匹配的字符在 str1 中的值大于在 str2 中的值
将 C 字符串 str1 的字符数与 C 字符串 str2 的字符数进行比较 此函数开始比较每个字符串的第一个字符。如果它们彼此相等,则继续使用以下对,直到字符不同,直到达到终止的空字符,或者直到两个字符串中的 num 字符匹配,以先发生者为准
例子
# 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] ) ; } return 0 ;
}
四、字符串查找
strstr
功能:查找子字符串 参数:要扫描的字符串(str1)包含要匹配的字符序列的字符串(str2) 返回值:指向 str1 中指定的整个字符序列在 str2 中首次出现的指针,如果序列在 str1 中不存在,则为 null 指针
例子
# include <stdio.h>
# include <string.h> int main ( )
{ char str[ ] = "This is a simple string" ; char * pch; pch = strstr ( str, "simple" ) ; if ( pch != NULL ) strncpy ( pch, "sample" , 6 ) ; puts ( str) ; return 0 ;
}
模拟实现
char * my_strstr ( const char * str1, const char * str2)
{ char * cp= str1; char * s1= str1; char * s2= str2; if ( * str2 == '\0' ) return str1; while ( * cp) { s1 = cp; s2 = str2; while ( * s1 && * s2 && * s1 == * s2) { s1++ ; s2++ ; } if ( * s2 == '\0' ) return cp; cp++ ; } return NULL ;
}
strtok
功能:将字符串拆分为标记 参数:要截断的c字符串(str)包含分割字符的c字符串(delimiters) 返回值:如果找到令牌,则指向令牌开头的指针,否则为空指针。当在正在扫描的字符串中到达字符串的末尾(即空字符)时,始终返回空指针 strtok函数找到str中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针。(注:strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改) strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置 strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标记
例子
# 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 , " ,.-" ) ; } return 0 ;
}
五、错误信息报告
strerror
功能:获取指向错误消息字符串的指针 参数:错误号(errnum) 返回值:指向描述错误错误的字符串的指针 解释 errnum 的值,生成一个字符串,其中包含描述错误条件的消息,就像由库的函数设置为 errno 一样
例子
# include <stdio.h>
# include <string.h>
int main ( )
{ int i = 0 ; for ( i = 0 ; i < 10 ; i++ ) { printf ( "%d: %s\n" , i, strerror ( i) ) ; } return 0 ;
}
六、字符分类函数
函数 如果他的参数符合下列条件就返回真 iscntrl 任何控制字符 isspace 空白字符:空格‘ ’,换页‘\f’,换行’\n’,回车‘\r’,制表符’\t’或者垂直制表符’\v’ isdigit 十进制数字 0~9 isxdigit 十六进制数字,包括所有十进制数字,小写字母a~f,大写字母A ~F islower 小写字母a~z isupper 大写字母A~Z isalpha 字母a~ z或A~Z isalnum 字母或者数字,a ~ z,A~ Z,0~9 ispunct 标点符号,任何不属于数字或者字母的图形字符(可打印) sgraph 任何图形字符 isprint 任何可打印字符,包括图形字符和空白字符
七、内存操作函数
memcpy
功能:复制内存块 参数:指向目标数组的指针(destinatiom)指向要复制的数据源的指针(source)要复制的字节数(num) 返回值:返回目标 函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置 这个函数在遇到 ‘\0’ 的时候并不会停下来 如果source和destination有任何的重叠,复制的结果都是未定义的
例子
# include <stdio.h>
# include <string.h> int main ( )
{ int arr1[ ] = { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 } ; int arr2[ 20 ] = { 0 } ; memcpy ( arr2, arr1, 40 ) ; int i = 0 ; for ( i = 0 ; i < 20 ; i++ ) { printf ( "%d " , arr2[ i] ) ; } return 0 ;
}
模拟实现
void * my_memcpy ( void * dest, const void * src, size_t num)
{ void * ret = dest; assert ( dest && src) ; while ( num-- ) { * ( char * ) dest = * ( char * ) src; dest = ( char * ) dest + 1 ; src = ( char * ) src + 1 ; } return ret;
}
memmove
功能:移动内存块 参数:指向目标数组的指针(destinatiom)指向要复制的数据源的指针(source)要复制的字节数(num) 返回值:返回目标 将字节数的值从源指向的位置复制到目标指向的内存块。复制就像使用了中间缓冲区一样,允许目标和源重叠 该函数不检查源中的任何终止空字符 - 它总是准确地复制字节数
例子
# include <stdio.h>
# include <string.h>
int main ( )
{ char str[ ] = "memmove can be very useful......" ; memmove ( str + 20 , str + 15 , 11 ) ; puts ( str) ; return 0 ;
}
模拟实现
void * my_memmove ( void * dest, const void * src, size_t num)
{ void * ret = dest; assert ( dest && src) ; if ( dest < src) { while ( num-- ) { * ( char * ) dest = * ( char * ) src; dest = ( char * ) dest + 1 ; src = ( char * ) src + 1 ; } } else { while ( num-- ) { * ( ( char * ) dest + num) = * ( ( char * ) src + num) ; } } return ret;
}
memcmp
功能:比较两个内存块 参数:指向内存块的指针1(str1)指向内存块的指针2(str2)要比较的字节数(num) 返回值:
返回值 表明 <0 两个内存块中不匹配的第一个字节在 PTR1 中的值低于 PTR2 中的值 0 两个内存块的内容相等 >0 两个内存块中不匹配的第一个字节在 PTR1 中的值大于在 PTR2 中的值
与 strcmp 不同,该函数在找到空字符后不会停止比较
例子
# include <stdio.h>
# include <string.h>
int main ( )
{ int arr1[ ] = { 1 , 2 , 1 , 4 , 5 , 6 } ; int arr2[ ] = { 1 , 2 , 33 } ; int ret = memcmp ( arr1, arr2, 10 ) ; printf ( "%d\n" , ret) ; return 0 ;
}