【C语言】第七期——字符数组、字符串、类型转换

目录

1 定义初始化字符数组

2 用字符数组来存储字符串

3 strlen 计算字符串有效长度

4 sprintf 字符串格式化函数

函数原型

参数说明

返回值

功能描述

示例代码 

5 snprintf 防溢出格式化函数

函数原型

参数说明

返回值

示例代码

内存分配

6 类型转换

6.1 整数类型转换成字符串

6.2 字符串转换成整数类型(atoi函数)

6.3 整数类型之间的相互转换


在软件开发中字符串的应用非常广泛,但是C语言却没有字符串类型,为了解决这个问题,我们可以使用字符数组来存储字符串

1 定义初始化字符数组

字符数组的定义和普通数组一样,通过char关键字可以定义字符数组

方法1:

 char chs1[6] = {'i', 't', 'y', 'i', 'n', 'g'};    

方法2:

char chs2[] = {'l', 'i', 's', 'i'};

2 用字符数组来存储字符串

C语言中没有专门的字符串类型,通常使用字符数组来存储字符串。为了区分普通字符数组和字符串,C 语言规定以字符“\0“作为字符串的结束标志,例如:

//字符串
char chs1[] = {'i', 't', 'y', 'i', 'n', 'g','\0'};//普通字符数组
char chs1[] = {'i', 't', 'y', 'i', 'n', 'g'};

除了以上初始化方式,也可以采用字符串对字符数组进行初始化,例如:

char c[]="user_a001"

使用字符串方式进行赋值时,系统会自动在字符串末尾添加“\0"

实例:

定义一个字符串并输出 

#include <stdio.h>
int main()
{char chs1[] = { 'i', 't', 'y', 'i', 'n', 'g', '\0' };char chs2[] = "itying";printf("字符\" % s \"的长度:%d\n", chs1, sizeof(chs1));printf("字符\" % s \"的长度:%d", chs2, sizeof(chs2));return 0;
}

 输出结果:

字符" itying "的长度:7
字符" itying "的长度:7

由于一个字符占用1个字节,所以可以通过字符串总长度/单个字符的长度求出总字符数

如下:

#include <stdio.h>
int main()
{char chs1[] = { 'i', 't', 'y', 'i', 'n', 'g', '\0' };char chs2[] = "itying";printf("字符\" % s \"的长度:%d\n", chs1, sizeof(chs1) / sizeof(chs1[0]));printf("字符\" % s \"的长度:%d\n", chs2, sizeof(chs2) / sizeof(chs2[0]));return 0;
}

注意:通过此方法得到的长度为实际字符串长度+1,因为末尾的"/0"也算,而下文的strlen函数计算的长度为字符串真实长度 


3 strlen 计算字符串有效长度

C语言中通过strlen 可以计算字符串的有效长度

strlen 函数在 "<string.h>"标准库里面,使用前需要先引入库文件

#include <stdio.h>
#include <string.h>
int main()
{char chs1[] = { 'i', 't', 'y', 'i', 'n', 'g', '\0' };char chs2[] = "itying.com";int length1 = strlen(chs1);int length2 = strlen(chs2);printf("%d\n", length1);printf("%d\n", length2);return 0;
}

输出结果:

6

10


4 sprintf 字符串格式化函数

sprintf 是 C 语言中的一个函数,用于将格式化的文本写入到指定的缓冲区中,该函数使用格式化字符串作为输入参数,并在输出时自动添加所需的分隔符和换行符等

函数原型

int sprintf(char *str, const char *format, ...);

参数说明

  • str:指向用于存储格式化后字符串的字符数组的指针。这个数组必须足够大,以容纳格式化后的字符串,包括字符串结束符 '\0'
  • format:这是一个格式化字符串,它指定了输出的格式。格式化字符串可以包含普通字符和格式说明符,格式说明符以 % 开头,用于指定后续参数的输出格式
  • ...:可变参数列表,这些参数将按照 format 字符串中的格式说明符进行格式化

返回值

在未发生重大错误(如传入 NULL 指针作为目标缓冲区)的前提下,无论写入内容是否超出目标字符数组的大小,sprintf 函数都会返回按照格式化规则将所有参数转换为字符串后拼接起来的总字符数量(不包括字符串结束符 '\0')

功能描述

sprintf 函数的主要功能是将格式化的数据写入到指定的字符数组中,而不是像 printf 函数那样直接输出到标准输出设备(如屏幕)

这使得它在需要将格式化数据存储到字符串中时非常有用,例如在构建动态字符串、生成日志信息等场景中经常会用到 

示例代码 

