【C语言常用字符串解析】

总结一下在 C 语言中用于字符串解析(特别是从文件中读取行并提取数据)的常用函数、

核心任务: 通常是从文件中读取一行文本(一个字符串),然后从这个字符串中提取出需要的数据(比如数字、单词等)。

常用函数总结:

  1. fgets() - 读取行

    • 头文件: <stdio.h>

    • 原型: char *fgets(char *str, int n, FILE *stream);

    • 作用: 从指定的文件流 stream 中读取一行,并将其存储到 str 指向的字符数组中。

    • 行为:

      • 最多读取 n-1 个字符(为末尾的空字符 \0 留出空间)。

      • 在读到换行符 \n、文件结束符 (EOF) 或达到 n-1 个字符时停止。

      • 如果读到了换行符 \n,它会被存储在字符串 str 中。

      • 总会在读取的字符后面添加一个空字符 \0。

      • 安全: 防止缓冲区溢出,因为读取的字符数有上限。

    • 返回值: 成功时返回 str 指针;如果遇到文件结尾且未读取任何字符,或者发生错误,则返回 NULL。——不需要额外接受值等于,会返回在str里面

    • 解析相关: 获取需要解析的原始字符串行的主要方式。 注意: 通常需要手动去除末尾可能存在的换行符 \n。

      char buffer[256];
      if (fgets(buffer, sizeof(buffer), fp) != NULL) {// 移除可能的换行符buffer[strcspn(buffer, "\n")] = '\0'; // 查找第一个换行符并替换为\0// 现在 buffer 包含了一行没有换行符的文本,可以进行解析
      }
    • strcspn() (来自 <string.h>) 在这里用来查找第一个换行符的位置。

  2. strlen() - 获取字符串长度

    • 头文件: <string.h>

    • 原型: size_t strlen(const char *str); (size_t 通常是 unsigned int 或 unsigned long)

    • 作用: 计算字符串 str 的长度,即第一个空字符 \0 之前的字符数。

    • 行为: 不包括结尾的 \0。

    • 返回值: 字符串的长度。

    • 解析相关: 虽然不直接解析内容,但在处理字符串(如检查是否为空、设置循环边界等)时非常有用。

  3. atoi() - 字符串转整数 (ASCII to Integer)

    • 头文件: <stdlib.h>

    • 原型: int atoi(const char *str);

    • 作用: 将表示整数的字符串 str 转换为 int 类型。

    • 行为:

      • 跳过开头的空白字符(如空格、制表符)。

      • 读取连续的数字字符,直到遇到非数字字符或字符串末尾 \0。

      • 不进行错误检查! 如果字符串不是有效的整数表示(例如是空的、"abc"、或者超出 int 范围),行为是:

        • 无法转换或为空:通常返回 0。你无法区分输入是 "0" 还是无效输入。

        • 超出范围:行为未定义(可能溢出并得到错误结果)。

    • 返回值: 转换后的 int 值,或者在无法转换时返回 0。

    • 解析相关: 用于从字符串片段中提取整数。仅适用于简单情况且不关心错误处理时。

  4. atof() - 字符串转双精度浮点数 (ASCII to Float)

    • 头文件: <stdlib.h>

    • 原型: double atof(const char *str);

    • 作用: 将表示浮点数的字符串 str 转换为 double 类型。

    • 行为:

      • 类似 atoi,跳过空白,读取数字、小数点、可选的 e 或 E 指数部分。

      • 同样不进行错误检查!

        • 无法转换或为空:通常返回 0.0。你无法区分输入是 "0.0" 还是无效输入。

        • 超出范围:行为未定义。

    • 返回值: 转换后的 double 值,或者在无法转换时返回 0.0。

    • 解析相关: 用于从字符串片段中提取浮点数。仅适用于简单情况且不关心错误处理时。

  5. strtod() - 字符串转双精度浮点数 (更健壮)

    • 头文件: <stdlib.h>

    • 原型: double strtod(const char *nptr, char **endptr);

    • 作用: 将字符串 nptr 的初始部分转换为 double 值。

    • 行为:

      • 比 atof 更强大、更安全。

      • endptr 是一个二级指针。如果它不是 NULL,strtod 会将指向转换结束后的第一个字符的指针存储在 *endptr 中。这允许你:

        • 检查是否发生了转换(如果 *endptr == nptr,则没有字符被转换)。

        • 继续从 *endptr 开始解析字符串的剩余部分。

      • 进行错误检查:

        • 如果发生上溢,返回 HUGE_VAL(或 -HUGE_VAL),并将全局变量 errno 设置为 ERANGE(需要 #include <errno.h> 和 #include <math.h>)。

        • 如果发生下溢,返回 0.0,并将 errno 设置为 ERANGE。

        • 如果无法转换,返回 0.0,并且 *endptr 会等于 nptr。

    • 返回值: 转换后的 double 值。

    • 解析相关: 强烈推荐使用此函数代替 atof 来进行字符串到 double 的转换,因为它提供了错误检测和更精细的控制。类似地,还有 strtof() (转 float) 和 strtold() (转 long double),以及 strtol() / strtoul() (转 long/unsigned long,代替 atoi)。

      char *line = "3.14 1.59 rest";
      char *end;
      double val1, val2;
      errno = 0; // 清除 errnoval1 = strtod(line, &end);
      if (errno == ERANGE || line == end) { /* 处理错误 */ }
      printf("First value: %f, Remaining string: '%s'\n", val1, end);// 继续解析 end 指向的剩余部分
      line = end; // 更新 line 指针
      errno = 0;
      val2 = strtod(line, &end);if (errno == ERANGE || line == end) { /* 处理错误 */ }
      printf("Second value: %f, Remaining string: '%s'\n", val2, end);
  6. strtok() - 分割字符串 (Tokenize)

    • 头文件: <string.h>

    • 原型: char *strtok(char *str, const char *delim);

    • 作用: 将字符串 str 分割成一系列的“令牌”(tokens),这些令牌由 delim 字符串中包含的任何一个字符分隔开。

    • 行为:

      • 会修改原始字符串 str! 它会在找到的分隔符位置写入 \0。因此,你通常需要一个可写的字符串副本。

      • 非可重入,非线程安全: 它使用一个内部静态指针来记住下次调用的位置。

      • 第一次调用: str 参数是要分割的字符串,函数返回第一个令牌的指针,如果没有令牌则返回 NULL。

      • 后续调用: str 参数必须是 NULL,函数会从上次停止的位置继续查找下一个令牌,返回令牌指针或 NULL。

    • 返回值: 指向下一个令牌的指针,或者在没有更多令牌时返回 NULL。

    • 解析相关: 用于按分隔符(如空格、逗号)拆分字符串。例如,拆分一行坐标 "x1 y1 x2 y2 ..."。

      char line[] = "10.0 20.5 30.0 15.0"; // 可写副本
      const char *delimiters = " "; // 按空格分割
      char *token;token = strtok(line, delimiters);
      while (token != NULL) {printf("Token: %s\n", token);// 在这里可以用 strtod() 将 token 转换为 doubledouble coord = strtod(token, NULL); // 简单用法,忽略错误检查printf("Coordinate: %f\n", coord);token = strtok(NULL, delimiters); // 获取下一个 token
      }
    • 注意: 因为它修改原字符串且非线程安全,有时会避免使用它,尤其是在复杂或多线程程序中。可以考虑使用 sscanf 或手动循环配合 strtod。

  7. sscanf() - 从字符串读取格式化输入

    • 头文件: <stdio.h>

    • 原型: int sscanf(const char *str, const char *format, ...);

    • 作用: 类似于 scanf,但是从字符串 str 而不是标准输入 stdin 读取数据。

    • 行为: 根据 format 字符串中的格式说明符,尝试从 str 中解析数据并存储到后续的参数(必须是指针)中。

    • 返回值: 成功赋值的参数个数。如果输入在第一次赋值前就结束或失败,返回 EOF。

    • 解析相关: 非常强大,可以一次性解析多个不同类型的值,只要它们的格式是预期的。

      char data[] = "Point 1 10.5 25.3";
      char label[10];
      int id;
      double x, y;int count = sscanf(data, "%s %d %lf %lf", label, &id, &x, &y);if (count == 4) {printf("Parsed: Label=%s, ID=%d, X=%.2f, Y=%.2f\n", label, id, x, y);
      } else {printf("Parsing failed or incomplete. Items matched: %d\n", count);
      }

    • 在循环中解析坐标序列: 可以结合 %n 实现。%n 不消耗输入,而是将在该点消耗的字符数写入其对应的 int* 参数。这可以帮助你移动解析的“光标”。

      char coords[] = "1.1 2.2 3.3 4.4 5.5 6.6";
      char *ptr = coords;
      int offset;
      double val;
      int items_read;while (sscanf(ptr, "%lf%n", &val, &offset) == 1) {printf("Read coordinate: %f\n", val);ptr += offset; // 移动指针到已解析部分的后面// 跳过可能的空格while (*ptr == ' ') {ptr++;}if (*ptr == '\0') break; // 到达字符串末尾
      }

如何选择?

  • 读取文件行: 始终使用 fgets。

  • 获取字符串长度: strlen。

  • 字符串转数字:

    • 优先使用 strtod, strtol, strtoul 因为它们提供错误检查和更好的控制。

    • atoi, atof 仅用于非常简单、不需错误处理的场景(或快速原型开发),生产代码中应避免。

  • 分割字符串:

    • strtok: 简单,但修改原串且非线程安全。适用于简单场景且拥有可写副本时。

    • sscanf: 适合格式相对固定的输入,可以一次性读取多个值。不修改原串。

    • 循环 + strtod: 最灵活、最健壮的方法,尤其当分隔符复杂或需要精细错误处理时。通过 strtod 的 endptr 可以精确控制解析位置。

例子:

多边形坐标解析任务(一行包含多个空格分隔的浮点数),以下两种方法比较常用:

  1. fgets + strtok + strtod:

    • fgets 读取行。

    • 创建行的可写副本。

    • 用 strtok 以空格为分隔符循环获取每个坐标字符串 (token)。

    • 在循环内用 strtod 将每个 token 转换为 double 并进行错误检查。

  2. fgets + 循环 + strtod:

    • fgets 读取行。

    • 使用一个指针 char *current_pos 指向当前解析位置(初始指向行首)。

    • 在循环中:

      • 调用 val = strtod(current_pos, &end_pos)。

      • 检查错误 (errno, current_pos == end_pos)。

      • 如果成功,存储 val。

      • 更新 current_pos = end_pos,让下一次循环从这里开始。

      • 如果 current_pos 指向 \0,结束循环。

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

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

相关文章

SpringTas定时任务使用详解

文章目录 Spring Task概述1、环境配置2.注解实现定时任务2.注解实现定时任务4. cron表达式详解&#xff1a; Spring Task概述 在开发中&#xff0c;我们经常会用到定时任务&#xff0c;而Spring Task 则是Spring提供的定时任务框架。 其它定时任务实现框架又jdk自带Timer和Qua…

数字智慧方案6172丨智慧医院扩建信息化整体规划方案(60页PPT)(文末有下载方式)

资料解读&#xff1a;智慧医院扩建信息化整体规划方案 详细资料请看本解读文章的最后内容。 在信息技术飞速发展的当下&#xff0c;医疗行业的信息化建设成为提升医疗服务水平、优化医院管理的关键路径。这份智慧医院扩建信息化整体规划方案&#xff0c;针对医院扩建过程中的信…

ts全局导入接口

为了在项目中全局导入 ITableColumn 接口&#xff0c;避免每次使用时手动导入&#xff0c;可以通过以下步骤实现&#xff1a; 1. 全局导入的实现方式 在 Vue 项目中&#xff0c;可以通过在 src 目录下创建一个 global.d.ts 文件&#xff0c;将 ITableColumn 接口声明为全局类型…

汽车启动原理是什么?

好的&#xff01;同学们&#xff0c;今天我们来讨论汽车的启动原理&#xff0c;重点分析其中的动力来源和摩擦力作用。我会结合物理概念&#xff0c;用尽量直观的方式讲解。 1. 汽车为什么会动&#xff1f;——动力的来源 汽车发动机&#xff08;内燃机或电动机&#xff09;工…

【音频】Qt6实现MP3播放器

1、简介 解码MP3有很多种方法,比如:FFmpeg、GStreamer、Qt、libmpg123 库等,下面介绍使用,只使用Qt的接口方法解码、播放MP3。 开发配置: 1)操作系统:Windows11 2)Qt版本:Qt6.5.1 3)编译器:MinGW_64 2、获取音频输出设备 QMediaDevices 用于获取媒体设备,包括音…

