目錄

7. strncat函數的使⽤

8. strncpy函數的使⽤

9. strncmp函數的使⽤

10. strstr的使⽤和模擬實現

11. strtok函數的使⽤

12. strerror函數的使⽤


7. strncat 函數的使⽤

函數原型如下:

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

注意:

  • 將source指向字符串的前num個字符追加到destination指向的字符串末尾,再追加⼀個 符)。 \0 字
  • 如果source 指向的字符串的⻓度⼩於num的時候,只會將字符串中到 \0 的內容追加到destination指向的字符串末尾
int main()
{
	char arr1[] = "abcdef";
	char arr2[20] = "xxxxxxxxxxx";
	//char arr2[20] = "xx\0xxxxxxxx"; //如果數之間加了個\0,追加從\0包括\0,開始追加,即會把\0替換掉
	strncat(arr2, arr1, 8);  //追加8個數,不夠的用\0填補
	printf("%s\n", arr2);
	return 0;
}

輸出結果:

c語言—字符函數和字符串函數進階篇—筆記_bc

如果數之間加了個\0,追加從\0包括\0,開始追加,即會把\0替換掉

代碼如下:

int main()
{
	char arr1[] = "abcdef";
	//char arr2[20] = "xxxxxxxxxxx";
	char arr2[20] = "xx\0xxxxxxxx"; //如果數之間加了個\0,追加從\0包括\0,開始追加,即會把\0替換掉
	strncat(arr2, arr1, 8);  //追加8個數,不夠的用\0填補
	printf("%s\n", arr2);
	return 0;
}

輸出結果:

c語言—字符函數和字符串函數進階篇—筆記_字符串_02

8. strncpy 函數的使⽤

函數原型:

char * strncpy ( char * destination, const char * source, size_t num );

注意:

  •   拷⻉num個字符從源字符串到⽬標空間。
  •   如果源字符串的⻓度⼩於num,則拷⻉完源字符串之後,在⽬標的後邊追加0,直到num個

拷貝8個數據

int main()
{
	char arr1[] = "abcdef";
	char arr2[] = "xxxxxxxxx";
	//strncpy(arr2,arr1,3); //這裏的3是,只會拷貝arr1裏面的前三個數,\0也不會算進去,是3個,就是3個
	strncpy(arr2, arr1, 8); //這裏的8顯然超過了arr1裏面的數,但是我們還是會拷貝8個數,不夠的用\0來填補
	printf("%s\n", arr2);
	return 0;
}

輸出結果:

c語言—字符函數和字符串函數進階篇—筆記_bc_03

拷貝3個數據

int main()
{
	char arr1[] = "abcdef";
	char arr2[] = "xxxxxxxxx";
	strncpy(arr2,arr1,3); //這裏的3是,只會拷貝arr1裏面的前三個數,\0也不會算進去,是3個,就是3個
	//strncpy(arr2, arr1, 8); //這裏的8顯然超過了arr1裏面的數,但是我們還是會拷貝8個數,不夠的用\0來填補
	printf("%s\n", arr2);
	return 0;
}

輸出結果:

c語言—字符函數和字符串函數進階篇—筆記_錯誤碼_04

9. strncmp函數的使⽤

函數原型如下:

int strncmp ( const char * str1, const char * str2, size_t num );

⽐較str1和str2的前num個字符,如果相等就繼續往後⽐較,最多⽐較num個字⺟,如果提前發現不⼀ 樣,就提前結束,⼤的字符所在的字符串⼤於另外⼀個。如果num個字符都相等,就是相等返回0.

c語言—字符函數和字符串函數進階篇—筆記_bc_05

代碼如下:

只設置3個比較數

int main()
{
	char arr1[] = "abcdef";
	char arr2[] = "abcq";
	int ret = strncmp(arr1, arr2,3); //只和前3個數繼續比較大小
	printf("%d\n", ret);
	return 0;
}

輸出結果:

c語言—字符函數和字符串函數進階篇—筆記_錯誤碼_06

設置4個數,代碼如下:

int main()
{
	char arr1[] = "abcdef";
	char arr2[] = "abcq";
	int ret = strncmp(arr1, arr2,4); //只和前3個數繼續比較大小
	printf("%d\n", ret);
	return 0;
}

輸出結果:

c語言—字符函數和字符串函數進階篇—筆記_bc_07

10. strstr 的使⽤和模擬實現

10.1 strstr的使用

函數原型:

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

注意:

  • 函數返回字符串str2在字符串str1中第⼀次出現的位置
  • 字符 串的⽐較匹配不包含 \0 字符,以 \0 作為結束標誌

代碼如下:

int main()
{
	char arr1[] = "this is an apple\n";
	char arr2[] = "is"; //如果沒有找到,默認的返回值是空指針,NULL
	char* ret = strstr(arr1, arr2); //從遇到的第一個is開始
	if (ret != NULL)
	{
		printf("%s\n", ret);
	}
	else
	{
		printf("沒有找到\n");
	}
	return 0;
 }

輸出結果:

c語言—字符函數和字符串函數進階篇—筆記_bc_08

如果我們尋找arr1之外的數,那麼機會找不到

這裏我們輸入AS,在arr1裏面找這個AS,結果我們發現,沒有找到

代碼如下:

