【C 標準庫】<string.h>

来源:http://www.cnblogs.com/tyrus/archive/2016/06/16/c_string.html
-Advertisement-
Play Games

參考鏈接:C 標準庫 - <string.h> string.h中主要有兩類函數: memxxx 和 strxxx,其中memxxx是針對記憶體操作的函數,在遇到'\0'的時候並不會停下來,而通常是設置一個size_t類型(其實是unsigned int)的參數來表示位元組大小; 而strxxx是針對字 ...


參考鏈接:C 標準庫 - <string.h>

string.h中主要有兩類函數:

  memxxx 和 strxxx,其中memxxx是針對記憶體操作的函數,在遇到'\0'的時候並不會停下來,而通常是設置一個size_t類型(其實是unsigned int)的參數來表示位元組大小;

  而strxxx是針對字元串操作的函數,遇到'\0'停下來。strxxx函數中,有一些函數是strnxxx的,這些函數可以通過傳入一個size_t類型的參數來表示位元組大小,所以遇到'\0'或到達位元組大小都會停下來,相對安全。

 

以下分組介紹函數:

1、memcpy memmove strcpy strncpy

void *memcpy(void *dest, const void *src, size_t n);
void *memmove(void *dest, const void *src, size_t n);
char *strcpy(char *dest, const char *src);
char *strncpy(char *dest, const char *src, size_t n);
 
// 記憶體拷貝。當拷貝字元串的時候,考慮到'\0'的問題,可以這樣拷貝進str1。此時如果str2中有\0,拷貝動作仍然會進行下去,直到達到n次
memcpy(str1, str2, sizeof(str1) - 1);
str1[sizeof(str1) - 1] = '\0';
// 遇到記憶體重疊的情況,memmove是更安全的,不會造成覆蓋的情況
// http://stackoverflow.com/questions/4415910/memcpy-vs-memmove
char str5[] = "aabbcc";
printf( "The string: %s\n", str5 );
memcpy( str5, str5 + 2, 4 );    // cccccc , wrong
printf( "New string: %s\n", str5 );

strncpy( str5, "aabbcc", sizeof(str5) );   // reset string

printf( "The string: %s\n", str5 );
memmove( str5, str5 + 2, 4 );   // bbcccc , right
printf( "New string: %s\n", str5 );


// 字元串拷貝。同理,strncpy也是如此。不過memcpy不考慮中間遇到'\0'的問題,而strncpy遇到\0就停止拷貝
ret = strncpy(str1, str2, sizeof(str1) - 1);
str1[sizeof(str1) - 1] = '\0';
// 如果str1的空間不足以放下str2,就會造成記憶體溢出
ret = strcpy(str1, str2);

  

2、memcmp strcmp strncmp

stackoverflow里有個回答舉例很詳細:what-is-the-difference-between-memcmp-strcmp-and-strncmp-in-c

strcmp 比較的是以'\0' 結束的字元串

strncmp 比較的是至多n個字元、以'\0'結束的字元串

memcmp 比較的是n個位元組的二進位位元組緩衝區

void *memcpy(void *dest, const void *src, size_t n);
char *strcpy(char *dest, const char *src);
char *strncpy(char *dest, const char *src, size_t n);

 

    const char s1[] = "atoms\0\0\0\0";  // extra null bytes at end
    const char s2[] = "atoms\0abc";     // embedded null byte
    const char s3[] = "atomsaaa";

    if(strcmp(s1, s2) == 0){printf("strcmp(s1, s2) == 0 \n");}      // strcmp stops at null terminator
    if(strcmp(s1, s3) != 0){printf("strcmp(s1, s3) != 0 \n");}      // Strings are different
    if(strncmp(s1, s3, 5) == 0){printf("strncmp(s1, s3, 5) == 0 \n");}  // First 5 characters of strings are the same
    if(memcmp(s1, s3, 5) == 0){printf("memcmp(s1, s3, 5) == 0 \n");}   // First 5 bytes are the same
    if(strncmp(s1, s2, 8) == 0){printf("strncmp(s1, s2, 8) == 0 \n");}  // Strings are the same up through the null terminator
    if(memcmp(s1, s2, 8) != 0){printf("memcmp(s1, s2, 8) != 0 \n");}   // First 8 bytes are different

  

3、memchr strchr strrchr

memchr 在記憶體中,從某個地址開始到n個位元組之後,返回最早匹配到的字元的指針

strchr 在一個字元串中,返回最早匹配到的字元的指針

strrchr 在一個字元串中,返回最後一個匹配到的字元的指針

void *memchr(const void *str, int c, size_t n);
char *strchr(const char *str, int c);
char *strrchr(const char *str, int c);

  

    char chr[] = "there is an orange";
    const char *memchrres = memchr(chr, 'r', 12); // 中間的int型參數其實需要傳入char型的字元。。
    const char *strchrres = strchr(chr, 'r');
    const char *strrchrres = strrchr(chr, 'r');
    printf("memchrres:(%p) %s, strchrres:(%p) %s, strrchrres:(%p) %s \n", &memchrres, memchrres, &strchrres, strchrres, &strrchrres, strrchrres);

  

