C语言字符串详解-程序员宅基地

技术标签: c语言  Re :C语言  开发语言  

目录

一、字符串的概念

二、占用内存的情况

三、字符串的初始化

四、字符串与指针

 五、字符串的结尾标志

六、字符串常用的库函数

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

举个例子

运行效果

自己实现一个 strlen 函数

运行效果

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

 自己实现一个 strcpy 函数

运行效果

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

自己实现一个 strncpy 函数

运行效果

4、字符串拼接(strcat)

自己实现一个 strncpy 函数 

运行效果

 5、字符串拼接(strncat)

自己实现一个 strncat 函数  

运行效果

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

自己实现一个strcmp 函数

运行效果 

自己实现一个strncmp函数

运行效果

7、字符查找(strchr、strrchr)

自己实现一个strchr函数

运行效果 

自己实现一个strrchr函数

8、字符串查找(strstr)

 自己实现一个 strstr 函数

运行效果


一、字符串的概念

我们可以把字符串储存在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;
}

运行效果

 

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/XiaoQiu__/article/details/126732659

智能推荐

http隧道 java_使用java语言实现http隧道技术-程序员宅基地

文章浏览阅读119次。该楼层疑似违规已被系统折叠隐藏此楼查看此楼/***Getaparametervalue**@paramkeyString*@paramdefString*@returnString*/publicStringgetParameter(Stringkey,Stringdef){returnisStandalone?System.getProperty(ke..._java http隧道

Keepalived高可用+邮件告警_keepalived sendmail-程序员宅基地

文章浏览阅读913次。IP主机名备注192.168.117.14keepalived-master主节点192.168.117.15keepalived-slaver备节点192.168.117.100VIP1.主备节点均安装keepalived# yum install -y keepalived httpd2.主备节点均修改keepalived日志存放路径..._keepalived sendmail

SPFILE 错误导致数据库无法启动(ORA-01565)_ora01565 ora27046-程序员宅基地

文章浏览阅读469次。--==========================================--SPFILE错误导致数据库无法启动(ORA-01565)--========================================== SPFILE错误导致数据库无法启动 SQL> startup ORA-01078: failurein proce_ora01565 ora27046

功能测试基础知识(1)-程序员宅基地

文章浏览阅读6.1k次,点赞2次,收藏54次。功能测试基础知识总结_功能测试

postgresql 中文排序_pg中文排序-程序员宅基地

文章浏览阅读3.2k次,点赞3次,收藏2次。pg 中文首字母排序_pg中文排序

[Mysql] CONVERT函数_mysql convert-程序员宅基地

文章浏览阅读3.1w次,点赞23次,收藏109次。本文主要讲解CONVERT函数_mysql convert

随便推点

HTML5与微信开发(2)-视频播放事件及API属性_微信开发者工具视频快进-程序员宅基地

文章浏览阅读8.6k次,点赞2次,收藏2次。HTML5 的视频播放事件想必大家已经期待很久了吧,在HTML4.1、4.0之前我们如果在网页上播放视频无外乎两种方法: 第一种:安装FLASH插件或者微软发布的插件 第二种:在本地安装播放器,在线播放组件之类的 因为并不是所有的浏览器都安装了FLASH插件,就算安装也不一定所有的都能安装成功。像苹果系统就是默认禁用FLASH的,安卓虽然一开始的时候支持FLASH,但是在安卓4.0以后也开始不_微信开发者工具视频快进

JedisConnectionException Connection Reset_jedisconnectionexception: java.net.socketexception-程序员宅基地

文章浏览阅读5.4k次,点赞3次,收藏4次。在使用redis的过程常见错误总结1.JedisConnectionException Connection Reset参考这边文章:Connection reset原因分析和解决方案https://blog.csdn.net/cwclw/article/details/527971311.1问题描述Exception in thread "main" redis.clients...._jedisconnectionexception: java.net.socketexception: connection reset

Lua5.3版GC机制理解_lua5.3 gc-程序员宅基地

文章浏览阅读8.3k次,点赞8次,收藏42次。目录1.Lua垃圾回收算法原理简述2.Lua垃圾回收中的三种颜色3.Lua垃圾回收详细过程4.步骤源码详解4.1新建对象阶段4.2触发条件4.3 GC函数状态机4.4标记阶段4.5清除阶段5.总结参考资料lua垃圾回收(Garbage Collect)是lua中一个比较重要的部分。由于lua源码版本变迁,目前大多数有关这个方面的文章都还是基于lua5.1版本,有一定的滞后性。因此本文通过参考当前..._lua5.3 gc

手机能打开的表白代码_能远程打开,各种手机电脑进行监控操作,最新黑科技...-程序员宅基地

文章浏览阅读511次。最近家中的潮人,老妈闲着没事干,开始学玩电脑,引起他的各种好奇心。如看看新闻,上上微信或做做其他的事情。但意料之中的是电脑上会莫名出现各种问题?不翼而飞的图标?照片又不见了?文件被删了,卡机或者黑屏,无声音了,等等问题。常常让她束手无策,求助于我,可惜在电话中说不清,往往只能苦等我回家后才能解决,那种开心乐趣一下子消失了。想想,这样也不是办法啊, 于是,我潜心寻找了两款优秀的远程控制软件。两款软件...

成功Ubuntu18.04 ROS melodic安装Cartograhper+Ceres1.13.0,以及错误总结_ros18.04 安装ca-程序员宅基地

文章浏览阅读1.8k次。二.初始化工作空间三.设置下载地址四.下载功能包此处可能会报错,请看:rosdep update遇到ERROR: error loading sources list: The read operation timed out问题_DD᭄ꦿng的博客-程序员宅基地接下来一次安装所有功能包,注意对应ROS版本 五.编译功能包isolated:单独编译各个功能包,每个功能包之间不产生依赖。编译过程时间比较长,可能需要几分钟时间。此处可能会报错:缺少absl依赖包_ros18.04 安装ca

Harbor2.2.1配置(trivy扫描器、镜像签名)_init error: db error: failed to download vulnerabi-程序员宅基地

文章浏览阅读4.1k次,点赞3次,收藏7次。Haobor2.2.1配置(trivy扫描器、镜像签名)docker-compose下载https://github.com/docker/compose/releases安装cp docker-compose /usr/local/binchmod +x /usr/local/bin/docker-composeharbor下载https://github.com/goharbor/harbor/releases解压tar xf xxx.tgx配置harbor根下建立:mkd_init error: db error: failed to download vulnerability db: database download

推荐文章

热门文章

相关标签