int main()
{
	char arr1[] = "this is an apple\n";
	char arr2[] = "AS"; //如果沒有找到,默認的返回值是空指針,NULL
	char* ret = strstr(arr1, arr2); //從遇到的第一個is開始
	if (ret != NULL)
	{
		printf("%s\n", ret);
	}
	else
	{
		printf("沒有找到\n");
	}
	return 0;
 }

輸出結果:

c語言—字符函數和字符串函數進階篇—筆記_字符串_09

10.2 strstr模擬實現

char* my_strstr(const char* str1, const char* str2)
{
	const char* s1 = NULL;
	const char* s2 = NULL;
	const char* cur = str1;
	if (*str2 == '\0')
	{
		return (char*)str1;
	}
	while (*cur)
	{
		s1 = cur;
		s2 = str2;
		while (*s1 != '\0' && *s2 != '\0' && *s1 == *s2)
		{
			s1++;
			s2++;
		}
		if (*s2 == '\0')
		{
			return (char*)cur;
		}
		cur++;
	}
	return NULL;
}
int main()
{
	char arr1[] = "abcdefabcdef";
	char arr2[] = "cdef";
	char* ret = my_strstr(arr1, arr2);
	if (ret != NULL)
	{
		printf("%s\n", ret);
	}
	else
	{
		printf("找不到\n");
	}
	return 0;
}

輸出結果:

c語言—字符函數和字符串函數進階篇—筆記_bc_10

解析這個代碼:

1.主程序入口

  • arr1 初始化為 "abcdefabcdef"(末尾隱含 '\0')。
  • arr2 初始化為 "cdef"
  • 調用 my_strstr(arr1, arr2),在 arr1 中查找 arr2 第一次出現的位置。

2.my_strstr 函數

第一次調用時:

  • str1 → "abcdefabcdef"
  • str2 → "cdef"
  • *str2 == 'c',所以不進入第一個 if。
  • cur 初始指向 str1 的第一個字符 'a'

外層循環第一次迭代:

cur → 'a'(地址 &arr1[0])
s1 = cur → 指向 'a's2 = str2 → 指向 'c'

內層 while 條件:
*s1 = 'a'*s2 = 'c''a' == 'c' 為假,不進入內層循環。
檢查 *s2 == '\0'?否,cur++ 指向 'b'

外層循環第二次迭代:

cur → 'b's1 = cur → 'b's2 = str2 → 'c''b' == 'c' 為假,內層不執行。
cur++ 指向 'c'

外層循環第三次迭代:

cur → 'c'(&arr1[2])
s1 = cur → 'c's2 = str2 → 'c'*s1 == *s2 為真,進入內層循環:

  • 內層第一次:
    s1++ → 'd's2++ → 'd',相等,繼續。
  • 內層第二次:
    s1++ → 'e's2++ → 'e',相等,繼續。
  • 內層第三次:
    s1++ → 'f's2++ → 'f',相等,繼續。
  • 內層第四次:
    s2++ 後指向 '\0'*s2 == '\0',內層循環條件 *s2 != '\0' 為假,退出內層循環

檢查 *s2 == '\0':是,説明 str2 全部匹配成功。
返回 (char*)cur,即 arr1 中 "cdefabcdef" 的起始地址。

3. 回到主函數

ret 指向 arr1 中 "cdefabcdef" 的位置。
ret != NULL 為真,執行 printf("%s\n", ret),輸出:

cdefabcdef

11. strtok函數的使⽤

函數原型:

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

注意:

  •  sep參數指向⼀個字符串,定義了⽤作分隔符的字符集合
  •  第⼀個參數指定⼀個字符串,它包含了0個或者多個由sep字符串中⼀個或者多個分隔符分割的標 記。
  • •strtok函數找到str中的下⼀個標記,並將其⽤ \0 結尾,返回⼀個指向這個標記的指針。(注: strtok函數會改變被操作的字符串,所以被strtok函數切分的字符串⼀般都是臨時拷⻉的內容並且 可修改。)
  •  strtok函數的第⼀個參數不為 中的位置。 NULL ,函數將找到str中第⼀個標記,strtok函數將保存它在字符串
  •  strtok函數的第⼀個參數為 NULL ,函數將在同⼀個字符串中被保存的位置開始,查找下⼀個標 記。
  • 如果字符串中不存在更多的標記,則返回 NULL 指針。
int main()
{
	char arr1[] = "zixiaolong@yeah.net";
	char arr2[100] = { 0 };
	strcpy(arr2, arr1);//拷貝一個臨時的數據
	const char* sep = ".@"; //分割符
	char* ret = NULL;
	for (ret = strtok(arr2, sep); ret != NULL; ret = strtok(NULL, sep))
	{
		printf("%s\n", ret);
	}
	return 0;
}

輸出結果:

c語言—字符函數和字符串函數進階篇—筆記_錯誤碼_11

12. strerror 函數的使⽤

函數原型:

char* strerror ( int errnum )

strerror 函數可以把參數部分錯誤碼對應的錯誤信息的字符串地址返回來。

在不同的系統和C語⾔標準庫的實現中都規定了⼀些錯誤碼,⼀般是放在 errno.h

代碼如下:

int main()
{
	int i = 0;
	for (i = 0; i <= 10; i++)
	{
		printf("%d:   %s\n", i, strerror(i));
	}
	return 0;
}

輸出結果:

c語言—字符函數和字符串函數進階篇—筆記_字符串_12

以上就是我們字符串函數和字符函數的全部內容了