`strchr` 字符串查找函數

1) 函數的概念與用途

strchr 是 C 標準庫中的一個基礎但極其重要的字符串處理函數,它的名字來源于"string chracter"(字符串字符)。這個函數的功能非常明確:在字符串中查找特定字符的第一次出現位置

可以將 strchr 想象成一個精準的探測器:給它一個字符串(如一段文本)和一個要查找的字符,它會從字符串開頭開始掃描,一旦發現目標字符,就立即報告這個字符的準確位置。

典型應用場景包括:

  • 字符串解析:查找分隔符、特定標記或關鍵字符
  • 路徑處理:在文件路徑中查找目錄分隔符(/\
  • 數據驗證:檢查字符串中是否包含特定字符(如電子郵件地址中的 @
  • 文本處理:在文檔中查找特定字符或標記

與之前討論的 strpbrk 函數相比,strchr 更加專注:strpbrk 查找字符集合中的任何一個字符,而 strchr 只查找單個特定字符。

調用 strchrstr, ch
從str起始位置開始掃描
當前字符 == ch?
返回指向該字符的指針
是字符串結尾'\0'?
返回NULL
移動到下一個字符

2) 函數的聲明與出處

strchr 是 C 標準庫(libc)的核心成員,聲明在 <string.h> 頭文件中:

#include <string.h>char *strchr(const char *str, int c);

這意味著在任何符合標準的 C 開發環境中,只需包含這個頭文件即可使用該函數,無需額外鏈接其他庫。

3) 參數詳解:搜索目標與目標字符

  • const char *str

    • 作用:要被搜索的目標字符串(“探測區域”)
    • 要求:必須以 \0 結尾的有效字符串;如果傳入 NULL,會導致未定義行為(通常是段錯誤)
  • int c

    • 作用:要查找的字符(“探測目標”)
    • 特點:雖然參數類型是 int,但實際上它會被轉換為 char 類型進行處理
    • 特殊情況:如果要查找的字符是 '\0',函數將返回指向字符串結尾空字符的指針

4) 返回值:精確的位置指針

  • 成功時:返回指向 str 中第一次出現的字符 c 的指針

    • 這個指針直接指向原字符串中的內存位置,可以用于后續操作
    • 示例:如果 str"Hello"c'e',則返回指向 'e' 的指針
  • 失敗時:返回 NULL

    • 表示在 str 中未找到字符 c
    • 重要:使用前必須檢查返回值是否為 NULL,否則可能引發程序崩潰

5) 實戰演示:多種使用場景

示例 1:基礎用法 - 查找字符

#include <stdio.h>
#include <string.h>int main() {const char *text = "Hello, World!";char target = 'W';// 查找字符 'W'char *result = strchr(text, target);if (result != NULL) {int position = result - text;printf("找到字符 '%c',位置:%d\n", target, position);printf("從該位置開始的子串:\"%s\"\n", result);} else {printf("未找到字符 '%c'\n", target);}return 0;
}

示例 2:查找所有出現的位置

#include <stdio.h>
#include <string.h>int main() {const char *text = "Hello, World!";char target = 'l';const char *current = text;int count = 0;printf("查找字符 '%c' 的所有出現位置:\n", target);// 循環查找所有出現的位置while ((current = strchr(current, target)) != NULL) {int position = current - text;printf("位置 %d: '%c' (剩余字符串: \"%s\")\n", position, target, current);current++; // 移動到下一個字符繼續查找count++;}printf("總共找到 %d 次\n", count);return 0;
}

示例 3:提取子字符串

#include <stdio.h>
#include <string.h>
#include <stdlib.h>int main() {const char *path = "/home/user/documents/file.txt";char separator = '/';// 查找最后一個分隔符const char *last_slash = strrchr(path, separator);if (last_slash != NULL) {// 提取文件名(分隔符后的部分)const char *filename = last_slash + 1;printf("完整路徑: %s\n", path);printf("文件名: %s\n", filename);// 提取目錄路徑(分隔符前的部分)int dir_length = last_slash - path + 1;char *directory = (char*)malloc(dir_length + 1);strncpy(directory, path, dir_length);directory[dir_length] = '\0';printf("目錄路徑: %s\n", directory);free(directory);}return 0;
}

