字符串--字符指针、字符串的访问和输入/输出(字符串空格问题,输入带双引号的字符串)

news2024/11/18 19:41:50

一、字符指针
字符指针(Character Pointers)是指向字符型数据的指针变量。
每个字符串在内存中都占用一段连续的存储空间,并有唯一确定的首地址。因此,只要将字符串的首地址赋值给字符指针,即可让字符指针指向一个字符串。对于字符串字面量而言,字符串字面量本身代表的就是存放它的常量存储区的首地址,是一个地址常量。例如:
char *ptr = “Hello”;
与 char *ptr;
ptr = “Hello”;//将保存在常量存储区中的“Hello”的首地址赋值给ptr//
这两种表达方式时等价的,都表示定义一个字符指针变量ptr,并用字符串字面量“Hello”在常量存储区中的首地址为其初始化,即让ptr指向字符串自字面量“Hello”。注意,这里不能理解为将字符串赋值给ptr。
因字符串“Hello”保存在只读的常量存储区中,所以此时可修改指针变量ptr的值(即ptr的指向),但不能对ptr所指向的存储单元进行写操作。
例如,此执行如下操作就是非法的:
*ptr = ‘w’;
//不能修改ptr指向的常量存储区中的字符,因为它是只读的
但如果字符串“Hello”保存在一个数组中,然后再用一个字符指针指向它,即
char str [10] = “Hello”;
char *ptr = str ;(第二句)
那么此时由于数组名代表数组的首地址,因此将str赋值给ptr,就是让ptr指向数组str中存储的字符串“Hello”。其中,上面第二条语句相当于
char *ptr;
ptr = str;
因为数组名是一个地址常量,所以str的值是不可修改的,但ptr的值(即ptr的指向)可以被修改,ptr所指向的字符串也可以被修改。
例如,若要将ptr所指向的字符串中的第一个字符修改为‘W’,则可使用下面的语句:
*ptr = ‘W’;//等价于ptr[0] = ‘W’ ; 相当于str[0]=‘W’
总之,正确使用字符指针,必须明确字符串被保存到了哪里以及字符指针指向了哪里。

在这里插入图片描述
在这里插入图片描述

#include <stdio.h>

char str[]="Hello!";
char *ptr;
char *sstr="Hello!";

int main(void)
{
	int i;
	int n=0;
	do{
		n++;
	}while(str[n]!=0);
	printf("%d\n",i);
	for(i=0;i<n;i++)
		printf("%c",str[i]);
	printf("\n");
	ptr=str;
	*ptr='W';
	for(i=0;i<n;i++)
		printf("%c",str[i]);
	printf("\n\n");
//	*sstr='w';
	for(i=0;i<6;i++)
	printf("%c",*sstr++);
	printf("\n");
 } 

此程序根据上述内容进行编写。

二、字符串的访问和输入/输出
1、如何访问字符串中的单个字符
和其他类型的数组一样,可以使用下标方式来访问存放于字符数组中的每个字节。
例如,在前面定义的字符数组str中,str[0]就表示第1个字符’H’,str[1]表示第2个字符’e’,依此类推,可以通过下标为i的元素str[i]来访问存放于数组中的第i+1个字符。
此外,还可通过字符指针间接访问存放于数组中的字符串,例如,若字符指针ptr指向了字符数组str的首地址,既可通过
(ptr+i)来引用字符串中的第i+1个字符,(ptr+i)相当于*(str+i),即str[i],也可通过ptr++操作,即移动指针ptr,使ptr指向字符串中的某个字符。

注意:对于数组名str,不能使用str++操作使其指向字符串中的某个字符,因为数组名是一个地址常量,其值是不能被改变的。

2、字符串的输入/输出
以下三种方法均可实现字符数组str的输入/输出。
(1)、按c格式符,一个字符一个字符地单独输入/输出。
例如:

#include <stdio.h>

int main()
{
	char str[10];
	for(int i=0;i<10;i++)
	{
		scanf("%c",&str[i]);
	}
	for(int i=0;i<10;i++)
	{
		printf("%c",str[i]);
	}
 } 

在这里插入图片描述
由于字符串地长度与字符数组地大小通常并不是完全一致的,因此很少使用上面这种方式输出字符数组中的字符串,更常用的方式是借助字符串结束标志’\0’,识别字符串的结束,进而结束字符串的输出操作,即:

 for(i=0;str[i]!='\0';i++)
 {
 	printf("%c",str[i]);//输出字符串
 }

