三、C语言初阶:字符串

2023-11-04

3 字符串

3.1 字符串操作:遍历、赋值、修改

int main(){
    char s[] = "Hello World!";
    // 字符串遍历1
    char* q = s;
    while('\0' != *q){
        printf("%c",*q++);
    }
    printf("\n");
    // 字符串遍历2
    for(int i = 0;'\0' != s[i];i++){
        printf("%c",s[i]);
    }
    printf("\n");

    // 字符串赋值
    char* p;
    p = s; //字符串可以赋值给指针
    // s = p; //指针不允许赋值给字符串

    // 字符串修改
    p[1] = 'A';
    printf("%p\n%p\n",s,p);
    printf("%s\t%s\n",s,p);
    s[2] = 'L';
    printf("%p\n%p\n",s,p);
    printf("%s\t%s\n",s,p);
}
Hello World!
Hello World!
0x7ffc0789c4fb
0x7ffc0789c4fb
HAllo World!	HAllo World!
0x7ffc0789c4fb
0x7ffc0789c4fb
HALlo World!	HALlo World!

3.2 字符串与函数

  • 字符串传参
    字符串传参方式与数组传参方式一样,只不过很多时候不需要传递字符串的长度
    两种传参方式:char* str / char str[]
void print_str(char* str){
    printf("%s\n",str);
}
void print_str2(char str[]){
    printf("%s\n",str);
}
int main(){
    char str[] = "Hello World!";
    print_str(str);
    print_str2(str);
}
  • 字符串返回
    字符串返回只能使用指针char*
    str1和str2拼接
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* Strcat(char* s1,char* s2){
    char *s = malloc(strlen(s1)+strlen(s2)+1);
    int k = 0;
    for(int i = 0;s1[i] != '\0';i++){
        s[k++] = s1[i];
    }
    for(int i = 0;s2[i] != '\0';i++){
        s[k++] = s2[i];
    }
    return s;
}
int main(){
    char str1[] = "Hello";
    char str2[] = "World";
    char* s = Strcat(str1,str2);
    printf("%s\n",s);
}

字符拼接2

#include <stdio.h>
char* Strcat(char* s1,char* s2){
    char* res = s1;
    while('\0' != *s1){
        ++s1;
    }
    while('\0' != *s2){
        *s1++ = *s2++;
    }
    *s1 = '\0';
    return res;
}
int main(){
    char str1[11] = "Hello";
    char str2[] = "World";
    char* s = Strcat(str1,str2);
    printf("%s\n",s);  
}

3.3 字符串指针

数组可以用指针表示
字符数组可以直接初始化字符数组,并且可以赋值给指针。

#include <stdio.h>
int main(){
    char s[] = "Hello World";
    char* p = s;
    printf("%s\n",p);
}

字符串也可以直接赋值给指针,这种指针成为字符串指针

#include <stdio.h>
int main(){
    char* s = "Hello World";
    printf("%s\n",s);
}

3.4 字符串指针 vs 字符数组

1、sizeof与strlen()
2、字符是否可修改
3、地址是否可修改

  • 1、sizeof与strlen()
#include <stdio.h>
#include <string.h>
int main(){
    char* s = "Hello World";
    char s1[] = "Hello World";
    printf("%d\t%d\n",sizeof(s),strlen(s));
    printf("%d\t%d\n",sizeof(s1),strlen(s1));
}
8	11 sizeof(s)为指针s的长度,strlen(s)为字符串的长度
12	11 sizeof(s1)为字符串s1的长度(包含'\0'),strlen(s1)为字符串的长度
  • 2、字符是否可修改
    字符串指针的元素不可以修改
    字符数组的元素可以修改
    char* s = "Hello World";
    char s1[] = "Hello World";
    //*(s+2) = 'L'; //字符串指针不支持修改元素
    s1[2] = 'L'; //字符数组可以修改元素
    printf("%s\n%s\n",s,s1);
