C语言学习笔记(16) c语言字符串分析

摘要:总结了字符串的概念,字符串长度的计算方法,尝试实现了strlen和strcpy函数,最后介绍了受限和不受限的字符串函数。


一、字符串的概念

    1.从概念上讲,c语言中并没有字符串这一类型,它使用字符数组末尾加’\0’来模拟字符串。

    2.C语言中的字符串是以’\0’结尾的字符数组。

    3.C语言中的字符串可以分配于栈空间,堆空间或者只读存储区。

这里的字符串分配于栈空间,堆空间或者只读存储区,是因为我们创建字符串的方式不同,例如使用数组,则是在栈空间分配,使用指针+malloc我们还在堆空间,如果只是char *s1=”hello”;那么就是在只读存储区了,这时候如果尝试改变它的值,就会出现段错误。

例如下面的例子:

#include

intmain(void)
{
    char *s1="hello";
    s1[2]='h';
   
    return 0; 
}

编译不会报错,但是运行就会出错,这里其实也可以理解为,并没有给s1分配内存空间。


二、字符串的长度

    1.字符串的长度其实就是字符串所包含的字符的个数。

    2.字符串的长度指的是第一个’\0’出现前,所包含的字符的个数。

    3.c语言通过’\0’来确定字符串的长度。

    下面的例子:

#include 
#include 
 
int main(void)
{
    chara[100];
   
    a[0]='h';
    a[1]='h';
    a[2]='h';
    a[3]='h';
    a[4]='h';
    a[5]='\0';
   
    printf("length=%d\n",strlen(a));
    printf("sizeis:%d\n",sizeof(a));
   
    return0;
    }
    最终结果输出如下:
    length=5
    sizeis:100

    可以看到长度是只认’\0’,但是数组的大小就是我们分配的内存空间的大小,这里strlen的函数原型如下:

 size_tstrlen(const char *s)
    {
       size_tlength=0;
       assert(s);
       while(*s++);
       {
           length++;
        }
    return length;
     }

    assert是用来判断字符串是否为空的函数,如果为空,程序就结束。

    注意:使用strlen比较两个字符串大小的时候,不要使用strlen(a)-strlen(b)这种格式,因为strlen的返回值是一个无符号类型的,所以他们相减的值永远不会出现负数,所以无论a和b的大小怎样,都会默认a比b大,这种比较应当使用>方法比较。


三、一条语句实现strlen

    首先复习两个知识点:

    第一:逗号表达式,从左往右依次计算表达式,整个过程的值以最后一个表达式的值为准。

    第二:三目运算符,对于条件表达式b?x:y,先计算条件b,然后进行判断。如果b的值为true,计算x的值,运算结果为x的值;否则,计算y的值,运算结果为y的值。

    实现语句如下:

    size_t strlen(const char *s)

    {

    return (assert(s),(*s?(strlen(s+1)+1):0));

    }

    首先利用逗号表达式,判断s是否为空,为空的话程序就会出错,后面的三目运算符,利用了递归的思想,其实是首先判断*s是否成立,如果不为0的话,就执行下一句strlen(s+1)+1,这是什么意思呢?我的理解是把指针移动一位,判断下一个是否为真,也就是是否为0,就是使用了判断和移位,也就是while(s++)这个语句被代替了,一直判断,往里递归,知道遇到\0,这样最后返回的值+1,就得到字符串的长度,之所以加1,是因为我们是从s+1开始递归进去。

    不过,一般不要使用自己写的库函数去替换原有的函数,因为有时候这些函数会使用汇编代码加快机器执行的速度,复用他们效率会更高。


四、不受限制的字符串函数

    不受限制的字符串函数是通过寻找字符串中的’\0’来判断字符串的长度。

    这些函数的输入参数中必须包含’\0’;

    strcpy和strcat目标字符串必须要保证有足够的分配到的空间来存放源文件字符串。

    strcmp在比较两个字符串大小的时候,相等返回0,大于返回正数,小于返回负数。strcmp不会修改参数的值,但是依然以’\0’作为结束符。

例如:

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

    字符串链接:char* strcat(char*dst,const char* src)

    字符串比较:int strcmp(constchar* dst,const char* src)


五、实现strcpy

#include 
#include 
 
char* strcpy(char* dst,const char* src)
{
    char* ret = dst;//将目标字符串的地址给返回值的指针
    assert(dst&&src);//判断是否有空字符串,安全性检测
    while((*dst++=*src++)!='\0');//利用指针的自加,比下标效率更高
   
    return ret;//返回值可以用作其他函数的输入
   
    }
 
int main(void)
{
    chars[20];
    printf("%s",strcpy(s,"myc project"));
    return 0; 
}
 

六、长度受限的字符串函数

    长度受限的字符串函数接收一个显示的长度参数用于限定操作的字符数,例如下列函数:

    字符串复制:char* strncpy(char*dst, const char* src, size_t len);
    字符串连接:char* strncat(char* dst, const char* src , size_tlen);
    字符串比较:int strncmp(const char* s1, const char*s2 ,size_t len);

    其中:

    strncpy只复制len个字符到目标字符串。
   当源字符串的长度小于len时,剩余的空间以’\0’填充。
   当源字符串的长度大于len时,只有len个字符会被复制,且它将不会以’\0’结束。
   strncat最多从源字符串中复制len个字符到目标串中
   strncat总是在结果字符串后面添加’\0’
   strncat不会用’\0’填充目标串中的剩余空间
   strncmp只比较len个字符是否相等


    其实这些受限的字符串函数,就是比之前的不受限制的多了一个n,这个n就是代表受限的大小,很容易理解,需要注意的就是关于空间不足或者多了的时候是怎么处理的,cpy会填充’\0’,cat则不会,只会以’\0’结束,当时cpy空间不足的时候,就只会复制len个,并且不会以’\0’结束。

    这篇帖子就总结到这里吧,如有不正确的地方还请指出,大家共同进步!

你可能感兴趣的:(C)