【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.pswp.cn/web/78071.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/78071.shtml
英文地址,請注明出處:http://en.pswp.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 讀音…