C语言之通过指针操作字符串

下面我们来学习通过指针来灵活操作字符串的方法


判断字符串的长度

我们用对指针的遍历来实现判断字符串的长度

#include <stdio.h>
int str_length(const char*s)
{int len = 0;while(*s++)len++;return len;
}
int main()
{char str[128];printf("请输入字符:");scanf("%s", str);printf("输入的字符串\"%s\"长度为%d\n", str, str_length(str));return 0;
}

在函数形参的声明中由使用[ ]变为*,这些声明方式是一样的,只是表面上的一些变化,实质上并没有什么变化。

程序中发生实质性变化的事函数体,让我们结合下图来看(以输入的字符串five为例):

b5456038d8ff4898813592b00639d688.png

函数开始执行时,s指向所接收的字符串str第一个字符str[0],即“five”中的f,当*s为0(null字符)时,while循环结束,因此在没有遇到null字符时,指针s和变量len都会递增。

指针s在判断循环表达式中递增,变量len在循环体中递增

注意

指向数组元素的指针递增后指向下一个元素,递减后指向上一个元素。 

p++即p=p+1;p--=p-1

这里的str_length函数中并没有使用下标运算符,而是使用了指针运算符 *和递增运算符++,这种技巧很常用,大家一定要好好理解。


字符串的复制

#include<stdio.h>char* str_copy(char *d, const char *s)
{char *t = d;while(*d++ = *s++);return t;
}
int main()
{char str[128] = "ABC";char tmp[128];printf("str = \"%s\"\n", str);printf("复制的是:");scanf("%s", tmp);str_copy(str, tmp);puts("复制了。");printf("str = \"%s\"\n", str);return 0;
}

我们首先来看str_copy函数中内实现字符串复制功能的while语句,控制表达式*d++ = *s++是比较复杂的。后置递增运算符++在对左操作数进行判定后会进行递增,因此控制表达式的判定和执行分为两个阶段(以str=ABC, tmp=abc为例):

①通过*d = *s进行赋值

指针s指向的字符会赋值给指针d指向的字符

②指针d和指针s递增

赋值结束后,指针d和s分别指向下一个字符。

③结果判断

对指向的指针所指向的字符进行判断,若指向的是null字符,while语句循环结束,否则就重复①和②两步直至指向null字符。

我们用图来表示:(剩下的步骤是重复的)

19ee677635374b5397054f89544f0b3b.png

复制时不同语句的写法

 我们还可以对指针d和s使用下标运算符,如下:

while(d[i] = s[i]);
i++;

与上面代码相比,该上面使用指针运算符的程序具有以下优点:

不需要用于下标的变量i,可以节约少量内存

运行效率有望更高


不正确的字符串赋值

下面的程序与上面的程序大致相同,str_copy函数一样,main函数有所不同:

#include<stdio.h>char* str_copy(char *d, const char *s)
{char *t = d;while(*d++ = *s++);return t;
}
int main()
{char* str = "ABC";char tmp[128];printf("str = \"%s\"\n", str);printf("复制的是:");scanf("%s", tmp);str_copy(str, tmp);puts("复制了。");printf("str = \"%s\"\n", str);return 0;
}

这个程序犯了两个错误

改写了字符串字面量

这个程序改写了指针str指向的字符串字面量的内容,但是,是否可以更改是取决于编译器,在不支持改写字符串字面量的编译器中,该程序不能正常运行。

可能会写入非空的内存空间

指针str指向了字符串字面量的“ABC”中的第一个字符,该字符串包括null字符在内长度为4位,在进行复制时,不能保证复制所需要的内存空间是空着的,在该内存空间甚至是保存着系统的关键信息

所以,进行复制时有可能会破坏其他变量的值,甚至会导致程序运行异常。

注意

不要改写字符串字面量,也不用对超过字符串字面量的内存单元进行写入操作。


返回指针的函数

str_copy函数的返回值类型是指向char型变量的指针型,只要是用到这种数据类型的地方都能调用该函数。

函数的返回值是t,它复制于传入的形参t,这就意味着函数返回的是“指向复制后的字符串中的第一个字符的指针”。


关于指针的基础知识学习我们就已经学习完了,在学完基础篇后我们会进行更加深入的学习,来打好更加深厚的基础。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/412255.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

低代码开发:解锁数字化转型新维度