该语句在输出时,依次检查数组中的每个元素str[i]受否为’\0’,若是,则停止输出,否则继续输出下一个字符。这种方法非常灵活,无论字符串中的字符数是已知还是未知,都可采用。
(2)、按s格式符,将字符串作为一个整体输入/输出。
例如:

scanf("%s",str);

表示读入一个字符串,直到遇空白字符(空格、回车符或制表符)为止。而

printf("%s",str);

表示输出一个字符串,直到遇到字符串结束标志为止。这里,由于字符数组名str本身代表该数组中存放的字符串的首地址,所以数组名str前面不能在加取地址符。

例题:从键盘输入一个人名,并把它显示再屏幕上。

#include <stdio.h>

int main()
{
	char str[]={};
	printf("Enter your name:");
	scanf("%s",str);
	printf("Hello %s !",str);
	printf("\n");
 } 

第一次调试:
在这里插入图片描述
第二次调试:
在这里插入图片描述
可以发现第二次调试,遇到空格之后,就结束了读入字符的操作。余下的字符被保留再缓冲区中,因此,我们可以对程序做如下修改:

#include <stdio.h>

int main()
{
	char str[12];
	printf("Enter your name:");
	scanf("%s",str);
	printf("Hello %s !\n",str);
	scanf("%s",str);//再次读入输入时空格后的字符
	printf("Hello %s !",str); 
	printf("\n");
 } 

修改后的调试结果:
在这里插入图片描述
第一个scanf语句将输入字符串中空格前面的字符串读到数组name中,然后由scanf后的第一个printf打印出第一个“Hello”信息。第9行将输入缓冲区中余下的上次未被读走的空格后面的字符串重新读到数组name中,然后由第10行语句打印出第二个“Hello”信息。
用%d输入数字或%s输入字符串时,忽略空格、回车或制表符等空白字符(被作为数据的分隔符),读到这些字符时,系统认为数据读入结束,因此用scanf()按s格式符不能输入带空格的字符串。

(3)使用字符串处理函数gets(),可以输入带空格地字符串,因为空格和制表符都是字符串地一部分。
此外,函数gets()与scanf()对回车符的处理也不同。gets()以回车符作为字符串的终止符,同时将回车符从的输入缓冲区读走,但不作为字符串的一部分。而scanf()不读走回车符,回车符仍留在输入缓冲区中。
例题:使用gets(),从键盘输入一个带有空格的人名,然后把它显示在屏幕上。

 #include <stdio.h>
 #define N 12
 int main(void)
 {
 	char name[N];
 	char nake[N];
 	printf("Enter your name: ");
 	gets(name);
 	printf("Hello %s !\n",name);
 	puts(name);
 }

在这里插入图片描述
函数puts()也可以输出字符串。
函数puts()用于从括号内的参数给出的地址开始,依次输出存储单元中的字符,当遇到第一个‘\0’时输出结束,并且自动输出一个换行符。函数puts()输出字符串简洁方便,唯一不足就是不能向函数printf()那样在输出行中增加其他字符信息。
由于gets()和puts()都是C语言的标准输入输出库函数,因此,在使用时只要在程序开始时将头文件<stdio.h>包含到源文件中即可。

例题2:程序还可以使用字符指针来编程实现。

#include <stdio.h>
#define N 12
int main(void)
{
	char name[N];
	char *ptrName = name;
	printf("Enter your name:");
	gets(ptrName);
	printf("Hello %s !\n",ptrName);
	return 0;
 } 

在这里插入图片描述
用字符指针输入字符串时,必须确保字符指针事先已经指向一个数组的首地址,如本例字符指针变量ptrName指向了数组name。但如果删掉第5行语句,并将第6行语句修改为:
char *ptrName;
那么由于指针变量ptrName尚未指向一个确定的存储单元,就把输入的字符串存入其中,会导致非法内存访问错误,因此程序在Visual C++ 6.0(DEv C++)下运行后会发生异常终止。
在这里插入图片描述
其实,在前面几个程序都存在一种容易被忽略的问题,即如果用户没有听从括号内的提示信息的指示,键入的字符数超过了数组name的大小12,那么多出来的那些字符就有可能重写内存的其他区域,导致程序出错。
其根本原因在于,gets函数不能限制输入字符的长度,很容易引起缓冲区溢出。同样scanf()函数也存在同样的问题。即使使用了带格式控制的形式,如scanf(“%12s”,name),也不可能真正解决这个问题。
所以建议使用能限制字符串长度的函数,即:
fgets(name, sizeof(name),stdin);
将更有利于设计安全可靠的程序。