4、memset:將s所指向的某一塊記憶體中的前n個 位元組的內容全部設置為ch指定的ASCII值, 第一個值為指定的記憶體地址,塊的大小由第三個參數指定,這個函數通常為新申請的記憶體做初始化工作, 其返回值為指向s的指針(摘自 百度百科)

void *memset(void *str, int c, size_t n);

  

struct S abc;
memset(&abc, 0, sizeof(struct S));

 

5、strstr:在字元串 haystack 中查找第一次出現字元串 needle(不包含空結束字元)的位置。

char *strstr(const char *haystack, const char *needle);

  

    const char haystack[20] = "W3CSchool lalala";
    const char needle[10] = "School";
    char *strres;
    strres = strstr(haystack, needle);
    printf("%s \n", strres);

  

6、strlen strnlen

strlen 計算字元串的長度,直到空結束字元,但不包含空結束字元

strnlen 以上函數不安全,如果字元串非法(不包含'\0'),所以需要規定最大匹配長度,防止記憶體溢出

size_t strlen(const char *str);
size_t strnlen(const char *str, size_t maxlen);

  

    const char strlenres[] = "test strlen";
    printf("strlen = %d \n", (int)strlen(strlenres));
    // 如果string沒有\0的時候,會判斷出錯
    printf("strnlen = %d \n", (int)strnlen(strlenres, sizeof(strlenres)));

  

7、strcat strncat

strcat 把源字元串追加到目標字元串的後面

strncat 規定最大追加數n,相對安全

char *strcat(char *dest, const char *src);
char *strncat(char *dest, const char *src, size_t n);

  

    char cat1[20] = "lalala";
    char cat2[] = "short";
    char cat3[] = "longlong";
    printf("res1 = %s \n", strcat(cat1, cat2));
    printf("res2 = %s \n", strncat(cat1, cat2, sizeof(cat1) - 1 - strlen(cat1)));
    printf("res3 = %s \n", strncat(cat1, cat3, sizeof(cat1) - 1 - strlen(cat1)));

  

8、strtok:根據給定的分隔符,分割一個長的字元串(使用方法很怪異。。)

char *strtok(char *str, const char *delim);

  

    char tok[80] = "This is - www.w3cschool.cc - website";
    const char delim[] = "-";
    char *token = strtok(tok, delim);   // 獲取第一個字元串
    while(token != NULL){
        printf("%s \n", token);
        token = strtok(NULL, delim);    // 註意!
    }

  

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 前天去面試,讓我說下生命周期,本來之前就瞭解過,但是沒說出來,被深深的鄙視了;今天弄了一上午,現在發到這分享一下,有什麼錯誤請各位大牛們指出~~ 昨天面試,又遇到這問題了... 然後說了半天,人家問我一用戶控制項的周期在哪執行,我想了半天,也沒有想出來,回來只好再研究了.. 請求的本頁面Page-Lo ...
  • ...
  • FileAccess Enumeration 定義用於文件讀取、寫入訪問許可權的常數。此枚舉有一個FlagsAttribute特性,通過該特性可使其成員值按位組合。(命名空間:System.IO) 語法 [SerializableAttribute] [FlagsAttribute] [ComVisi... ...
  • 今天遇到了一個關於日期的問題,需要將2016-6-15 20:23:23這種形式的時間字元串轉換為2016年6月15日,由於學習經驗少,但是懵逼了0.0, 後來百度找到了相關方法。同時,也將常用的日期轉換方法的用法保存下來。供大家學習查閱。 我的代碼: 運行結果: ...
  • Private Sub textbox1_KeyPress(ByVal sender As System.Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles textbox1.KeyPress If e.KeyChar ...
  • 1、設置父窗體: 如果要將某個窗體設置為父窗體,只需將該窗體的IsMdiContainer屬性設置為True即可。 2、設置子窗體: 通過設為某個窗體的MdiParent屬性來確定該窗體是那個窗體的子窗體。 語法如下: 3、排列MDI子窗體: 語法如下: value:是MdiLayout的枚舉值之一 ...
  • 問題:如下代碼 想獲取某兩個Decimal類型數之間的商的大小,結果偶爾出錯(請註意是 偶爾) Decima t1; Decima t2; int shang =Convert.ToInt32(t1 / t2) ; 解決方法:將Decimal類型數據強制轉換成INT整型時 會有四捨五入的過程。如下, ...
  • 本文參考Roslyn項目Issue:#206,及Docs:#patterns。 1. C# 7.0 新特性1: 基於Tuple的“多”返回值方法 2. C# 7.0 新特性2: 本地方法 3. C# 7.0 新特性3: 模式匹配 模式匹配也許能算的上C#本次更新最重量級的升級,也是最受關註的特性(也 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...