//等价
char s[] = "Hello World";
char s[]={'H','e','l','l','o',' ','W','o','r','l','d','\0'};
//等价
char* s = "Hello World";
const char t[]="Hello World"; //看作const型,所以无法修改元素
char* s = t;
  • 3、地址是否可修改
    字符串指针内容可以整体修改
    字符串数组内容无法整体修改
#include <stdio.h>
#include <string.h>
int main(){
    char* p = "Hello";
    char s[] = "Hello";
    p = "World"; //可以修改
    // s = "World"; //无法修改
    printf("%s\n%s\n",p,s);
}
  • 字符串指针和字符数组如何选择
    1、如果需要构造字符串使用数组;如果需要处理字符串使用指针(指向字符数组的指针)。
    2、字符串不需要修改,使用字符串字面量初始化字符串指针。
    3、字符串需要修,改使用字符串字面量初始化字符数组。

3.5 字符串const

  • const字符数组
  • 指向const字符是数组的字符串指针
#include <stdio.h>
#include <string.h>
int main(){
    const char s[] = "Hello World";
    //s[0] = 'h'; //不可修改
    //s[6] = 'w';
    char* p = s;
    printf("%s\n%s\n",s,p);
    *(p+6) = 'w'; //可修改
    *p = 'h';
    printf("%s\n%s\n",s,p); //s和p均被修改
}
Hello World
Hello World
hello world
hello world

结论:决定能否修改的是指针指向的值能否修改,const的限制只针对对应为const的变量。

3.6 字符串函数

  • 字符串比较 strcmp
int strcmp(const char* s1,const char* s2)

s1>s2,返回值>0;
s1<s2,返回值<0;
s1==s2,返回值为0.

  • 字符串拷贝 strcpy
char* strcpy(char* restrict dst,const char* restrict src);

返回值为dst

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

int main(){
    char dst[3] = "cd";
    const char* src = "ab";
    char* res  = strcpy(dst,src);
    printf("%s\t%s\n",dst,res);
    printf("%p\t%p\n",dst,res);
}
ab	ab
0x7ffd7f72fbbd	0x7ffd7f72fbbd
#include <stdio.h>
#include <string.h>

int main(){
    char dst[3] = "cd";
    const char* src = "ab";
    strcpy(dst,src);
    printf("%s\n",dst);
}  
ab
  • 字符串拼接 strcat
#include <stdio.h>
#include <string.h>

int main(){
    char* a = "hello";
    const char* b = "world";
    char res[11];
    strcat(strcat(res,a),b);
    printf("%s\n",res);
}

strcpy和strcat都会有安全问题:dst空间不足,出现越界。

  • 字符查找
#include <stdio.h>
#include <string.h>

int main(){
    const char* s1 = "abcdef";
    const char* s2 = "cd";
    char* c = strstr(s1,s2);
    printf("%s\n",c);
    printf("%p\t%p\n",c,s1+2);
}
cdef
0x40072a	0x40072a

返回地址为s2在s1中首次出现的地址

3.7 空字符串

#include <stdio.h>
#include <string.h>
int main(){
    char str[10] = "";
    char str2[] = "";
    printf("%d\t%d\n",strlen(str),strlen(str2));
    printf("%d\t%d\n",sizeof(str),sizeof(str2));
    // char* str3; //错误,使用未初始化的char*,若指针定义时候无法确定初始值,使用NULL初始化指针
    // printf("%s\n",str3);
}
0	0
10	1
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