6) 編譯方式與注意事項

編譯命令:

gcc -o strchr_demo strchr_demo.c

關鍵注意事項:

  1. 空指針檢查:使用返回值前必須檢查是否為 NULL
  2. 字符串終止符:確保輸入字符串以 '\0' 結尾,否則可能導致未定義行為
  3. 字符類型:注意第二個參數是 int 類型,但實際按 char 處理
  4. 查找空字符:可以查找 '\0',此時返回指向字符串結尾的指針
  5. 與相關函數的區別
    • strrchr():查找字符的最后一次出現位置
    • strpbrk(str, set):查找字符集合中的任何一個字符
    • strstr(str, substr):查找子字符串

7) 執行結果說明

示例 1 輸出:

找到字符 'W',位置:7
從該位置開始的子串:"World!"

函數在字符串 "Hello, World!" 中找到了字符 'W',它位于位置 7(索引從 0 開始),并返回從該位置開始的子字符串。

示例 2 輸出:

查找字符 'l' 的所有出現位置:
位置 2: 'l' (剩余字符串: "llo, World!")
位置 3: 'l' (剩余字符串: "lo, World!")
位置 10: 'l' (剩余字符串: "ld!")
總共找到 3 次

通過循環調用 strchr,找到了字符 'l' 在字符串中的所有出現位置。

示例 3 輸出:

完整路徑: /home/user/documents/file.txt
文件名: file.txt
目錄路徑: /home/user/documents/

使用 strrchr()(查找最后出現的位置)找到最后一個路徑分隔符,然后分別提取目錄路徑和文件名。

8) 總結:strchr 的核心價值

strchr 是 C 語言字符串處理工具箱中最基礎且必不可少的函數之一。它的價值在于:

  1. 高效簡單:提供了一種直接的方法來查找字符串中的特定字符
  2. 廣泛應用:是許多字符串處理操作的基礎構建塊
  3. 標準兼容:作為 C 標準庫的一部分,具有高度的可移植性
字符串查找需求
如何選擇函數?
查找單個特定字符
使用 strchr 或 strrchr
查找字符集合中任何一個字符
使用 strpbrk
查找子字符串
使用 strstr

最佳實踐建議:

  1. 始終檢查返回值:避免對 NULL 指針進行解引用
  2. 注意字符編碼:對于非ASCII字符,確保理解當前環境的字符編碼
  3. 考慮使用更安全的變體:在某些環境中,可以考慮使用更安全的函數如 strchr_s(C11)
  4. 性能考量:對于大量數據的重復查找,考慮使用更高效的算法

strchr 雖然簡單,但卻是 C 語言編程中不可或缺的工具。掌握它的正確用法和注意事項,對于編寫健壯、高效的字符串處理代碼至關重要。無論是處理用戶輸入、解析文件格式還是分析文本數據,strchr 都能提供簡單而有效的解決方案。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/96526.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/96526.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/96526.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Redis 678

Redis 8 是當前的最新穩定版&#xff08;截至 2024 年中&#xff09;&#xff0c;它在 Redis 7 的基礎上帶來了更多重要改進。我們來對這三個主要版本進行一次全面的功能和性能對比。 核心演進脈絡 Redis 6 (2020)&#xff1a;多線程時代的開創者。解決了網絡 I/O 瓶頸&#xf…

【大白話解析】 OpenZeppelin 的 Address 庫:Solidity安全地址交互工具箱?(附源代碼)

?? 一、這個文件是干嘛的?—— Address.sol 是個“工具箱” 你可以把這個 Address.sol文件理解為一個 ??“工具箱”??,里面裝了一堆??專門用來安全地跟別的地址(賬戶或合約)打交道的工具函數??。 在區塊鏈世界里,地址(address)可以是: ??外部賬戶(EOA)…

