首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C 語言字符串處理利器:sscanf、sprintf、snprintf、strlen、memset 深度解析

     編輯:關於C語言

C 語言字符串處理利器:sscanf、sprintf、snprintf、strlen、memset 深度解析

字符串解析與格式化是 C 開發高頻任務。本文系統整理 sscanf 掃描匹配技巧、sprintf/snprintf 安全格式化、以及 strlen/memset 基礎操作,附豐富實戰模式與避坑指南。

一、sscanf:從字符串中按模式提取數據

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

核心優勢:格式字符串支持集合操作(%[...]),可替代簡單正則,效率極高。

常用模式速查表

模式含義示例輸入 → 結果
%s跳過空白,讀單詞"123456 " → "123456"
%4s最大讀 4 字符"123456" → "1234"
%[^ ]讀到空格為止"123456 abcd" → "123456"
%[1-9a-z]僅匹配集合內字符(貪婪)"123abcDEF" → "123abc"
%[^A-Z]遇大寫字母停止"123abcDEF" → "123abc"
%*[^/]/%[^@]跳過 / 前內容,取 / 到 @ 間"iios/12DDWDFF@122" → "12DDWDFF"
%*s%s跳過第一個詞,取第二個"hello, world" → "world"

進階技巧:%[] 與 %* 抑制賦值

  • %[^=]=%s:提取 key=value 中的 value(如 notepad=1.0.0 → 1.0.0)
  • %*[^:]:跳過冒號前所有字符,不保存
  • %[^;]:讀到分號為止(適合解析 email:xxx@yy.com;)

⚠️ 避坑指南

  1. 緩衝區溢出:目標數組必須足夠大,或用 %Ns 限寬。
  2. 格式字符串漏洞:不要直接用用戶輸入作為 format。
  3. 跨平台差異:部分舊庫 scanf 族函數存在浮點解析 bug,關鍵路徑建議手寫解析器。

二、sprintf / snprintf:格式化輸出到字符串

函數原型關鍵差異返回值
sprintfint sprintf(char *buf, const char *fmt, ...)無長度檢查,極易溢出寫入字符數(不含 \0)
snprintfint snprintf(char *buf, size_t size, const char *fmt, ...)最多寫 size-1 字符,末尾補 \0格式化後完整長度(可能 ≥ size)

實戰示例

char buf[32];
int len = snprintf(buf, sizeof(buf), "Hello %s %d", "World", 2024);
// len = 14, buf = "Hello World 2024" (安全截斷如果超長)

// 替代 itoa:整數轉字符串
snprintf(buf, sizeof(buf), "%d", 12345);  // "12345"

關鍵點:snprintf 返回「完整格式化長度」,而非實際寫入長度。判斷是否截斷:if (len >= size) truncated = true;

三、strlen 與 memset:基礎且易誤用

函數原型核心語義常見錯誤
strlensize_t strlen(const char *s)返回 首個 \0 前的字符數傳非 \0 結尾指針 → UB;統計含 \0 長度應用 sizeof
memsetvoid *memset(void *s, int c, size_t n)按字節填充 c(取低 8 位)用於非字符數組(如 int[])清零以外數值 → 錯誤;結構體填充可能破壞 padding

memset 正確用法

// 清零結構體/數組(最常用)
memset(&struct_obj, 0, sizeof(struct_obj));
memset(int_arr, 0, sizeof(int_arr));  // 僅適合清 0 或 -1 (0xFF)

// 錯誤示範:memset(arr, 1, sizeof(arr)) → 每字節變 0x01,int 變 0x01010101 ≠ 1

總結建議

  • 解析輸入:優先 sscanf + %[] 模式,複雜場景轉正則或手寫狀態機。
  • 格式化輸出:堅決禁用 sprintf,全面改用 snprintf 或 C++ std::format/fmt::format。
  • strlen 只能用於合法 C 字符串;二進制數據長度用 sizeof 或顯式長度字段。
  • memset 僅用於「按字節置 0/0xFF」,其他數值請用循環或 std::fill。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved