首頁 > 軟體

盤點分析C語言中少見卻強大的字串函數

2022-02-14 13:00:34

正片開始

字串函數

首先神魔是字串函數?

指的是程式語言中用來進行字串處理的函數,如C,pascal,Visual以及LotusScript中進行字串拷貝,計算長度,字元查詢等的函數。 功能:把src所指由NUL結束的字串複製到dest所指的 陣列 中。 返回指向dest結尾處字元 (NUL)的 指標 。

像之前我寫到過的 strcpy,strcat,strcmp 這些函數都屬於長度不受限的字串函數,由此就有下面兩種分類

1.長度不受限的字串函數

2.長度受限的字串函數

長度不受限就是以‘ ’為函數結束標準的判定,當物件沒給定 ’ '時,就跑不出結果或者報錯;相反則為長度受限。我再整理一下,好做個對比:

strcpy

字串拷貝,把指向的字串複製到目標字串,宣告為

char *strcpy(char *dest, const char *src)

strcat

字串連續,把指向的字串追加到目標字串的結尾(無間隔),宣告為:

char *strcat(char *dest, const char *src)

strcmp

把所指向的字串和目標字串進行比較, 返回值大小決定二者的相對大小,宣告如下:

int strcmp(const char *str1, const char *str2)

以上三種是函數的長度受限,我們可以變 strncpy,strncat 和 strncmp,就是長度不受限函數了,相比多了一個 n ,這個 n 是指函數作用範圍最多在前 n 個位元組,比如 strncmp 中的n 就是要比較的最大字元數,就相當於一個限制機制了。

這裡主要補充幾個比較實用的吧:

strstr

其實顧名思義,翻譯過來就是“字串字串”,其實作用就是在一個字串裡面找我的目標字串,不包含終止符 ‘’,返回值是該函數在 目標字串中第一次出現該字串的位置。宣告為:

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

舉個栗子:

int main()
{
	char a[] = "overwatch";
	char b[] = "wa";
	char* c = strstr(a, b);
	if (c != NULL)
	{
		printf("found it: %sn", c);
	}
	else
	{
		printf("there was nothingn");
	}
	return 0;
}

我們用最常規的程式碼也可以模擬出 strstr 的功能,庫函數的實現方法也是類似

#include<assert.h>
char* strstr1(const char* a, const char* b)
{
	assert(a && b);
	const char* c = NULL;
	const char* d = NULL;
	const char* str = a;
	if (*b == '')
	{
		return (char*)a; //處理查詢語句為空語句
	}
	while (*str)
	{
		c = str;
		d = b;
		while (*c && *d && (*c == *d))//防止相同元素為'' 迴圈繼續導致越界存取
		{
			*c++;
			*d++;
		}
		if (*d == '')
		{
			return (char*)str;
		}
		str++;//多次查詢,匹配錯誤會回到起點++再重新查詢
	}
	return NULL;
}

要注意的是,該函數規定當查詢物件字串為空 () 時,會返回目標字串的地址。

KMP演演算法

說到了 strstr ,引申一下KMP演演算法,也就是字串查詢演演算法,稱之為 Knuth-Morria-Pratt 演演算法。該演演算法相對於暴力演演算法有比較大的改進,主要是消除了主串指標的回溯,從而使演演算法效率有了某種程度的提高。KMP演演算法比我們的 strstr 效率要高,我們日後再細細講解

strtok

我們可以稱之為字串刀,作用就是分割字串,strtok() 函數的宣告如下:

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

str 為一組字串,delim 為分隔符,也可以是個集合,分割結果變成第一個子字串。

因為結果被修改所以 strtok 物件一般為臨時拷貝的可修改內容。舉個栗子:

int main()
{
	char a[] = "overwatch";
	char b[20] = { 0 };
	char* ret = NULL;
	strcpy(b, a); //進行臨時拷貝方便切割
	char* p = "w";//指標型別維護分隔符
	ret = strtok(b, p);
	printf("%sn", ret);
	return 0;
}

若要進一步分割,我們需要空指標進行維護,什麼意思?
分割完一次,結尾就會變成 ‘ ’,此時的 strtok 記憶能力已經記住了 ‘ ’的位置,這個記憶功能我們大致都能猜出是一個靜態變數,static 修飾一個區域性變數時就可以做到這點,就是我們只需要傳入一個 null ,就可以自動進行分割,以此類推:

	strtok(b, p);
	ret = strtok(NULL,"t");

strerror

咱在使用庫函數時,總會有呼叫失敗的時候,這時候都會有一個錯誤碼被設定,這個錯碼都會放進 errno 這個全域性錯誤碼裡面,我們看到的錯誤資訊可能是一個莫名其妙的數位,而 strerror 就是將錯誤碼翻譯成錯誤資訊,並返回一個指向錯誤訊息字串的指標。strerror 生成的錯誤字串取決於開發平臺和編譯器。

char *strerror(int errnum)

比如:

int main()
{
	printf("%sn", strerror(10));
	printf("%sn", strerror(20));
	printf("%sn", strerror(30));
	return 0;
}

結果分別是:無子程序,非目錄元素,唯讀檔案系統

但其實 strerror 並不是小題大做拿來查詢錯誤的,是在文字上輸入輸出時方便我們得知開啟寫入開啟失敗的原因的,當我們嘗試開啟一個不存在的檔案時就會報錯: No such file or directory

#include <errno.h>
int main ()
{
   FILE *fp;  fp = fopen("file.txt","search");
   if( fp == NULL ) 
   {
      printf("Error: %sn", strerror(errno));
   }  
  return(0);
}

因為我們要呼叫C語言給出的全域性變數 errno,所以記得要引 <errno.h> 標頭檔案。

以上就是盤點分析C語言中少見卻強大的字串函數的詳細內容,更多關於C語言字串函數的資料請關注it145.com其它相關文章!


IT145.com E-mail:sddin#qq.com