C语言字符串和字符函数
- 1.什么是字符串 ?
- 2.字符串函数的好处
- 3. 字符串函数功能介绍与函数的模拟实现
- [3.1 strlen](http://www.cplusplus.com/reference/cstring/strlen/?kw=strlen)
- [3.2 strcpy](http://www.cplusplus.com/reference/cstring/strcpy/?kw=strcpy)
- [3.3 strcmp](http://www.cplusplus.com/reference/cstring/strcmp/?kw=strcmp)
- [3.4 strcat](http://www.cplusplus.com/reference/cstring/strcat/?kw=strcat)
- [3.5 strncpy]( http://www.cplusplus.com/reference/cstring/strncpy/?kw=strncpy)
- [3.6 strncmp](http://www.cplusplus.com/reference/cstring/strncmp/?kw=strncmp)
- [3.7 strncat](http://www.cplusplus.com/reference/cstring/strncat/?kw=strncat)
- [3.8 strstr](http://www.cplusplus.com/reference/cstring/strstr/?kw=strstr)
- 4. 总结
1.什么是字符串 ?
字符串或串(String)是由数字、字母、下划线组成的一串字符。一般记为 s=“a1a2···an”(n>=0)。它是编程语言中表示文本的一种数据类型。
2.字符串函数的好处
C语言中对字符和字符串的处理很是频繁, 但是c语言它本身没有字符串类型,字符串通常放在常量字符串中或者字符串数组中。 字符串常量适用那些对它不做修改的字符串函数。
3. 字符串函数功能介绍与函数的模拟实现
3.1 strlen
size_t strlen ( const char * str );
功能介绍:
- 字符串以‘\0’ 作为结束标志,strlen函数返回的是在字符串中’\0’前面出现的字符个数(并不包括’\0‘)。
- 参数str只想的字符串必须要以’\0‘ 结束。
- 函数的返回值是size_t , 是无符号的(易错)。
针对易错, 我们来做这样一道题目。请问结果输出什么?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char* str1 = "abcdef";
char* str2 = "bbb";
printf("%d ", strlen(str1));
if (strlen(str2) - strlen(str1) > 0)
{
printf("str2>str1\n");
}
else
{
printf("str1>str2\n");
}
return 0;
}
相信很多人都会不加思索,回答 str1的长度肯定大于 str2,所以一定输出str1>str2 。当然这样的回答也一定是错的 。
strlen函数的设计者设计strlen函数时,只是想到字符串的长度怎么可能为负数呢?故将它的返回值设置为size_t(无符号整形)。strlen(str1) 与 strlen(str2)返回的结果都是无符号的,它们加减乘除的结果当然也是无符号整形, strlen(str1) - strlen(str2) 的结果是 -4 ,在内存中的补码是oxFFFFFFFC,被当做一个无符号整形,故是一个非常大的正数,在判断条件作为真,故打印str2 > str1 。
那如何模拟实现strlen函数呢?
这里有三种实现方式,仅供参考。
方式一(设置一个计数器)
size_t mystrlen(const char* str)
{
size_t count = 0 ;
while(*str)
{
count ++ ;
str ++ ;
}
return count ;
}
方法二(递归,不需设置一个临时计数器)
size_t mystrlen(const char* str)
{
if(*str == '\0') return 0 ;
return mystrlen(str+1) + 1 ;
}
方法三(指针 - 指针)
size_t mystrlen(const char * str)
{
char* end = str ;
while(*end)
{
end++;
}
return end - str ;
}
3.2 strcpy
char * strcpy ( char * destination, const char * source );
功能介绍:
- 将源所指向的C字符串复制到目标所指向的字符数组中,包括结束的空字符(并在该点停止)。
- 为了避免溢出,destination指向的数组长度应该足够长,以包含与source相同的C字符串(包括结束的’\0‘字符),并且在内存中不应该与source重叠。
- 目标空间必须可修改。
根据以上几点, 我们注意到源字符必须以 ’\0’ 结束。
如何模拟实现 ?
供参考:
char * mystrcpy ( char * dest, const char * src )
{
assert(dest && src ) ;
char* ret = dest;
while(*dest++ = *src++);
return ret ;
}
3.3 strcmp
int strcmp ( const char * str1, const char * str2 );
功能介绍:
- strcmp函数开始比较每个字符串的第一个字符。如果它们彼此相等,则继续使用以下一字符对,直到字符对不相等或达到结束的空字符为止。
返回值描述:
实例 :
#include <stdio.h>
#include <string.h>
int main ()
{
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!");
return 0;
}
模拟实现
int mystrcmp(const char* str1 , const char* str2 )
{
assert(str1 && str2 );
while(*str1 == *str2)
{
if(*str2 == '\0') return 0 ;
str1 ++ , str2 ++ ;
}
return *str1 - *str2 ;
}
3.4 strcat
char * strcat ( char * destination, const char * source );
功能介绍:
- 将源字符串的副本追加到目标字符串。目标中的结束空字符被源的第一个字符覆盖,并且一个空字符包含在目标中由两者连接形成的新字符串的末尾。
- 目的内存空间和源内存空间不应重叠。(否则会造成死循环)
由以上几点,可知
- 源字符串必须以‘\0’结束 。
- 目标空间必须足够大,能够容的下源字符的内容。
- 目标空间必须可修改。
模拟实现
char * mystrcat (char* des, const char* src )
{
char* ret = des ;
while(*des)des++;//找到目的字符串的结束'\0'
while(*src)
{
*des = *src ;
des++, src++;
}
return ret ;
}
3.5 strncpy
char * strncpy ( char * destination, const char * source, size_t num );
功能介绍:
- 从源的第一个字符启复制到目标空间。如果在复制num个字符之前提前找到源字符串的末尾(‘\0’),则用‘\0’填充目标空间,直到向目标空间写入num个字符的总数。
简单的就以下几点:
- 拷贝num个字符串从源字符串到目标空间。
- 如果源字符串的长度小于num, 则拷贝完源字符串之后, 在目标的后面追加上‘\0’,知道num个。
模拟实现
char* mystrncpy(char* des , const char* src ,size_t num)
{
char * ret = des ;
while (num && (*des++ = *src++) != '\0') num--;
if(num)
{
while(--num)
*des++ = '\0';
}
return ret ;
}
3.6 strncmp
int strncmp ( const char * str1, const char * str2, size_t num );
功能介绍
-
将C字符串str1的num字符与C字符串str2的num字符比较。
-
这个函数开始比较每个字符串的第一个字符。如果它们彼此相等,则继续使用以下字符对,直到字符不相等,直到到达结束的空字符,或直到num字符在两个字符串中匹配,以先出现的为准.。
模拟实现
int mystrncmp ( const char * str1, const char * str2, size_t num )
{
while(num-- && *str1 == *str2)
{
if(*str2 == '\0'){
return 0;
}
str1 ++ , str2 ++ ;
}
if(num == 0){
return 0 ;
}
else
{
return *str1 - *str2 ;
}
}
3.7 strncat
char * strncat ( char * destination, const char * source, size_t num );
功能介绍:
- 将源的第一个num字符附加到目标空间的结束字符‘\0’,再加上一个结束空字符。
- 如果源文件中的C字符串的长度小于num,则只复制终止空字符之前的内容。
模拟实现:
char * mystrncat ( char * des, const char * src, size_t num )
{
char * ret = des ;
while(*des) des++;
while(num--)
{
if((*des++ = *src++) == 0)
return ret;
}
*des = '\0';
return ret ;
}
3.8 strstr
const char * strstr ( const char * str1, const char * str2 );
char * strstr ( char * str1, const char * str2 );
功能介绍
- strstr(str1,str2) 函数用于判断字符串str2是否是str1的子串。如果是,则该函数返回str2在str1中首次出现的地址;否则,返回NULL。
Example
/* strstr example */
#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;
}
This example searches for the “simple” substring in str and replaces that word for “sample”.
模拟实现:
char* mystrstr(const char* str1 , const char* str2)
{
assert(str1 && str2);
char* s1 = NULL;
char* s2 = NULL;
char* cp = (char*) str1 ;
for (; *cp != '\0'; cp++) {
s1 = cp;
s2 = (char*)str2;
while(*s2 && *s1 && *s2 == *s1)
{
s2++,s1++;
}
if(*s2 == '\0'){
return cp;
}
}
return NULL;
}
4. 总结
以上就是关于字符串函数的重要知识点总结, 谢谢大家观看。