三、C语言初阶:字符串 的相关文章

  • mod_perl 无法看到 /tmp 中的文件

    我有一些 mod perl 代码试图访问 tmp 下的文件 但它抛出 没有这样的文件或目录 错误 我在代码中添加了一个 ls al tmp 来查看 Perl 在目录中看到的内容 它只给了我 和 drwxrwxrwt 2 root root
  • 警告构建使用导出符号的内核模块

    我有两个内核模块 例如 modA 和 modB modA 导出一个符号EXPORT SYMBOL symA modB 使用它 我有标题modA h对于modA extern void symA int param and in modB c
  • 如何获取文件夹的大小,包括稀疏文件的表观大小? (du太慢了)

    我有一个包含很多KVM qcow2文件的文件夹 它们都是稀疏文件 现在我需要获取文件夹的总大小 qcow2 文件大小应计为表观大小 而不是实际大小 例如 图片 c9f38caf104b4d338cc1bbdd640dca89 qcow2 文
  • 使用 xargs 时如何获取退出代码(并行)

    我制作了一个用于启动并行 rsync 进程的脚本 bin bash LIST 1 DEST DIR 2 RSYNC OPTS 3 echo rsyncing From SRC DIR To DEST DIR RSYNC OPTS RSYNC
  • Bash 脚本错误 [重复]

    这个问题在这里已经有答案了 我想知道下面的脚本有什么错误 我收到错误为 command not foundh line 1 command not foundh line 2 其连续的 我试过添加 但现在工作请告诉我该怎么做 bin bas
  • 如何从 swagger 文档生成静态 html 文件?

    我创建了一个 Swagger 文档yaml文件位于 api swagger swagger yaml 现在我想分享一个静态 HTML 文档及其定义 但它已在招摇项目 https github com swagger api swagger
  • 多线程进程的线程ID可以与另一个正在运行的进程的进程ID相同吗?

    我正在尝试找到一种方法来唯一标识多进程环境中的线程 我有一个服务器 它跟踪连接到它的不同进程 其中一些是多线程的 一些不是 为了识别多线程连接中的线程 我使用线程 ID 作为唯一标识符 在任何给定时间最多有 1 个多线程进程连接 我的问题是
  • 如何像C99一样使用make和编译?

    我正在尝试使用 Makefile 编译 Linux 内核模块 obj m main o all make C lib modules shell uname r build M PWD modules clean make C lib mo
  • 容器上的“container_memory_working_set_bytes”指标和 OOM-killer 之间有什么关系?

    我试图找出并理解 OOM killer 如何在容器上工作 为了弄清楚这一点 我读了很多文章 发现 OOM killer 会根据oom score And oom score是由oom score adj以及该进程的内存使用情况 有两个指标c
  • 仅为我自己禁用和重新启用地址空间布局随机化

    我想在我的系统 Ubuntu Gnu Linux 2 6 32 41 server 上禁用地址空间布局随机化 ASLR 但是 如果我使用 sysctl w kernel randomize va space 0 我认为这一更改将影响系统上的
  • C:运行系统命令并获取输出? [复制]

    这个问题在这里已经有答案了 我想在 Linux 中运行一个命令并获取其输出内容的返回文本 但我do not想要将此文本打印到屏幕上 有没有比制作临时文件更优雅的方法 你想要 popen http linux die net man 3 po
  • 如何从内部找到C++ Linux程序的完整路径?

    我有这个要求 我需要从内部找到 C 程序的完整路径 对于Windows 我有以下解决方案 argv 0 可能包含也可能不包含完整路径 但我需要确定 TCHAR drive MAX DRIVE dir MAX DIR base MAX FNA
  • 如何在 arago 项目构建中编写自己的食谱包

    我如何在 arago 项目构建中编写自己的食谱包 我知道它可以是 bitbake 文件 但我怎么写 不知道 我在互联网上搜索 但未能找到任何好的来源 有人可以给我提供链接或示例来开始吗 RegardsLinux 学习者 使用 Bitbake
  • 是否有一种异步信号安全的方式来读取 Linux 上的目录列表?

    SUSv4 http pubs opengroup org onlinepubs 9699919799 functions V2 chap02 html tag 15 04 03 03未在其异步信号安全函数列表中列出 opendir rea
  • 如何删除名称最大的目录?

    我有一个包含子目录的目录 其中一些名称是数字 不看的话 我不知道数字是多少 如何删除名称最大的子目录 我认为解决方案可能会将子目录按相反顺序排序 并选择以数字开头的第一个子目录 但我不知道该怎么做 感谢您的帮助 cd yourdir go
  • 您会为 Linux 推荐哪种甘特图/项目管理工具? [关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 我需要一个可在 Linux 中运行并具有甘特图的项目管理工具 它不一定是免费的 只是不贵 我不在乎它如何存储我提供的信息 只要我可以访问它即可 我一定
  • 不必记住我要拉和推的分支的最佳别名是什么?

    这里非常懒 不喜欢输入太多 特别不喜欢记住我在哪个分支上拉出和推入 我经常犯这样的错误git pull来自非主分支 或者更糟糕的是 进行推送并且目标分支不正确 并且我留下了未推送或未提交的更改 我在我的 bashrc以下别名可以提供帮助 a
  • 从 S3 存储桶下载 300 万个对象的最快方法

    我尝试过使用 Python boto 多处理 S3cmd 和 J3tset 但都在努力解决 有什么建议 也许是您一直在使用的现成脚本或我不知道的其他方式 EDIT eventlet boto 是一个有价值的解决方案 如下所述 在这里找到了一
  • 真实设备中的 Android strace

    我有以下情况 我想监控Android手机上的系统调用 所以 我编写了一个脚本来做到这一点 使用 Android 模拟器可以完美地工作 将应用程序的痕迹写入我的 Ubuntu 上的特定文件中 问题是当我连接一个真实的手机来分析它时 它在结果文
  • 如何将发布档案转换为 git repo

    我有一个发布档案列表 MyProject 0 9 zip MyProject 1 0 zip MyProject 1 3 tar gz MyProject 2 0 tar gz 每个文件都包含一个与存档同名的文件夹 不带文件扩展名 其中包含

随机推荐

  • Docker root用户的pip使用方法

    Docker下root用户 pip install XX 显示pip命令不存在 原始目标 pip install XX pip install root user action ignore XX 要安装的包 参考 WARNING Runn
  • JavaScript中的正则表达式

    ECMAScript 通过RegExp类型来支持正则表达式 测试的方法 pattern test str 或 pattern exec str 其中str 是待匹配的字符串 pattern 是正则表达式 JavaScript 中的正则表达式
  • 找不到msvcp140.dll无法继续执行代码怎么解决?分享三个解决方法

    当你在运行某个程序或游戏时遇到msvcp140 dll缺失的错误提示 你可能会感到困惑和烦恼 在修复msvcp140 dll的过程中 我遇到了一些挑战 但最终成功解决了这个问题 以下是我总结的三个解决方法 希望能帮助你解决这个问题 找不到m
  • sklearn中的归一化方法StandardScaler中的fit、transform和fit_transform

    StandardScaler类 常用的数据归一化方式 减去平均值 然后通过标准差映射到均至为0的空间内 系统会记录每个输入参数的平均数和标准差 以便数据可以还原 sklearn preprocessing StandardScaler能够轻
  • 【极速版】vite安装配置ceisum教程

    Hello大家好 今天带来的是vite版本的cesium的安装教程 借助一个国人大佬写的插件vite plugin cesium 安装非常简单快捷 一起来看看吧 1 安装vite插件 官网 https github com nshen vi
  • opencv遍历彩色图像、灰度图像像素值的方法

    https www bbsmax com A RnJWZb2ozq
  • 嵌套滑动学习

    我们知道两个同一方向的可以滑动的View 如果不做任何处理 会出现滑动冲突 处理滑动冲突我们有内部和外部拦截法 如果有朋友还不知道事件分发的原理可以看包括滑动冲突的拦截事件分发源码的学习分享 处理滑动冲突之后还是存在缺陷 比如一次滑动操作父
  • JavaScript面试题

    1 数据类型有哪几种 检测方法是什么 基本数据类型 ES5 Number Boolean String Undefined Null ES6新增 symbol 引用数据类型 Object 检测方法4种 1 Object prototype
  • 无向图和有向图

    1 无向图 两点之间的边没有方向 点 Vertex 简称V 边 Edge 简称E 2 有向图 两点之间的边是有方向的 有多少边以某点为出发点 则有多少的出度 同理有多少边以某点为终点则有多少入度 度 出度 入度 3 邻接矩阵 用G V E
  • 几种常用回归算法的比较

    type introduce example k nearest neighbors 原理 是一种常用的监督学习方法 给定测试样本 基于某种距离度量找出训练集中与其最靠近的k个训练样本 然后基于这k个 邻居 的信息来进行预测 判定方法 1
  • 98个创新JAVA计算机毕业设计项目,通俗易懂,被朋友羡慕了

    面对如海的计算机毕业设计题目 你是否感到困惑 不知如何选择一个具有创新性的项目 今天 我们将为大四的同学们分享一些毕业设计项目 希望能对你的毕业设计有所帮助 一 成品列表 以下所有springboot框架项目的源码博主已经打包好上传到百du
  • Visual Studio对代码进行注释

    1 Ctrl K C 可以同时按住三键 也已分开来按Ctrl K Ctrl C 对选中的代码段进行注释 Ctrl K U 可以同时按住三键 也已分开来按Ctrl K Ctrl U 对选中的代码段取消注释 2 Ctrl Shift 切换块注释
  • Nacos 入门应用

    Nacos入门应用 一 概述 Nacos提供了统一配置管理 服务发现与注册 其中服务注册和发现的功能 相当于dubbo里面使用到的zookeeper 或者spring cloud里面应用到的eureka 之前在Spring Cloud Eu
  • lucene 目录结构简单介绍

    今天回顾了一下lucene 搜索引擎的基础技术 有必要总结一下 搜索引擎的相关知识点 lucene 目录结构 如下图所示 lucene 目录结构详细说明 core Lucene核心类库 analyzers common 不同语言和领域通用的
  • KNN算法实例——鸢尾花种类预测

    线性回归的scikit learn实现 scikit learn中提供了一个KNeighborClassifier类来实现k近邻法分类模型 方法 fit X y 训练模型 predict 使用模型来预测 返回待预测样本的标记 score X
  • 使用Java实现斗地主发牌逻辑(简单基础版)

    大家好 我是垃圾佬 一个正在学Java的 无业游民 最近复习到了Map 集合 我觉得斗地主发牌这个案例来练习Map集合还是非常好的 话不多说先上图解 1 斗地主发牌 图解 图解 1 首先定义扑克牌映射表 按编号的顺序从小到大依次是牌面的从大
  • c 回调函数&函数指针

    概述 之前写Android程序的时候 我们常常对一些异步操作 或事件监听 都会通过回调函数 回调处理结果 最近写c c 项目的时候 也需要实现回调函数 却不知道怎么下手 经过自己学习 了解到c c 可以通过函数指针实现回调函数的功能 在此做
  • 2022年9月27日每日一练 选择客栈 数学-简单

    题目 丽江河边有 n 家很有特色的客栈 客栈按照其位置顺序从 1 到 n 编号 每家客栈都按照某一种色调进行装饰 总共 k 种 用整数 0 k 1 表示 且每家客栈都设有一家咖啡店 每家咖啡店均有各自的最低消费 两位游客一起去丽江旅游 他们
  • 华为OD机试真题-木板【2023Q1】【JAVA、Python、C++】

    题目描述 小明有n块木板 第块木板的长度为a i 小明买了一块长度为m的木料 这块木料可以切割成任意块 拼接到已有的木板上 用来加长木板 小明想让最短的木板尽量长 请问小明加长木板后 最短木板的长度最大可以为多少 输入描述 输入的第一行包含
  • 三、C语言初阶:字符串

    3 字符串 3 1 字符串操作 遍历 赋值 修改 int main char s Hello World 字符串遍历1 char q s while 0 q printf c q printf n 字符串遍历2 for int i 0 0