例题修改:

 #include <stdio.h>
 #define N 12
 int main(void)
 {
 	char name[N];
 	printf("Enter your name:");
 	fgets(name , sizeof(name),stdin);
 	printf("Hello %s !\n",name);
 	return 0;
 }

在这里插入图片描述
输入字符产包含双引号:
例题3:从键盘输入一个带有空格的人名,然后在显示人名的前面显示“hello”,I said to。

 #include <stdio.h>
 #define N 12
 int main(void)
 {
 	char name[N];
 	char str[]="\"Hello\",I said to";
 	printf("Enter your name :");
 	fgets(name,sizeof(name),stdin);
 	printf("%s %s.",str,name);
 }

在这里插入图片描述

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

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

相关文章

安卓主板/开发板定制开发生产,MTK/高通/紫光展锐安卓开发板

智物通讯是一家致力于行业安卓主板定制开发的公司&#xff0c;提供包括MTK四核/八核方案、MTK、高通、紫光展锐系列行业主板方案定制等多样化的服务。 用户可以根据实际需求选择各种不同的模块类型&#xff0c;包括4G模块和5G模块。其中4G模块方案有MT6761、MT6762、MT6765、M…

爬虫 python 正则匹配 保存网页图片

目录 1. 简介1.1 爬虫1.2 爬虫语言1.3 python库1.4 我的步骤 2. 导入包2.1 代码2.2 requests库 3. 写入文件函数4. 获取图片5. 主函数5.1 代码5.2 说明一下webbrowser 6. 所有代码7. 其他&#xff08;可以忽略&#xff09;8. 总结 在这里我只提供的是一种方法&#xff0c;有很多…

webpack生产模式配置

一、生产模式和开发模式介绍 生成模式&#xff08;production mode&#xff09;是指在开发完成后将代码部署到生产环境中运行的模式&#xff0c;通常需要进行代码压缩、优化、合并&#xff0c;以减少文件大小和请求次数&#xff0c;提高页面加载速度和运行效率。 开发模式&am…

Android12 系统开发记录-迅为RK3588使用ADB工具

ADB 英文名叫 Android debug bridge &#xff0c;是 Android SDK 里面的一个工具&#xff0c;用这个工具可以 操作管理 Android 模拟器或者真实的 Android 设备&#xff0c;主要的功能如下所示&#xff1a;  在 Android 设备上运行 shell 终端&#xff0c;用命令行操作 …

How to fix the NHS 如何改革英国的国民医疗保险制度 | 经济学人20230527版社论双语精翻

他山之石&#xff1a;2023年5月27日《经济学人》社论&#xff08;Leaders&#xff09;精选&#xff1a;《如何改革英国的国民医疗保险制度》&#xff08;“How to fix the NHS”&#xff09; Leaders | The sick factor 社论 | 致病因素 How to fix the NHS 如何改革英国的国民…

软件安装mysql

1系统约定 安装文件下载目录&#xff1a;/data/softwareMysql目录安装位置&#xff1a;/usr/local/mysql数据库保存位置&#xff1a;/data/mysql日志保存位置&#xff1a;/data/log/mysql 2下载mysql 在官网&#xff1a;MySQL :: Download MySQL Community Server 中&#x…

Guitar Pro8.0.1最新中文版本吉他谱下载及使用教程

许多人都对吉他这个乐器很感兴趣&#xff0c;因为吉他的学习成本较低&#xff0c;学习难度较小&#xff0c;即便是零基础的小白通过短期的学习也能掌握基本的技巧。但实际上&#xff0c;学习吉他还需要认识吉他谱&#xff0c;识谱是每个吉他爱好者都必须掌握的技能&#xff0c;…

数字孪生世界建设核心能力:物理世界感知能力

中国信通院在《数字孪生城市白皮书&#xff08;2022年&#xff09;》中指出&#xff0c;数字孪生城市技术集成性高&#xff0c;核心板块日渐清晰&#xff0c;当前已逐步深入到城市全要素表达、业务预警预测、场景仿真推演、态势感知只能决策等多个环节。数字孪生技术的向前发展…

Yum update和upgrade的区别

Yum update和upgrade的区别 Linux yum中package升级命令有两个分别是 yum upgrade 和 yum update 1、区别 默认情况下&#xff0c;yum update和yum upgrade的功能是完全一样的&#xff0c;都是将需要更新的package(这里的包包括常规的包、软件、系统版本、系统内核)更新至软件…

如何使用ArcGIS加载历史影像