#include <stdio.h>int main() {char str[100];int num = 123;float f = 3.14;char ch = 'A';// 使用sprintf将不同类型的数据格式化为字符串sprintf(str, "整数: %d, 浮点数: %.2f, 字符: %c", num, f, ch);// 输出格式化后的字符串printf("格式化后的字符串: %s\n", str);return 0;
}

运行结果:

格式化后的字符串: 整数: 123, 浮点数: 3.14, 字符: A

❗注意:

缓冲区溢出风险:由于 sprintf 函数不会检查目标字符数组的大小,因此如果格式化后的字符串长度超过了数组的大小,就会发生缓冲区溢出,可能导致程序崩溃或产生安全漏洞

为了避免这种情况,可以使用 snprintf 函数,它可以指定最大写入的字符数


5 snprintf 防溢出格式化函数

snprintf 是 C 语言标准库中的一个函数,同样声明在 <stdio.h> 头文件中。它是 sprintf 的安全版本,主要用于解决 sprintf 可能存在的缓冲区溢出问题

函数原型

int snprintf(char *str, size_t size, const char *format, ...);

参数说明

  • str:指向用于存储格式化后字符串的字符数组的指针。格式化后的字符串将被写入该数组
  • size:指定了 str 数组的最大可写入字节数,包含字符串结束符 '\0',这是 snprintf 与 sprintf 的关键区别,snprintf 会根据这个参数来防止缓冲区溢出
  • format:格式化字符串,用于指定输出的格式。它可以包含普通字符和格式说明符,格式说明符以  % 开头,用于指定后续可变参数的输出格式
  • ...:可变参数列表,这些参数会按照 format 字符串中的格式说明符进行格式化

返回值

  • 如果格式化后的字符串长度小于 size,snprintf 会将整个格式化字符串(包括字符串结束符 '\0')写入 str 数组,并返回实际写入的字符数(不包括字符串结束符)
  • 如果格式化后的字符串长度大于或等于 size,snprintf 会将 size - 1 个字符写入 str 数组,并在末尾添加字符串结束符 '\0',此时返回值为格式化字符串原本应有的长度(不包括字符串结束符)。这个返回值可以用于判断是否发生了截断

示例代码

#include <stdio.h>int main() {char str[20];int num = 123456;int result;// 使用 snprintf 进行格式化result = snprintf(str, sizeof(str), "数字是: %d", num);if (result >= sizeof(str)) {printf("发生截断,格式化字符串原本长度为 %d 字节。\n", result);} else {printf("格式化后的字符串为: %s\n", str);}return 0;
}

代码解释

  • 定义字符数组和变量:定义了一个长度为 20 的字符数组 str,用于存储格式化后的字符串,同时定义了一个整数 num 和一个用于存储 snprintf 返回值的变量 result
  • 调用 snprintf 函数:将整数 num 按照指定格式组合成字符串,并尝试写入 str 数组。sizeof(str) 用于指定 str 数组的最大可写入字节数
  • 根据返回值判断是否发生截断:如果 result 大于或等于 sizeof(str),说明发生了截断;否则,正常输出格式化后的字符串

内存分配

如果需要存储完整的格式化字符串,可以根据 snprintf 的返回值动态分配足够的内存。例如:

注意:malloc、free函数在第十三期讲解,此处可先跳过

#include <stdio.h>
#include <stdlib.h>int main() {int num = 123456;int len;char *str;// 先计算格式化字符串的长度len = snprintf(NULL, 0, "数字是: %d", num);// 动态分配足够的内存str = (char *)malloc((len + 1) * sizeof(char));if (str != NULL) {// 将格式化后的字符串写入分配的内存snprintf(str, len + 1, "数字是: %d", num);printf("格式化后的字符串为: %s\n", str);// 释放分配的内存free(str);}return 0;
}

在这个示例中,首先使用 snprintf(NULL, 0, ...) 计算格式化字符串的长度,然后根据这个长度动态分配足够的内存,最后再次调用 snprintf 将格式化后的字符串写入分配的内存中,使用完内存后,记得使用 free 函数释放内存,避免内存泄漏


6 类型转换

6.1 整数类型转换成字符串

使用sprintf

#include <stdio.h>
int main(void)
{char buffer_int[10] = { 0 };char buffer_float[10] = { 0 };sprintf(buffer_int, "%d", 100);sprintf(buffer_float, "%f", 3.14);printf("%s\n", buffer_int);printf("%s\n", buffer_float);return 0;
}

6.2 字符串转换成整数类型(atoi函数)

函数原型:

int atoi (const char * str);

头文件:

 #include<stdlib.h>