漫談《數字圖像處理》之測不準原理

在數字圖像處理中&#xff0c;提到的 “測不準原理” &#xff0c;和量子力學里由海森堡提出的 “不確定性原理” &#xff08;Heisenberg uncertainty principle&#xff0c;也叫海森堡測不準原理&#xff09;有一定的類比關系&#xff0c;但本質上并不是同一個概念。以下為詳…

Linux服務測試

一、環境準備確認 確保 4 臺主機&#xff08;APPSRV、STORAGESRV、ROUTERSRV、CLIENT &#xff09;網絡連接正常&#xff0c;虛擬機網卡模式按要求設置&#xff08;APPSRV、STORAGESRV 為 NAT 模式&#xff1b;ROUTERSRV 為雙網卡&#xff0c;NAT 僅主機模式&#xff1b;CLIE…

2.Shell腳本修煉手冊---創建第一個 Shell 腳本

2. 創建第一個 Shell 腳本 文章目錄2. 創建第一個 Shell 腳本2.1 什么是 Shell 腳本&#xff1f;2.1.1 腳本開頭&#xff1a;告訴系統用什么程序執行2.1.2 腳本注釋&#xff1a;給人看的 “說明書”2.1.3 bash 與 sh 的區別2.2 如何執行 Shell 腳本&#xff1f;方法 1&#xff…

Day22 順序表與鏈表的實現及應用(含字典功能與操作對比)

day22 順序表與鏈表的實現及應用&#xff08;含字典功能與操作對比&#xff09; 使用順序表實現查字典功能 支持連續查詢單詞&#xff0c;輸入 #quit 退出程序。數據格式示例如下&#xff1a; a\0 indef art one\r\n word mean [---buf--->] [---i--…

51單片機與stm32單片機,先學習哪一個?

糾結 51 單片機和 STM32 該先學哪個&#xff0c;就像剛學開車的人在自動擋和手動擋之間打轉。有人一上來就愛開自動擋&#xff0c;踩著油門就能跑&#xff0c;不用琢磨換擋踩離合的門道&#xff1b;有人偏要從手動擋練起&#xff0c;哪怕起步時熄十幾次火&#xff0c;也得搞明白…

DS 0 | 數據結構學習:前言

數據結構是CS最基礎、最重要的課程之一在學習數據結構時&#xff0c;通常來講&#xff0c;學生遇到的難點不在于對數據結構的理解&#xff0c;而在于如何寫程序。即編寫特定的程序&#xff0c;來實現這些數據結構&#xff0c;特別是如何按照面向對象思想將一個個數據結構設計成…

JVM-(8)JVM啟動的常用命令以及參數

JVM啟動的常用命令以及參數 在上文 JVM 堆內存邏輯分區 中已經使用過一些 jvm 啟動命令&#xff0c;本文著重講述JVM啟動命令用法以及一些常用的參數 一. 基本命令格式 java [options] classname [args...] java [options] -jar filename.jar [args...]① [options] - 命令行…

GO學習記錄七——上傳/下載文件功能,添加啟動運行工具

本來計劃是學習Docker部署的&#xff0c;研究了一天沒搞出來&#xff0c;得出結論是需要翻墻&#xff0c;懶得弄了&#xff0c;暫時放置。 一、以下是&#xff0c;上傳/下載代碼&#xff0c;和之前是重復的&#xff0c;只多添加了&#xff0c;上傳/下載功能。 測試目錄為工程根…

SQL中對視圖的操作命令匯總

以下是基于搜索結果整理的SQL視圖操作命令匯總&#xff0c;按功能分類說明&#xff1a; 一、創建視圖 使用 CREATE VIEW 語句定義視圖&#xff0c;需指定視圖名稱和基礎查詢表達式&#xff1a; CREATE VIEW view_name AS SELECT column1, column2, ... FROM table_name WHER…