历史影像对研究地物的变化可以产生很直观的效果&#xff0c;Esri提供了在线浏览的历史影像&#xff0c;这里给大家介绍一下如何将这个历史影像加载到ArcGIS&#xff0c;希望能对你有所帮助。 获取地图链接 打开地图网站&#xff08;https://livingatlas.arcgis.com/wayback/&a…

【MySQL】复合查询(重点)

&#x1f3e0; 大家好&#xff0c;我是 兔7 &#xff0c;一位努力学习C的博主~&#x1f4ac; &#x1f351; 如果文章知识点有错误的地方&#xff0c;请指正&#xff01;和大家一起学习&#xff0c;一起进步&#x1f440; &#x1f680; 如有不懂&#xff0c;可以随时向我提问&…

实验篇(7.2) 13. 创建点对点安全隧道 (二)(FortiGate-IPsec) ❀ 远程访问

【简介】上一篇实验发现&#xff0c;两端都是可以远程的公网IP的话&#xff0c;两端防火墙都可以发出连接请求&#xff0c;并且都能够连通。这样的好处是安全隧道不用随时在线&#xff0c;只在有需求时才由发起方进行连接。但是现实中很多情况下只有一端公网IP可以远程&#xf…

番外篇 离线服务器环境配置与安装

&#xff08;离线远程服务器的Anaconda安装与卸载torch的安装与卸载&#xff09; 我参考或百度一些博主发的经验贴关于Anaconda的安装与卸载等教程&#xff0c;但实际情况是每一个服务器遇到的问题多多少少总有不一样的地方&#xff0c;虽然可以借鉴&#xff0c;但不能完全照搬…

常见Visual Studio Code 快捷键

一&#xff0c;文件与窗口快捷键&#xff1a; 1.打开一个新窗口&#xff1a; CtrlShiftN 2.关闭窗口&#xff1a; CtrlShiftW 3.文件切换&#xff1a;CtrlTab 4.快速打开文件&#xff1a;CtrlP 5.新建文件&#xff1a; CtrlN 6.切换侧边栏&#xff1a;CtrlB 7.选中单个文…

JWT代码实现

什么是 JWT&#xff1f; JSON Web Token&#xff0c;通过数字签名的方式&#xff0c;以 JSON 对象为载体&#xff0c;在不同的服务终端之间安全的传输信 息。(将信息进行封装&#xff0c;以 JSON 的形式传递) JWT 有什么用? JWT 最常见的场景就是授权认证&#xff0c;一旦用户…

web3.0 爆红是炒作还是真有赚头?

前言 最近两年虽然疫情肆虐全球&#xff0c;虽然困得住人们的脚步&#xff0c;但是困不住科技的发展趋势&#xff0c;前有元宇宙&#xff0c;后有 web3.0&#xff0c;新的热点一个接着一个的出现&#xff0c;技术革新也是越来越快&#xff0c;之前只能在科幻电影、科幻小说中出…

SIFT算法

文章目录 1. SIFT算法简介1.1 SIFT特征检测步骤1.2 SIFT算法的特点 2. SIFT算法原理2.1 尺度空间2.1.1 多分辨率金字塔2.1.2 高斯金字塔2.1.3 高斯尺度空间&#xff08;使用不同的参数&#xff09; 2.2 DoG空间极值检测&#xff08;查找关键点&#xff09;2.3 删除不好的极值点…

二、Kafka生产与消费全流程

Kafka生产与消费全流程 Kafka是一款消息中间件&#xff0c;消息中间件本质就是收消息与发消息&#xff0c;所以这节课我们会从一条消息开始生产出发&#xff0c;去了解生产端的运行流程&#xff0c;然后简单的了解一下broker的存储流程&#xff0c;最后这条消息是如何被消费者…

JVM笔记(一)

走进JVM JVM相对于Java应用层的学习难度更大&#xff0c;**开篇推荐掌握的预备知识&#xff1a;**C/C(关键)、微机原理与接口技术、计算机组成原理、操作系统、数据结构与算法、编译原理&#xff08;不推荐刚学完JavaSE的同学学习&#xff09;&#xff0c;如果没有掌握推荐的一…

javac 无效的目标发行版: xx

一、检查系统JDK版本 java --version 如果不符合&#xff0c;重新配置系统环境。 二、检查IDEA设置 1、项目结构->项目->SDK和语言级别 2、 项目结构->模块->设置每一个模块的语言级别。 3、java编译器&#xff0c;模块预言级别。 三、检查pom文件 <!--Licens…