数据结构作业复盘1:字符串疑难杂症小汇总(字符串赋值,指针数组...)

news2024/11/16 9:41:24

学校里开始上数据结构了,一开始是从C语言一些相关的基础开始讲起。第一次作业主要是字符串相关的基础知识以及编程题目。先做了一部分,整理了一下一些字符串隐含的知识和一些易误易混的概念,算是给自己的一个复盘和归纳。

strcpy函数相关

首先来看一下这段代码

char s[7]="abcdef",a[4]="ABC";

strcpy(s,a);

printf("%s,s);

 一开始的时候我以为会输出ABCdef,但是只输出了ABC。相信应该也会有人和我一样犯这种错误,本质上还是对strcpy本质不了解。本质上其实是把a的首地址复制到了s上,所以打印的时候自然不会把s的内容也给输出出来。

那我们不妨把a的长度变为9,变成ASDFGHJK(注意还有个\0),再进行复制后,输出的s竟然还是ASDFGHJK,这就说明了一个问题:复制地址的时候,目标字符串(前者s)的长度和原字符串(后者a)的长度并不会影响复制,即使前者的长度比后者短,依旧可完整的输出原字符串(a)。这体现了地址传递与值传递的差异所在。

同时,通过阅读《C Primer Plus》,我还了解到了strcpy函数另外的几个特点:

1.strcpy的返回值是char*类型,具体来说是其中第一个参数的地址,比如:strcpy(s+2,a);返回的就是s+2这个指针。

2.第一个参数不用指向目标字符串的首地址,就像上面的例子,可以使s+2,这样我们可以进行在数组的中部进行插入,值得注意的是,在中部插入之后,原来字符串的后半部分也是不会再有的了,全部都是新复制进来的字符串

3.strcpy函数如果要进行复制的话,其目标字符串指针必须指明地址,否则将指向一个不定的位置造成错误。

4.声明一个数组(char s[2])会自动为你分配内存,但是仅声明一个指针(char*s)不会给存储数据用的空间,仅仅会给一个存储地址的空间。

5.假如你是给字符串数组复制了一个常量字符串,那么后面你就不能在对他进行修改了。比如以下代码就会报错:

char sr[5];
strcpy(sr,"qwer");
sr="qq";

关于字符串,字符数组的赋值问题

来看下面的代码

char a[3];
char b[]="china";
a=b;
printf("%s",a);

乍一看上去好像没有什么问题 ,但是编译会报错。

所以我们来总结一下有关字符串,字符指针的赋值问题。

参考文章:c语言中不能将字符串赋值给字符数组,c - "error:对具有数组类型的表达式的赋值 error"

1.这个问题翻译过来是对具有数组类型的表达式的赋值 ,也就是说,作为一个左值,数组类型是不可以被进行赋值的,这个是c11的规定,就按照规定来就好了。

2.char a[10]="hello";这个语句是正确的,从中我的理解是:如果初始化和数组声明在同时进行,是不会出问题的,此时虽然左边是数组类型,但是右边的字符串不再是常量,而是被理解为变量;但是如果先声明数组再进行初始化就会有问题,这时我们进行的是赋值操作,此时右边的字符串就是一个常量了

3.如果声明的是char s[12],在后面的时候就会把s理解为数组类型;如果声明的是char*s,那后面就会把s理解为指针,数组是不能被进行赋值的,而对于指针而言,如果它作为左值,无论右边是数组的首地址还是纯粹的指针,都是正确的。下面的代码都是正确的。

 赋值时的长度问题

来看下面的代码:

char a[3];strcpy(a,"qwerty");
char b[3]="china";

如果将他们两个进行输出,会产生什么结果呢?

 所以根据这个我们来总结一下不同方法赋值的长度问题:

1.如果使用strcpy函数,那么,无论前面的长度是多少,都是可以的,因为本质上复制的是字符串的地址,与存储空间无关。

2.如果直接将字符串赋值给字符数组,那么假如字符数组没有足够长的空间,就会把字符串进行截断,只保留它的空间所能容纳的长度。

字符串结尾‘\0’问题的研究

这篇文章的大佬讲的很细致了,链接在这:字符串结束符'\0' -何时自动加- 字符串定义方法

我在这里还是自己再总结一遍加深印象:

如果使用字符数组进行对字符串的定义:

1.char s[5]={"ABCDE"};这种方法不会给字符串末尾加上‘\0’。如果字符串长度等于数组所声明的长度,他是不会加上‘\0’的。

2.char s[10]={"ABCDE"};字符串长度小于数组所声明的长度,会把还未初始化的元素自动变成‘\0’,也就是说后面五个元素全部都是'\0'。

3.char s[]="ABCDE";一开始没有声明数组长度,进行赋值以后,会在后面加上'\0'。对比1,我试了一下,打印sizeof(s)的话,第一种是5,而第三种是6,这说明第三种方法后面有‘\0’而第一种没有。

4.char s[]={'A','B','C',‘D’,‘E’};这种方法相当于一个字符一个字符的赋值,所以也不会加上‘\0’.

5.char s[10]={'A','B','C',‘D’,‘E’};和前面的3类似,后面五个会被初始化为‘\0’。

如果使用字符指针对字符串进行定义

使用指针的话,就没什么大问题了,后面一定是会加上‘\0’的,前面说过,字符指针作为左值是既可以初始化(char* s=“qwert”),又可以直接用自己赋值的(char*s;s=“qwert”)而字符数组只能够进行前者(char s[10]="qwert"),不能够进行后者(char s[10]; s="qwert"),如果想要赋值,必须使用strcpy函数。

转义字符的小问题

来看代码

char s[]="\t\v\\\0wwww";

printf("%d",strlen(c));

 输出的长度是3,我们知道\0是字符串的终止符,所以前面是字符串的内容,关于长度是三这个问题,总结一下:

1.\  作为C语言中的转义字符,是用来表达在ASCII码表中不可见字符和控制符的。类似于\t,\v,\n,他们是控制符,如果你在ASCII表里去寻找这些字符,他们是不会以\t,\v,\n的形式出现的。因此如果想要输出他们,就需要使用转义字符和别的字母一起来实现控制符的意思。这些控制符是作为一个整体存在的,也就是说\t,\v是只占一个字符的位置的。

2.\还有的功能是转换那些单独打印无法打印的字符的,比如\,",如果你想单独在printf的引号中去打印这些字符,是无法输出的,这就需要转义字符了。比如\\,实际上最后只输出一个\。

综上,上面的字符串相当于是有\t,\v,\三个字符,注意,strlen是不会读取‘\0’的,而sizeof才会输出包含‘\0’的长度。

指针数组与数组指针

char* s[]={"abc","ABC","QWE","qqqqq"};

上面的这个数组与之前的有所区别,我们可以看到,s前面的类型是char*,也就是说,存放在这个数组里的是指向char的指针,也就是里面字符串的首地址。我们可以把这个理解为一个二维的字符串数组。

下面来介绍几个输出的内容:

1.*(s+2)或者s[2],是字符串的首地址,用%s来输出,代表的是QWE这整个字符串。 

2.*((*(s+2))+2)或者s[2][2]输出的是E这个字符。

3.*s[2]或者**(s+2),用%c输出,代表的是Q这个字符,也就是说,把首地址所指向的字符给打印了出来。(这个点容易混淆)

归根到底,s+i代表的是指向字符串的指针的指针(有点拗口),是一个二级指针s[i]代表的是指向字符串的指针,是一个一级指针。从此延伸,加上*就是一层一层的取内容了。比如如果想用s+i来取出字符串本身,那就要两个*,第一个*代表的是字符串的首地址,第二个*才是字符串本身。

char(*s)[10];

这里的s代表的是这样的含义:首先s是一个指针,去掉*和变量名之后,剩下char[10],也就是说,s所指向的内容是一个长度为10的char型数组,指向的是数组!

我们可以把它叫做行指针,因为在二维的数组中,每一行都是一个一维数组,而这个指针正是指向一个一维的数组的。 

注意数组指针和数组的首地址的区别。数组指针本身虽然也是数组首地址,两者仅仅是在数值上相等,两者所指向的内容并不一样。数组指针指向的是数组整体,而数组首地址如果不是字符数组,而是其他类型比如整型数组的时候,指向的仅仅是第一个元素。比如以下代码:

char str[3][10]={"qwertyuiop","qwr","uiop"};
char(*s)[10];
s=str;
s+=2;
printf("%s",s);

最后输出的时候,输出的是uiop,也就是说,对于一个数组指针,它的加减是以所指向的数组长度决定的,每加一次,他都会跳过整个数组的长度,如果在二维数组中的话,就相当于他跳到了下一行 。

相比之下,普通的数组首地址如果加1的话,由于它所指向的是首元素,因此只会跳到下一个元素去,不会把整个数组越过。

也就是说,指针的加减是由指针所指向的数据类型决定的。加减都会以数据的字节数为单位。这从另外一个角度展示了数组指针和数组首地址的区别。

好了以上就是我自己整理过的关于字符串的很多疑难杂症和边边角角,希望对大家有帮助。

整理不易,最后给个一键三连再走吧~~~

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux系统编程之多线程

目录 1、进程与线程 2、线程的优势与使用理由 3、多线程的使用 3.1 线程的使用 1.线程创建函数 2.线程退出函数 3.线程的等待 4.线程脱离 5. 线程ID获取及比较 6.示例 3.2 互斥锁的应用 1.互斥锁相关API 2.示例 3.3 条件变量的使用 1. 创建及销毁条件变量 2. 等待…

数字化转型导师坚鹏:证券公司数字化领导力提升之道

证券公司数字化领导力提升之道 ——融合中西智慧,践行知行合一思想,实现知行果合一 课程背景: 很多证券公司存在以下问题: 不知道证券公司数字化思维如何提升? 不清楚证券公司数字化领导力模型内涵?…

加密与安全_探索数字证书

文章目录 Pre概述使用keytool生成证书使用Openssl生成证书 (推荐)证书的吊销小结 Pre PKI - 借助Nginx 实现Https 服务端单向认证、服务端客户端双向认证 PKI - 04 证书授权颁发机构(CA) & 数字证书 PKI - 数字签名与数字证…

土壤侵蚀量化评估

根据之前的文章,已经算出了R、K、LS、C、P 现在计算土壤侵蚀,将几个前期制作好的因子的TIFF文件,用栅格计算器相乘 发现局部地区存在轻度侵蚀,大部分区域是微度侵蚀 然后对比了一下范围 其中的几个因子都在文献范围内,说明计算结果并未出错,可能就是研究区正常范围和结…

《数字图像处理(MATLAB版)》相关算法代码及其分析(1)

目录 1 自适应中值滤波算法 1.1 函数定义 1.2 输入参数检查 1.3 初始化 1.4 自适应中值滤波过程 1.5 处理剩余未处理的像素 1.6 总结 2 计算输入数组的平均值 2.1 函数定义 2.2 注释 2.3 输入验证 2.4 计算平均值 2.5 总结 3 基于高斯模型的贝叶斯分类器 3.1 函…

【搭建 Hbase 集群】

搭建 Hbase 集群 一、准备工作二、三台服务器之间的 SSH 免密登录1.修改hosts文件添加DNS映射2.在每台服务器上生成 SSH 密钥对3.将公共密钥(通常为 ~/.ssh/id_rsa.pub)复制到目标服务器上4.从本地使用 SSH 命令无需密码连接到目标服务器 二、安装JDK1.执…

Linux/Docker 修改系统时区

目录 1. Linux 系统1.1 通过 timedatectl 命令操作1.2 直接修改 /etc/localtime 文件 2. Docker 容器中的 Linux 操作环境: CentOS / AlmaOSMySQL Docker 镜像 1. Linux 系统 1.1 通过 timedatectl 命令操作 使用 timedatectl list-timezones 命令列出可用的时区…

Learning from Unlabeled 3D Environments forVision-and-Language Navigation

这篇论文是关于高级指令的 摘要 在视觉和语言导航 (VLN) 中,实体代理需要按照自然语言指令在真实的 3D 环境中进行导航。现有 VLN 方法的一个主要瓶颈是缺乏足够的训练数据,导致对未见过的环境的泛化效果不理想。虽然 VLN 数据通常是手动收集的&#x…

2024年 前端JavaScript Web APIs 第一天 笔记

1.1 -声明变量const优先 1.2 -DOM树和DOM对象 1.3 -获取DOIM元素 1.4 -DOM修改元素内容以及年会抽奖 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta http-equiv"X-UA-Compatible" content&quo…

初识面相对象深入理解、构造方法--学习JavaEE的day12

day12 一、初识面相对象深入理解 需求&#xff1a; 创建人类的对象&#xff0c;并操作对象 分析&#xff1a; 人类 - Person 属性&#xff1a;name、sex、age 方法&#xff1a;eat、sleep 场景&#xff1a;创建多个对象&#xff0c;去操作对象 public class Person {//成员变…

9、taocms代码审计

一、XSS 1、DOM型xss 限制 无复现 payload: aa)alert(1)( 触发的参数&#xff1a;name代码 根据路由找到对应的文件&#xff0c;在api.php里接受全局变量action&#xff0c;最终赋值给$m,判断 如果$m不在数组就结束&#xff0c;新建方法复制给$model。检查类的方法是否存…

2024 年广东省职业院校技能大赛(高职组)“云计算应用”赛项样题 2

#需要资源或有问题的&#xff0c;可私博主&#xff01;&#xff01;&#xff01; #需要资源或有问题的&#xff0c;可私博主&#xff01;&#xff01;&#xff01; #需要资源或有问题的&#xff0c;可私博主&#xff01;&#xff01;&#xff01; 某企业根据自身业务需求&#…

【全局异常处理记录】⭐️通过自定义全局处理器有效统一各种异常并记录

目录 前言 方案 示例 测试 总结 前言 朋友们大家好啊&#xff0c;随着项目的进行&#xff0c;接口也是越来越多了&#xff0c;每个接口无论调用成功与否&#xff0c;都要有相应的应对措施&#xff0c;总不能出错的时候返回一堆异常信息给调用者&#xff0c;所以每个接口都…

Python算法100例-3.2 水仙花数

完整源代码项目地址&#xff0c;关注博主私信源代码后可获取 1.问题描述2.问题分析3.算法设计4.确定程序框架5.完整的程序6.问题拓展7.巧用字符串技巧 1&#xff0e;问题描述 输出所有的“水仙花数”。所谓的“水仙花数”是指一个三位数&#xff0c;其各位数字的立方和等于该…

【机器学习】有监督学习算法之:支持向量机

支持向量机 1、引言2、决策树2.1 定义2.2 原理2.3 实现方式2.4 算法公式2.5 代码示例 3、总结 1、引言 小屌丝&#xff1a;鱼哥&#xff0c;泡澡啊。 小鱼&#xff1a;不去 小屌丝&#xff1a;… 此话当真&#xff1f; 小鱼&#xff1a;此话不假 小屌丝&#xff1a;到底去还是…

奔跑吧,前端er!前端五大方向技能罗列,webGL、AI、桌面、游戏

经常看到头条上前端们争论各种框架的优劣&#xff0c;然后相互争吵不休&#xff0c;其实技术也好&#xff0c;框架也好&#xff0c;都是服务于项目需求的&#xff0c;争论的铁子们都站在自己的项目角度来品评工具&#xff0c;肯定是公说公有理婆说婆有理啦。 技术和框架是中性的…

ArrayBlockingQueue 数组阻塞队列 源码阅读

1. 概述 数组阻塞队列 有界的阻塞数组, 容量一旦创建, 无法修改阻塞队列, 队列满的时候, 往队列put数据会被阻塞, 队列空, 取数据也会被阻塞并发安全 2. 数据结构 /** 存储队列元素的数组 */ /** 存储队列元素的数组 */ final Object[] items;/** 队首位置&#xff0c;下一…

【王道操作系统】ch1计算机系统概述-06虚拟机

文章目录 【王道操作系统】ch1计算机系统概述-06虚拟机01传统计算机02虚拟机的基本概念&#xff08;1&#xff09;第一类虚拟机管理程序&#xff08;2&#xff09; 第二类虚拟机管理程序&#xff08;3&#xff09; 两类虚拟机管理程序的对比 【王道操作系统】ch1计算机系统概述…

【Linux系统化学习】线程概念

目录 线程的概念 线程的引出 什么是线程 理解线程比进程更加的轻量化 线程的优点 现成的缺点 线程异常 线程用途 Linux进程VS线程 线程的简单现象 线程的概念 有关操作系统的书籍或者课本都会这样描述线程&#xff1a; 线程是比进程轻量化的一种执行流线程是进程内部…

[SWPUCTF 2021 新生赛]babyrce

先打开环境 分析代码&#xff0c;要给COOKIE赋值admin1 使用hackbar赋值 打开rasalghul.php 分析代码&#xff0c;使用GET传参url&#xff0c;如果url里没有/ /&#xff0c;则赋值给ip&#xff0c;然后通过shell_exec函数得到flag&#xff0c;否则&#xff0c;返回nonono。他…