#include <stdio.h>
#include <stdlib.h>
int main(void)
{char s1[] = "123";int num1 = atoi(s1); // 将字符串 "123" 转化为整数 123printf("%d\n", num1);char s2[] = "2.123";double num2 = atof(s2); // 将字符串 "2.123" 转化为doblue 2.123printf("%lf\n", num2);return 0;
}

其他:字符串转成双精度浮点型用atof函数

#include <stdio.h>
#include <stdlib.h>int main() {char str[] = "3.14";double num = atof(str);  // 将字符串 "3.14" 转换为双精度浮点数 3.14printf("Converted number: %lf\n", num);return 0;
}

6.3 整数类型之间的相互转换

显示转换(强制转化): 

#include <stdio.h>
#include <stdlib.h>
int main(void)
{int a = 123;double b = (double)a;printf("b=%lf\n", b);float c = 123.4f;int d = (int)c;printf("d=%d\n", d);return 0;
}

隐式转换:

#include <stdio.h>int main() {int a;float b = 3.14;a = b;  // 浮点数b隐式转换为整数类型赋给aprintf("a = %d\n", a);return 0;
}

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

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

相关文章

项目实战--网页五子棋(匹配模块)(4)

上期我们完成了游戏大厅的前端部分内容&#xff0c;今天我们实现后端部分内容 1. 维护在线用户 在用户登录成功后&#xff0c;我们可以维护好用户的websocket会话&#xff0c;把用户表示为在线状态&#xff0c;方便获取到用户的websocket会话 package org.ting.j20250110_g…

hot100_108. 将有序数组转换为二叉搜索树

hot100_108. 将有序数组转换为二叉搜索树 思路 给你一个整数数组 nums &#xff0c;其中元素已经按 升序 排列&#xff0c;请你将其转换为一棵 平衡 二叉搜索树。 示例 1&#xff1a; 输入&#xff1a;nums [-10,-3,0,5,9] 输出&#xff1a;[0,-3,9,-10,null,5] 解释&#…

Win11更新系统c盘爆满处理

1.打开磁盘管理 2.右击c盘选择属性&#xff0c;进行磁盘管理&#xff0c;选择详细信息。 3.选择以前安装的文件删除即可释放c盘空间。

深入理解 JSP 与 Servlet:原理、交互及实战应用

一、引言 在 Java Web 开发领域,JSP(JavaServer Pages)和 Servlet 是两个至关重要的技术,它们共同构成了动态网页开发的基础。Servlet 作为服务器端的 Java 程序,负责处理客户端请求并生成响应;而 JSP 则是一种简化的 Servlet 开发方式,允许开发者在 HTML 页面中嵌入 J…

[通俗易懂C++]:指针和const

