天天看點

【C/C++】string.h、stdlib.h、math.h、string函數庫回顧

  寫這篇部落客要是為了疏理一下C/C++标準庫自帶字元串操作函數 ,為迎接9月的“細細诶夫“考試的孩子們(包括我自己咯)整理思路,在處理字元串問題時更加得心應手。

  閑話少說,開始進入正體。C/C++中對字元串的操作函數有不少,集中分布在C string.h、stdlib.h,C++ string頭檔案中,當然不排除将其視為容器也可使用algorithm的算法(這個以後再讨論),主要涉及的字元串的複制、移動、連接配接、比較、搜尋、到其他數值類型的互相轉換、以及其他操作,接下來按功能進行分别解析各函數用法以及應用。此外,還将讨論一下其他有用的工具性函數。

C篇:

<string.h> / <cstring>

一.複制

1.(沒什麼卵用系列) void* memcpy(void* destination,const void* source, size_t num)

    void* memmove(void* destination, const void* source, size_t num)

這兩個函數屬于對記憶體塊進行操作函數,操作對象是記憶體,是以無視\0l字元的終止限定,從source指針指向的記憶體往後數num bytes,将其copy/move到destination,copy與move均不會導緻destination記憶體的自動配置設定,是以需要程式員自己預先配置設定足夠的記憶體,使用memcpy需要注意source與destination不能有重疊,即存在共有部分,而memmove則允許存在重疊部分,是以比memcpy更安全。

2.(有點用)char* strcpy(char* destination, const char* source)

   char* strncpy(char* destination, const char* source, isize_tnum)

與上面兩個mem氏函數不同,str氏的操作對象是字元數組/c風格字元串,是以會受到\0限定,這也可以從參數與傳回值類型為char*而不是void*中看出,于是存在不指定num的情況和指定num的情況,指定num主要對于有特定需求(截取前num位元組)進行複制操作,同樣,這兩個函數也不會對記憶體執行配置設定操作,是以需要程式員自己管理記憶體,防止溢出。

二.連接配接(有點用)

  char* strcat(char* destination, const char* source)

  char* strncat(char* destination, const char* source, size_t num)

這兩個函數功能為将source的(帶有n則是前num個)字元連接配接到destination尾部,同樣需要程式員保證不會溢出,同時,通過以上我們也能知道c函數庫的命名的套路:操作對象+操作,如果隻對前n個位元組/字元操作,需要在中間加上n,參數為目标字元數組+源字元數組+num,傳回值為目标字元數組。

三.比較(有用)

  int strcmp(const void* ptr1, const void* ptr2)

  int strncmp(const* char* ptr1, const char* ptr2, size_t num)

這兩個函數功能為将ptr字元數組與ptr2字元數組按字典順序進行比較,ptr1 > ptr2傳回1,ptr1 == ptr2傳回0,ptr1 < ptr2傳回-1。(n的作用同上)

四.搜尋(有用)

1.  char* strchr(char* str, int character)

     char* strrchar(char* str, int character)

在str中搜尋character字元出現的第一個/最後一個,如果搜尋到,傳回一個指針指向這個字元,如果不存在,傳回NULL。

  char* strstr(char* str1, char* str2)

在str1中搜尋字串str2,如果搜尋到,傳回一個指針指向這個字元,如果不存在,傳回NULLl。

2.size_t strspn(const char* str1, const char* str2) (特定情況有用)

   size_t strcspn(const char* str1, const char* str2)

中間不帶有c的函數(即strspn)功能為從str1第一個字元從前往後查找在str2中出現過的字元,直到遇到不屬于str2的字元,傳回之前在str2出現過的字元的個數。

中間帶有c的函數(即strcspn)功能“相反”,從str1第一個字元從前往後查找未在str2中出現的字元,直到遇到屬于str2的字元,傳回之前在str2中未出現的字元的個數。

    char* strpbrk(const char* str1, const* str2)

在str1中查找第一次出現的屬于str2的字元,并傳回一個指針指向這個字元,如果不存在,傳回NULL。

 3.char* strtok(char* str, const char* delimiters) (有用+)

    字元串分割函數,這個函數使用起來相比之前略複雜,第一次調用的第一個參數是需要分割的字元串,第二個為分割的标志字元串,而以後每一次調用第一個參數需要調整為NULL,第二個參數不變,傳回值為指向分割後的字串的指針,在每一次查找到後,将找到的标志指派為NULL(\0)。回顧整個流程,相當于将字元串中的标志字元串全部用\0替代,在每一次調用時傳回每個字串的首位址。

五.長度(最常用)

size_t strlen(const char* str)

傳回字元串的長度,以\0作為終止符。

<stdlib.h>/<cstdlib>

一.字元串轉換函數

  首先說一下命名的套路:a和str都代表字元串,to代表轉換,數值資料類型的前面的字母代表其他數值資料類型,如i代表int,l代表long,f代表float,