【Linux】VSCode用法

描述 部分图片和经验来源于网络&#xff0c;若有侵权麻烦联系我删除&#xff0c;主要是做笔记的时候忘记写来源了&#xff0c;做完笔记很久才写博客。 专栏目录&#xff1a;记录自己的嵌入式学习之路-CSDN博客 目录 1 安装环境及运行C/C 1.1 安装及配置步骤 1.2 运…

WPF之RadioButton控件详解

文章目录 一、RadioButton简介二、RadioButton的基本用法1. 创建基本的RadioButton2. 分组管理3. 设置默认选中 三、RadioButton的重要属性和事件1. 关键属性2. 主要事件3. 事件处理流程4. 监听选中状态变化 四、数据绑定与RadioButton1. 基本数据绑定2. 数据绑定流程3. 使用枚…

笔试专题(十三)

文章目录 kotori和气球题解代码 走迷宫题解代码 主持人调度&#xff08;二&#xff09;&#xff08;难题&#xff09;题解代码 kotori和气球 题目链接 题解 1. 数学-排列组合 2. 每次乘完之后对109取模 代码 #include<iostream>using namespace std;int main() {int…

图形图像基础知识(1)---- RGB/YUV 颜色格式

目录 常见RAW颜色格式RGB类型YUV类型YUV类型汇总YUV444类型YUV422类型YUV420类型 参考实例 常见RAW颜色格式 RGB 类型&#xff1a; ARGB1010102&#xff0c;ABGR1010102&#xff0c;BGRA1010102&#xff0c;RGBA1010102 ARGB8888&#xff0c;ABGR8888&#xff0c;BGRA8888&…

