C语言字符串详解

目录


一、字符串的概念

我们可以把字符串储存在char类型的数组中,如果char类型的数组末尾包含一个表示字符串末尾的空字符\0,则该数组中的内容就构成了一个字符串

因为字符串需要用\0结尾,所以在定义字符串的时候,字符数组的长度要预留多一个字节用来存放\0,\0就是数字0

例如

char name[21];  // 定义一个最多存放20个英文字符或十个中文的字符串
  • 字符串也可以存放中文和全角的标点符号,一个中文字符占两个字节(GBK编码)。char strname[21]用于存放中文的时候,最多只能存10个汉字。
  • 字符串采用双引号包含起来,如:”hello,world”、”你好C语言”

二、占用内存的情况

一个字符占用一字节的内存,字符串定义时数组的大小就是字符串占用内存的大小

  char str[21];     // 占用21字节的内存
  char str[1024];   // 占用1024字节的内存

三、字符串的初始化

char name[21];
memset(name,0,sizeof(name));//采用memset函数初始化字符串

四、字符串与指针

数组名是数组元素的首地址,字符串是字符数组,所以在获取字符串的地址的时候,不需要用&取地址

char name[21];
memset(name,0,sizeof(name));
strcpy(name,"hello,xiaoqiu");//把hello,xiaoqiu赋值给name
printf("%s\n",name);

 五、字符串的结尾标志

  1. 字符串的结尾标志是0,如果没有结尾标志,后面的内容将被丢弃
  2. 结尾标志后面的内容如何处理
#include <stdio.h>
#include <string.h>

int main()
{

   char name[21];
   memset(name,0,sizeof(name));
   strcpy(name,"hello,xiaoqiu");//把hello,xiaoqiu赋值给name

   name[5]=0;//强制把第6个元素赋值为0   

   printf("%s\n",name);

   return 0;
}

运行效果

以上代码输出的结果是 hello ,但是,在内存中的值仍是hello0xiaoqiu,后面的 xiaoqiu 成了内存中的垃圾值

不要让字符串的内存中有垃圾值,容易产生意外的后果。这就是字符串的初始化不建议采用把第一个元素的值置为0的原因(name[0]=0)

六、字符串常用的库函数

1、获取字符串的长度(strlen)

size_t  strlen( const char*  str);
  1. 功能:计算字符串的有效长度,不包含 \0
  2. 返回值:返回字符串的字符数 
  3. strlen 函数计算的是字符串的实际长度,遇到第一个\0结束
  4. 函数返回值一定是size_t,是无符号的整数,即typedef unsigned int size_t
  5. 如果您只定义字符串没有初始化,求它的长度是没意义的,它会从首地址一直找下去,遇到0停止
  6. 很多人对 sizeofstrlen 有点分不清楚 。sizeof 返回的是变量所占的内存数,不是实际内容的长度

举个例子

#include <stdio.h>
#include <string.h>
int main()
{
    char name[21];
    memset(name,0,sizeof(0));
    strcpy(name,"xiaoqiu");

    printf("strlen=%d\n",strlen(name)); // 7
    printf("sizeof=%d\n",sizeof(name)); // 21  sizeof 返回的是变量所占的内存数

    return 0;
}

运行效果

自己实现一个 strlen 函数

#include <stdio.h>
#include <string.h>

int mystrlen(const char* str)
{   
    int i = 0;
    while( str[i]!='\0' ) {
     i++;
    }
    return i;
}

int main()
{
    char name1[21];
    memset(name1,0,sizeof(0));
    strcpy(name1,"xiaoqiu");

    char name2[21];
    memset(name2,0,sizeof(0));
    strcpy(name2,"baidu");

    printf("mystrlen=%d\n",mystrlen(name1)); // 7
    printf("mystrlen=%d\n",mystrlen(name2)); // 5

    return 0;
}

运行效果

2、字符串复制或赋值(strcpy)

char *strcpy(char* dest, const char* src);
  1. 功 能: 将参数src字符串拷贝至参数dest所指的地址
  2. 返回值: 返回参数dest的字符串起始地址
  3. 复制完字符串后,在dest后追加0
  4. 如果参数dest所指的内存空间不够大,可能会造成缓冲溢出的错误情况

 自己实现一个 strcpy 函数

#include <stdio.h>
#include <string.h>

char *mystrcpy(char* dest,const char* src)
{   
    size_t i = 0;
    
    while (src[i] != '\0') {
      dest[i] = src[i];
      i++;
    }
    
    dest[i]='\0';
    
    return dest;
}