d代表double,然後是沒什麼多用的ul,代表usigned long,其中當後面的為f,i,l時,a代表字元串,為d,l時str代表字元串。

  atox的參數為字元數組,傳回值為到第一個不為數字之前的字元字串轉換成為的數字,例如"12306str",将傳回12306,"123 06"将傳回123,而“str12306”将傳回0,超出int範圍将引發為定義的行為。

  那麼就會有人想,如果我需要擷取譬如"12306str12580"這樣的字元串中的每一個數值字串的值呢,strtox可以做到。strtox提供了第二個參數,char** endptr,每次調用函數後,*endptr将會指向轉換後的數值的後一個字元,譬如說第一次調用strtol("12306str12580“, &endPtr, 10)後,endptr将會指向's',第二次調用後将會指向't',第三次指向'r',第四次指向最後\0,對于非小數類型,還提供了第三個參數,表示進制數,如16,則可以将"0xf"轉換為15,如2,則可以将"110"轉換為6。

二.算法

隻有兩個,快速排序函數和二分搜尋函數,由于使用起來較為繁瑣,一般會被STL中的sort和find函數代替。

void qsort(void* base, size_t num, size_t size, int (*comptr)(const void*, const void*) )

void* bsearch(const void* key,const void* base, size_t num, size_t size,int (*comptr)(const void*, const void* ) )

由于函數本身不知道傳進去的資料類型,是以需要指定數組元素size大小,函數也不知道數組長度,需要指定數組大小,提供比較器則是指定比較的規則,注意bsearch傳回的是void*,是以在使用時要注意進行顯示的轉換。

三.數學運算

1.絕對值

abs和labs,取絕對值,分别對應int型和long型

2.整除

div和ldiv,傳回值是結構體div_t、ldiv_t,

typedef struct {    typedef struct {

  int quot;                  long quot;

  int rem;                   long rem;

} div_t;                      } ldiv_t;

quot代表整除的結果,rem代表餘數。

<math.h>/<cmath>

1.絕對值函數

abs與fabs,二者之間并沒有什麼明顯的差別,主要對浮點數進行操作,傳回值為float、double,與stdlib中的相混合可能會讓人比較糾結,但是一個強制類型轉換就可以解除選擇困難症的問題,部落客一般用fabs。

2.舍入

ceil,floor,round:ceil為向上取整,floor為向下取整,round傳回距離參數最近的整數。

3.乘方/開方

pow,sqrt:常用函數,不多解釋了。

C++篇:

<string>

終于到了c++的舞台了,被c中繁瑣的函數糾纏的欲生欲死?系加加是你的福音。

首先,談到string頭檔案就有必要談談string類本身了。

string類本身可以視為一種STL容器類,它擁有iterator,也擁有begin(),end(),push_back(),pop_back(),insert(),erase()等基本函數,是以可以某種意義上可以将string當作vector<char>來使用,algorithm中的算法也可以完美的應用在string類上。這些都是後話了,現在主要讨論string作為string所具有的獨特函數:

1.構造函數:

default (1)

string(); //預設構造函數,沒什麼可說的

copy (2)

string (const string& str); //通過另外一個string的複制構造函數,也沒有什麼好說的

substring (3)

string (const string& str, size_t pos, size_t len = npos); //通過另外一個string的某一部分,某種意義上相當于取字串

from c-string (4)

string (const char* s); //通過c風格字元串,是c-string到string的途徑

from sequence (5)

string (const char* s, size_t n);  //通過c風格的字串建立

fill (6)

string (size_t n, char c);  //用n個相同的字元建立

range (7)

template <class InputIterator>  //通過疊代器建立

  string  (InputIterator first, InputIterator last);

2.析構函數

pass~

3.擷取大小

size()方法和length()方法,并無什麼差別,可能是為了與傳統的length和STL的size相容而特意弄出兩個來。

4.連接配接

+=重載或者append()方法

5.複制

=運算符重載

6.替換

replcae()方法,前兩個參數為位置 + 長度,這個格式在之前的c函數中也頻繁出現,後面的參數為字元串的各種表示方法以及取字串添加的數字。

7.擷取字元

[]運算符重載,或者at方法

8.查找

find()方法,參數是要查找的字元串/字元 + 查找起始位置,要查找的字元串為c-string還可以加上一個數字指明c-string的長度。

r_find()為反向查找。

*注意,這裡如果沒有找到傳回的是string::nopos。

9.比較

compare()方法,按照字典順序比較

10.截取字串

substr()方法,參數為起始位置+長度。

11.轉化為c-string

c_str()方法。

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

  寫到這裡部落客有必要說以下,剛才發現string中其他函數全是c++11的,為了突顯針對“系系诶夫”的主題,部落客決定去除部落格c++11的内容,以免産生誤導作用,但

值得一提的是,c/c++/java等各個語言都在與時俱進,都在發展,而考試卻僅僅停留在98标準,實在讓人感到費解,新标準中加入了對原有标準的補充與修複,是值

的去學習的,也希望“系系诶夫”有一天能發揮預期的作用。寫了兩三個小時,後面的有些簡略,以後有空完善,如果有錯誤敬請指出。

  休息會去了==下個部落格見。