CentOS7.9安装OpenSSL 1.1.1t和OpenSSH9.9p1

一、临时开启telnet登录方式&#xff0c;避免升级失败无法登录系统 &#xff08;注意telnet登录方式存在安全隐患&#xff0c;升级openssh相关服务后要记得关闭&#xff09; 1.安装telnet服务 yum -y install xinetd telnet* 2.允许root用户通过telnet登陆&#xff0c;编辑…

使用DCI和RTIT技术进行精准调优--看录像

使用DCI和RTIT技术进行精准调优_哔哩哔哩_bilibili 每次看录像都记录一下。 PT/RTIT简介 DCI技术即通过USB3.0接口去访问调试目标机的JTAG组件&#xff0c;凡是运行在CPU上的代码均可以进行调试&#xff0c;这就没有了使用WinDBG调试时&#xff0c;会出现的不能调试敏感代码…

从MCP基础到FastMCP实战应用

MCP(https://github.com/modelcontextprotocol) MCP&#xff08;模型上下文协议&#xff09; 是一种专为 基于LLM的工具调用外部工具而设计的协议 &#xff0c; 本质上是 LLM ↔ 工具之间的RPC&#xff08;远程过程调用&#xff09; 的一种安全且一致的处理方式&#xff0c; 是…

深入理解C语言中的整形提升与算术转换

深入理解C语言中的整形提升与算术转换 一.整形提升&#xff1a;概念与原理 在C语言中&#xff0c;整形提升&#xff08;Integer Promotion&#xff09;是一个重要但容易被忽视的概念。它指的是在表达式中&#xff0c;任何小于int类型的整型&#xff08;如char、short&#xf…

编程题python常用技巧-持续

1.字典 1.1排序 在Python中&#xff0c;要按照字典的值进行排序&#xff0c;可以按照以下步骤操作&#xff1a; 方法说明 ‌获取键值对列表‌&#xff1a;使用 dict.items() 获取字典的键值对视图。‌排序键值对‌&#xff1a;使用 sorted() 函数&#xff0c;并通过 key 参…

硬件工程师面试常见问题(11)

第五十一问&#xff1a;器件手册的翻译题目 要学英语啊&#xff0c;孩子。 第五十二问&#xff1a;二极管三极管常识题 1.二极管的导通电压一般是 0.7V 2.MOS管根据掺杂类型可以分为 NMOS和PMOS 3.晶体三极管在工作时,发射结和集电结均处于正向偏置,该晶体管工作在一饱和态。…

mysql 配置文件中的[client]、[mysqld]、[mysqldump]和[mysql]区块的作用区别

1. [client] 区块 作用&#xff1a; 适用于 所有 MySQL 客户端工具&#xff08;如 mysql 命令行客户端、mysqldump、mysqladmin 等&#xff09;。 常见配置项&#xff1a; [client] host 127.0.0.1 # 默认连接的服务器地址 port 3306 # 默认端口 user root …

SARSA 算法详解:python从零实现

喜欢可以订阅专栏哟 第一章 强化学习基础与核心概念 1.1 强化学习的定义与特点 强化学习(Reinforcement Learning, RL)是机器学习三大范式之一(监督学习、无监督学习、强化学习),其核心思想是通过智能体(Agent)与环境(Environment)的持续交互来学习最优策略。与监督…

(C题|社交媒体平台用户分析问题)2025年第二十二届五一数学建模竞赛(五一杯/五一赛)解题思路|完整代码论文集合

我是Tina表姐&#xff0c;毕业于中国人民大学&#xff0c;对数学建模的热爱让我在这一领域深耕多年。我的建模思路已经帮助了百余位学习者和参赛者在数学建模的道路上取得了显著的进步和成就。现在&#xff0c;我将这份宝贵的经验和知识凝练成一份全面的解题思路与代码论文集合…

AI重塑SEO关键词策略

内容概要 传统SEO策略主要依赖人工经验与基础工具进行关键词布局&#xff0c;存在效率低、覆盖维度单一等痛点。而AI技术的介入&#xff0c;使关键词优化从静态词库匹配转向动态语义网络构建。通过自然语言处理&#xff08;NLP&#xff09;与深度学习模型&#xff0c;AI不仅能…

【Unity】 组件库分类详解

1️⃣ Audio&#xff08;音频组件&#xff09; 用于处理游戏中的声音。 Audio Source 读音[ˈɔːdiəʊ ˈsɔːs]&#xff0c;音频源组件&#xff0c;用于播放音频文件&#xff0c;可设置音量、Pitch、循环播放等属性&#xff0c;是音频播放的核心组件。 Audio Listener 读音…