int main()
{
    char name[21];
    memset(name,0,sizeof(0));
    mystrcpy(name,"xiaoqiu");

    printf("strlen=%d\n",strlen(name)); // 7
    printf("sizeof=%d\n",sizeof(name)); // 21

    return 0;
}

运行效果

3、字符串复制或赋值(strncpy)

char * strncpy(char* dest,const char* src, const size_t n);
  1. 功能:把src前n字符的内容复制到dest中
  2. 返回值:dest字符串起始地址
  3. 如果src字符串长度小于n,则拷贝完字符串后,在dest后追加0,直到n个
  4. 如果src的长度大于等于n,就截取src的前n个字符,不会在dest后追加0
  5. dest必须有足够的空间放置n个字符,否则可能会造成缓冲溢出的错误情况

自己实现一个 strncpy 函数

#include <stdio.h>
#include <string.h>

char *mystrncpy(char* dest,const char* src,const size_t n)
{
    int len = (strlen(src)>n)?n:strlen(src);

    size_t i = 0;

    for (i=0;i<len;i++) {
       dest[i] = src[i];
    }

    dest[i]='\0';

    return dest;
}

int main()
{
    char name[21];
    memset(name,0,sizeof(0));
    mystrncpy(name,"xiaoqiu",4);

    printf("strlen=%d\n",strlen(name)); // 4
    printf("sizeof=%d\n",sizeof(name)); // 21

    return 0;
}

运行效果

4、字符串拼接(strcat)

char *strcat(char* dest,const char* src);
  1. 功能:将src字符串拼接到dest所指的字符串尾部
  2. 返回值:返回dest字符串起始地址
  3. dest最后原有的结尾字符0会被覆盖掉,并在连接后的字符串的尾部再增加一个0
  4. dest要有足够的空间来容纳要拼接的字符串,否则可能会造成缓冲溢出的错误情况

自己实现一个 strncpy 函数 

#include <stdio.h>
#include <string.h>

char *mystrcat(char* dest,const char* src)
{   
    int destlen = strlen(dest);
    
    int i = 0;
    
    for (i=0;i<strlen(src);i++) {
     dest[destlen+i]=src[i];
    }
    
    dest[destlen+i]='\0';
}

int main()
{
    char name1[21];
    memset(name1,0,sizeof(0));
    strcpy(name1,"xiaoqiu");

    char name2[21];
    memset(name2,0,sizeof(0));
    strcpy(name2,"hello");
    mystrcat(name2,name1);

    printf("%s\n",name2);

    return 0;
}

运行效果

 5、字符串拼接(strncat)

char *strncat (char* dest,const char* src, const size_t n);
  1. 功能:将src字符串的前n个字符拼接到dest所指的字符串尾部
  2. 返回值:返回dest字符串的起始地址
  3. 如果n大于等于字符串src的长度,那么将src全部追加到dest的尾部,如果n小于字符串src的长度,只追加src的前n个字符
  4. strncat会将dest字符串最后的0覆盖掉,字符追加完成后,再追加0
  5. dest要有足够的空间来容纳要拼接的字符串,否则可能会造成缓冲溢出的错误情况

自己实现一个 strncat 函数  

#include <stdio.h>
#include <string.h>

char *mystrncat(char* dest,const char* src,size_t n)
{
    /*  方法一
    int len = strlen(src);

    if (len > n) len = n;

    else if (len < n) len = strlen(src);
    */

    // 方法二
    int len = (strlen(src)>n)?n:strlen(src);


    int destlen = strlen(dest);

    int i = 0;

    for (i=0;i<len;i++) {
     dest[destlen+i]=src[i];
    }

    dest[destlen+i]='\0';
}

int main()
{
    char name1[21];
    memset(name1,0,sizeof(0));
    strcpy(name1,"xiaoqiu");

    char name2[21];
    memset(name2,0,sizeof(0));
    strcpy(name2,"hello");
    mystrncat(name2,name1,4);

    printf("%s\n",name2);

    return 0;
}

运行效果

6、字符串比较(strcmp、strncmp)

int strcmp(const char *str1, const char *str2 );

功能:比较str1和str2的大小

返回值:相等返回0,str1大于str2返回1,str1小于str2返回-1

自己实现一个strcmp 函数

#include <stdio.h>
#include <string.h>

int mystrcmp(const char *str1,const char *str2)
{    
     int i = 0;
     int len = 0;//  str1 和 str2 较短的字符串长度
     
     if ( strlen(str1) > strlen(str2) )  len = strlen(str2);
     
     else len = strlen(str1);
     
     for (i = 0;i < len;i++) {
       if (str1[i]==str2[i]) continue;
       else break;
     }
     
     // 两个字符串相等
     if ( (i==len) && (strlen(str1)==strlen(str2))  ) return 0;
     
     // 两个字符串不相等
     else if (str1[i]>str2[i]) return 1;
     
     else return -1;
}    