之前的文章有说过,使用指针我们可以改变指针指向的内容(通过给指针赋一个新的地址)或者改变被保存地址的值(通过给解引用指针赋一个新值): int main() {int x { 5 }; // 创建一个整数变量 x&#xff0c;初始值为 5int* ptr { &x }; // 创建一个指针 ptr&#xff0c;指向 …

DL/CV领域常见指标术语(FLOPS/mIoU/混淆矩阵/F1-measure)------一篇入门

1. FLOPS、FLOPs和GFLOPs FLOPS: floating-point operations per second&#xff0c;每秒浮点运算次数&#xff0c;用来衡量硬件性能。 FLOPs&#xff1a;floating point of operations&#xff0c;是浮点运算次数&#xff0c;用来衡量算法、模型的复杂度。 GFLOPS&#xff…

被裁20240927 --- WSL-Ubuntu20.04安装cuda、cuDNN、tensorRT

cuda、cuDNN、tensorRT的使用场景 1. CUDA&#xff08;Compute Unified Device Architecture&#xff09; 作用&#xff1a; GPU 通用计算&#xff1a;CUDA 是 NVIDIA 的并行计算平台和编程模型&#xff0c;允许开发者直接利用 GPU 的并行计算能力&#xff0c;加速通用计算任…

DeepSeek vs ChatGPT:AI对决中的赢家是……人类吗?

DeepSeek vs ChatGPT&#xff1a;AI对决中的赢家是……人类吗&#xff1f; 文章目录 DeepSeek vs ChatGPT&#xff1a;AI对决中的赢家是……人类吗&#xff1f;一、引言1. 背景2. 问题 二、DeepSeek vs ChatGPT&#xff1a;谁更胜一筹&#xff1f;2.1 语言生成能力评测对比场景…

旧手机热点无法提供ipv6解决方法(emui 8 热点提供ipv6)

旧手机热点无法提供ipv6解决方法 手机&#xff1a;荣耀8x 系统版本: EMUI 8 网络&#xff1a;移动流量卡 解决方案 设置-》无线和网络-》移动网络-》接入点名称(APN)-》cmiot 修改 APN协议: IPv4/IPv6 修改 APN漫游协议: IPv4/IPv6

I2C学习笔记-软件模拟I2C

I2C学习笔记&#xff08;软件模拟&#xff09; 介绍GPIO的配置信号的展示起始信号 与 停止信号应答信号&#xff08;非应答信号&#xff09;检测应答信号发送一个字节数据接收一个字节数据 硬件配置实物测试 介绍 I2C的信号大概有 起始信号、应答信号、停止信号、写数据、读数…

VUE四:Vue-cli

什么是Vue-cli vue-cli是官方提供的一个脚手架,用于快速生成一个vue的项目模板; 预先定义好的目录结构及基础代码&#xff0c;就好比咱们在创建 Maven项目时可以选择创建一个骨架项目&#xff0c;这个骨架项目就是脚手架,我们的开发更加的快速; 什么是web pack 本质上&#…

基于 openEuler 构建 LVS-DR 群集

目录 对比 LVS 负载均衡群集的 NAT 模式和 DR 模式&#xff0c;比较其各自的优势 NAT 模式&#xff08;网络地址转换模式&#xff09; DR 模式&#xff08;直接路由模式&#xff09; 基于 openEuler 构建 LVS-DR 群集 实验准备环境 配置web服务器 web1 web2 首先下载ngi…

传统的自动化行业的触摸屏和上位机,PLC是否会被取代?

传统的自动化行业的触摸屏和上位机是否会被取代&#xff1f; 在工业自动化领域&#xff0c;触摸屏和上位机长期扮演着核心角色&#xff0c;尤其在污水处理、化工生产等场景中&#xff0c;它们通过实时数据采集、逻辑控制、报警联动等功能&#xff0c;保障了生产设备的稳定运行…

Spring Boot 集成MyBatis-Plus

文章目录 一、背景说明二、集成过程 2.1 引入 maven 依赖2.2 增加属性配置2.3 自动配置类 三、验证集成 3.1 控制器3.2 服务类3.3 Mapper接口类3.4 实体类3.4 不要忘记XML文件3.5 发起请求 四、技巧拓展 4.1 如何打印sql语句&#xff1f;4.2 如何对参数增加非空验证&#xff1f…

力扣hot100——排序链表(常见方法,归并排序)

解题思路&#xff1a; 分解&#xff08;Divide&#xff09;&#xff1a;将待排序的列表递归地分成两半&#xff0c;直到每个子列表只包含一个元素&#xff08;此时每个子列表都是有序的&#xff09;。解决&#xff08;Conquer&#xff09;&#xff1a;递归地对每个子列表进行排…

技术解析 | 适用于TeamCity的Unreal Engine支持插件,提升游戏构建效率

龙智是JetBrains授权合作伙伴、Perforce授权合作伙伴&#xff0c;为您提供TeamCity、Perforce Helix Core等热门的游戏开发工具及一站式服务 TeamCity 是游戏开发的热门选择&#xff0c;大家选择它的原因包括支持 Perforce、可以进行本地安装&#xff0c;并提供了多种配置选项。…

Three.js 快速入门教程【二】透视投影相机

系列文章目录 系列文章目录 Three.js 快速入门教程【一】开启你的 3D Web 开发之旅 Three.js 快速入门教程【二】透视投影相机 Three.js 快速入门教程【三】渲染器 Three.js 快速入门教程【四】三维坐标系 Three.js 快速入门教程【五】动画渲染循环 Three.js 快速入门教程【六…

无人机仿真、感知、规划

文章目录 1.仿真环境1.1 博客教学1.2 教学视频1基础无人机仿真教学视频介绍2 XTDrone无人机仿真与控制技术全面教程3 ROS机器人集群仿真与实践教程 1.3 开源项目及插件1 ROS2-Gazebo Drone Simulation Plugin2 RotorS_UAV_Gazebo_Simulator3 自主无人机与Aruco导航教程4 基于 A…

php文件包含

文章目录 基础概念php伪协议什么是协议协议的格式php中的协议file协议http协议ftp协议php://input协议php://filter协议php://data协议 php文件上传机制高级文件包含nginx文件日志包含临时文件包含session文件包含pear文件包含远程文件包含 基础概念 文件包含&#xff0c;相当…

【超详细】神经网络的可视化解释

《------往期经典推荐------》 一、AI应用软件开发实战专栏【链接】 项目名称项目名称1.【人脸识别与管理系统开发】2.【车牌识别与自动收费管理系统开发】3.【手势识别系统开发】4.【人脸面部活体检测系统开发】5.【图片风格快速迁移软件开发】6.【人脸表表情识别系统】7.【…