在信息化浪潮中&#xff0c;企业正面临着前所未有的挑战与机遇。一方面&#xff0c;市场环境瞬息万变&#xff0c;业务需求迭代频繁&#xff0c;对快速应用开发提出了更高要求&#xff1b;另一方面&#xff0c;传统软件开发模式受限于高成本、长周期等瓶颈&#xff0c;难以满足…

【深度学习】Anaconda3 + PyCharm 的环境配置 3:GitHub 项目运行前的环境配置

前言 文章性质&#xff1a;实操记录 &#x1f4bb; 主要内容&#xff1a;主要记录了运行 GitHub 项目前的环境配置过程&#xff0c;包括创建并激活新的虚拟环境、安装 torch 和 torchvision&#xff0c;在 PyCharm 中使用新建的虚拟环境&#xff0c;根据项目源代码提供的 requi…

前端react入门day04-useEffect与Hook函数

(创作不易&#xff0c;感谢有你&#xff0c;你的支持&#xff0c;就是我前行的最大动力&#xff0c;如果看完对你有帮助&#xff0c;请留下您的足迹&#xff09; 目录 useEffect 的使用 useEffect 的概念理解 useEffect 依赖项参数说明 useEffect — 清除副作用 自定义Ho…

文件操作解析(一)

前言 很多非计科的专业并未对文件操作这点做出详细解释&#xff0c;今天复习到这里就想趁此机会记录一下自己学到的知识&#xff0c;也希望能对大家有所帮助。 一.为什么使用文件 如果没有⽂件&#xff0c;我们写的程序的数据是存储在电脑的 内存中&#xff0c; 如果程序退出…

力扣刷MySQL-第四弹(详细讲解)

&#x1f389;欢迎您来到我的MySQL基础复习专栏 ☆* o(≧▽≦)o *☆哈喽~我是小小恶斯法克&#x1f379; ✨博客主页&#xff1a;小小恶斯法克的博客 &#x1f388;该系列文章专栏&#xff1a;力扣刷题讲解-MySQL &#x1f379;文章作者技术和水平很有限&#xff0c;如果文中出…

探索自动化测试断言:提升测试效率与质量的关键!

前言 断言在自动化测试中起着关键的作用&#xff0c;它是验证测试结果是否符合预期的重要手段。如果在自动化测试过程中忽视了断言&#xff0c;那么这个测试就失去了其本质的意义&#xff0c;因为我们无法得知测试结果是否达到了预期的效果。因此&#xff0c;断言在自动化测试…

CSC8021_computer network_The Application Layer

The Role of the Application layer The Application layer is the interface between the network and its users › It contains network services (e.g. DNS) › It contains user applications (e.g. email, web browsing&#xff09; Domain Name System (DNS) › The …

Java 基础知识-反射

大家好我是苏麟 , 今天聊聊反射 . 反射 ​专业的解释&#xff1a; 反射允许对封装类的字段&#xff0c;方法和构造函数的信息进行编程访问 是在运行状态中&#xff0c;对于任意一个类&#xff0c;都能够知道这个类的所有属性和方法 ​ 对于任意一个对象&#xff0c;都能够调…

数据库作业三

1.创建student和score表 2.为student表和score表增加记录 3.查询student表的所有记录 4.查询student表的第2条到4条记录 5.从student表查询所有学生的学号&#xff08;id&#xff09;、姓名&#xff08;name&#xff09;和院系&#xff08;department&#xff09;的信息 6.从st…

Unity中四元数常用的方法

单位四元数 #region 单位四元数print(Quaternion.identity);testObj.rotation Quaternion.identity;//初始化对象时可能会用来赋值Instantiate(testObj,Vector3.zero,Quaternion.identity);#endregion 插值运算 #region 插值运算 //四元数中也提供了如同Vector3的插值运算 /…

命令行参数环境变量和进程空间地址

文章目录 命令行参数环境变量进程地址空间 正文开始前给大家推荐个网站&#xff0c;前些天发现了一个巨牛的 人工智能学习网站&#xff0c; 通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。 点击跳转到网站。 命令行参数 什么是命令行参数&#xff1f; 我…

架设一台NFS服务器,并按照以下要求配置

1、开放/nfs/shared目录&#xff0c;供所有用户查询资料 2、开放/nfs/upload目录&#xff0c;为192.168.xxx.0/24网段主机可以上传目录&#xff0c; 并将所有用户及所属的组映射为nfs-upload,其UID和GID均为210 3、将/home/tom目录仅共享给192.168.xxx.xxx这台主机&#xff0c;…