int main()
{
    char name1[21];
    memset(name1,0,sizeof(0));
    strcpy(name1,",xiaoqiu");

    char name2[21];
    memset(name2,0,sizeof(0));
    strcpy(name2,"hello");

    printf("%d\n",mystrcmp(name1,name2));

    return 0;
}
                               

运行效果 

int strncmp(const char *str1,const char *str2 ,const size_t n);

功能:比较str1和str2前n个字符的大小

返回值:相等返回0,str1大于str2返回1,str1小于str2返回-1

两个字符串比较的方法是比较字符的ASCII码的大小,从两个字符串的第一个字符开始,如果分不出大小,就比较第二个字符,如果全部的字符都分不出大小,就返回0,表示两个字符串相等

自己实现一个strncmp函数

#include <stdio.h>
#include <string.h>

int mystrcmp(const char *str1,const char *str2,size_t n)
{   
    int i = 0;
    
    for (i = 0;i < n;i++) {
     if (str1[i]==str2[i]) continue;
     else break;
    }
    
    if (i==n) return 0;
    
    else if (str1[i]>str2[i]) return 1;
    
    else return -1;
}

int main()
{
    char name1[21];
    memset(name1,0,sizeof(0));
    strcpy(name1,",xiaoqiu");

    char name2[21];
    memset(name2,0,sizeof(0));
    strcpy(name2,"hello");

    printf("%d\n",mystrcmp(name1,name2,4));

    return 0;
}

运行效果

7、字符查找(strchr、strrchr)

char *strchr(const char *s,const int c);

返回一个指向在字符串s中第一个出现c的位置,如果找不到,返回0

自己实现一个strchr函数

#include <stdio.h>
#include <string.h>

char *mystrchr(const char *s,const int c)
{   
    int i = 0;
    
    int len = strlen(s);
    
    for (i = 0;i<len;i++) {
       if (s[i]==c) 
       return (char *)s+i;
    }
    return 0;
}

int main()
{
    char name1[21];
    memset(name1,0,sizeof(0));
    strcpy(name1,",xiaoqiu");

    printf("%s\n",mystrchr(name1,'q'));

    return 0;
}

运行效果 

 

char *strrchr(const char *s,const int c);

返回一个指向在字符串s中最后一个出现c的位置,如果找不到,返回0

自己实现一个strrchr函数

#include <stdio.h>
#include <string.h>

char *mystrrchr(const char *s,const int c)
{
    int i = 0;

    for (i = strlen(s)-1;i>=0;i--) {
       if (s[i]==c)
       return (char *)s+i;
    }
    return 0;
}

int main()
{
    char name1[21];
    memset(name1,0,sizeof(0));
    strcpy(name1,",qqqxiaoqiu");

    printf("%s\n",mystrrchr(name1,'q'));

    return 0;
}

运行效果

  

8、字符串查找(strstr)

char *strstr(const char* str,const char* substr);
  1. 功能:检索子串在字符串中首次出现的位置
  2. 返回值:返回字符串str中第一次出现子串substr的地址;如果没有检索到子串,则返回0

 自己实现一个 strstr 函数

#include <stdio.h>
#include <string.h>

char *mystrstr(const char* str,const char* substr)
{   
    char* pos = (char *)str;//要被检索的 C 字符串
    char* pos1 = NULL;
    
    while (1) {
      
      if (pos[0]==0) break; // 如果要被检索的 C 字符串已经结束 break
      
      pos1 = strchr(pos,substr[0]); // 在pos中查找子字符串的首字符。
      
      if (pos == 0) return 0; // 如果没有找到,直接返回0
      
      if ( strncmp(pos1,substr,strlen(substr)) ==0  )  return pos1;// 如果找到了,返回找到的地址。
      
      pos++;// 待搜索的位置后移一个字节。
    }

}

int main()
{
    char name1[21];
    memset(name1,0,sizeof(0));
    strcpy(name1,",qqqxiaoqiu");

    printf("%s\n",mystrstr(name1,"xiao"));

    return 0;
}

运行效果

 

版权声明:本文为博主作者:易点点心动原创文章,版权归属原作者,如果侵权,请联系我们删除!

原文链接:https://blog.csdn.net/XiaoQiu__/article/details/126732659

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
乘风的头像乘风管理团队
上一篇 2023年12月29日
下一篇 2023年12月29日

相关推荐