【Spring Cloud 微服務】2.守護神網關Gateway

目錄 1.API網關的作用 2.Spring Cloud Gateway 是什么&#xff1f; 3.核心由來與背景 1. 微服務架構的挑戰&#xff1a; 2. API 網關模式的興起&#xff1a; 3. Zuul 的局限性&#xff1a; 4. Spring Cloud Gateway 的誕生&#xff1a; 4.核心特征&#xff1a; 5.核心概…

解讀商業智能BI,數據倉庫中的元數據

之前的文章討論過數據分析、數據治理、數據倉庫等等&#xff0c;即使是非業內人員從字面意思&#xff0c;也是可以了解一二的&#xff0c;但是&#xff0c;很多人對于元數據可能就比較陌生了。那么&#xff0c;今天我們就來聊一聊元數據管理。數據倉庫要說元數據&#xff0c;那…

3 種無誤的方式刪除 Itel 手機上的短信

如果你希望釋放存儲空間、保護隱私&#xff0c;或者準備出售或轉讓手機&#xff0c;刪除 Itel 手機上的短信是一個實用的步驟。無論是收件箱中充斥著垃圾短信、過時的對話還是敏感內容&#xff0c;刪除不需要的短信可以讓你的消息體驗更加干凈和安全。本文將向你介紹 3 種簡單且…

【學習筆記】網絡安全專用產品類別與參考標準

一、基本標準 1.1 關鍵設備 網絡關鍵設備認證依據的強制標準為 GB 40050-2021。 1.2 專用產品 網絡安全專用產品認證依據的強制標準為 GB 42250-2022。 二、數據備份與恢復產品標準 相關標準&#xff1a; GB/T 29765-2021《信息安全技術 數據備份與恢復產品技術要求與測試評…

Pytho“張量”(Tensor)和 Java的“向量”(Vector)區別和聯系

在Python和Java中&#xff0c;“張量”&#xff08;Tensor&#xff09;和“向量”&#xff08;Vector&#xff09;是兩個不同語境下的概念&#xff0c;它們的設計目標、功能和應用場景存在顯著差異&#xff0c;但也存在一定的共性。以下從區別和聯系兩方面詳細說明&#xff1a;…

Ubuntu部署K8S集群

Ubuntu部署K8S集群 本例以三臺Ubuntu24.04為例,1master節點2worker節點 環境準備 修改hostname,三臺服務器分別執行 hostnamectl set-hostname k8s-master01hostnamectl set-hostname k8s-worker01hostnamectl set-hostname k8s-worker02 配置靜態ip(不同系統修改方法略微差…

openEuler系統安裝Ascend Docker Runtime的方法

在openEuler系統中使用NPU前一定要安裝Ascend Docker Runtime,也是在安裝CANN和mis-tei前的必備工作。 使用容器化支持、整卡調度、靜態vNPU調度、動態vNPU調度、斷點續訓、彈性訓練、推理卡故障恢復或推理卡故障重調度的用戶,必須安裝Ascend Docker Runtime。 下面是具體的安…

控制對文件的訪問:Linux 文件系統權限管理總結

在 Linux 系統中&#xff0c;文件權限是保障系統安全和數據完整性的核心機制。紅帽企業 Linux 9.0通過一套靈活且精細的權限控制體系&#xff0c;讓用戶能夠精確管理文件和目錄的訪問范圍。本章將系統梳理 Linux 文件系統權限的核心概念、管理方法及高級應用&#xff0c;為系統…

ansible中roles角色是什么意思?

文章目錄一、介紹二、Ansible Roles目錄編排三、創建role四、playbook調用角色五、roles中tags使用免費個人運維知識庫&#xff0c;歡迎您的訂閱&#xff1a;literator_ray.flowus.cn 一、介紹 角色是ansible自1.2版本引入的新特性&#xff0c;用于層次性、結構化地組織playbo…