目錄
一、strlen的使用和模擬實(shí)現(xiàn)
1.strlen()函數(shù)的介紹
2.strlen()函數(shù)的具體使用
3.strlen函數(shù)的注意事項(xiàng)
4.strlen函數(shù)的模擬實(shí)現(xiàn)
二、strcpy的使用和模擬實(shí)現(xiàn)
1.strcpy()函數(shù)的介紹
2.strcpy()函數(shù)的具體使用
3.strcpy()函數(shù)的注意事項(xiàng)
4.strcpy函數(shù)的模擬實(shí)現(xiàn)
三、strcat 的使用和模擬實(shí)現(xiàn)?
1.strcat()函數(shù)的介紹
2.strcat函數(shù)的具體使用
3.strcat函數(shù)的注意事項(xiàng)
4.strcat函數(shù)的模擬實(shí)現(xiàn)
四、strcmp的使用和模擬實(shí)現(xiàn)
1.strcmp()函數(shù)的介紹
2.strcmp()函數(shù)的具體使用
3.strcmp函數(shù)的注意事項(xiàng)
4.strcmp函數(shù)的模擬實(shí)現(xiàn)
一、strlen的使用和模擬實(shí)現(xiàn)
1.strlen()函數(shù)的介紹
strlen:計(jì)算的是字符串str的長度,從字符的首地址開始遍歷,以 '\0' 為結(jié)束標(biāo)志,然后將計(jì)算的長度返回,計(jì)算的長度并不包含'\0'。下面是庫中的strlen()函數(shù):
size_t? strlen (const char* str);
- 函數(shù)的參數(shù)為------const char* str:字符指針
- 返回值的類型------size_t:無符號(hào)整數(shù)(即:unsigned int)
前提知識(shí):
- const關(guān)鍵字:是用來定義常量的,若一個(gè)變量被const關(guān)鍵字修飾時(shí),那么這個(gè)變量的值就不可以被改變。故:這里的 * str 的值是不能被修改的。
- size_t數(shù)據(jù)類型:表示C中任何對(duì)象所能達(dá)到的最大長度,它是無符號(hào)整數(shù)。
1.使用const關(guān)鍵字:這里只是計(jì)算字符串的長度,用const修飾,避免將原字符串修改掉。
2.使用size_t數(shù)據(jù)類型:這里返回計(jì)算的字符串長度,長度最小值為0,不可能為負(fù)數(shù)。
2.strlen()函數(shù)的具體使用
場景一:
#include <stdio.h>
#include <string.h>
int main()
{
char arr[10] = "abcde";
int num = strlen(arr);
printf("數(shù)組arr的長度為:%d\n", num);
return 0;
}
輸出的結(jié)果:
?場景二:
#include <stdio.h>
#include <string.h>
int main()
{
char arr[] = { 'a','b','c','d','e' };
int num = strlen(arr);
printf("數(shù)組arr的長度:%d\n", num);
return 0;
}
輸出的結(jié)果:
上述兩種場景輸出的結(jié)果并不相同
為什么會(huì)出現(xiàn)這樣的結(jié)果,我們?cè)谟胹trlen函數(shù)時(shí)應(yīng)該注意什么?
3.strlen函數(shù)的注意事項(xiàng)
strlen函數(shù):當(dāng)計(jì)算長度時(shí),只有遇到'\0'才會(huì)停止計(jì)算,同時(shí)計(jì)算的長度不包含'\0'。
? ? 場景一,arr字符數(shù)組中存儲(chǔ)的是一個(gè)字符串(字符串是以'\0'為結(jié)束標(biāo)志的),那么strlen遍歷到字符 'e' 時(shí),再向后遍歷,就會(huì)遇到'\0',此時(shí)strlen停止遍歷,返回字符個(gè)數(shù):5;
? ? 場景二:字符'a'、'b'、 'c' 、'd' 、'e'五個(gè)字符依次存儲(chǔ)在arr的字符數(shù)組中,并沒有存儲(chǔ)'\0',所以'e'字符后面存儲(chǔ)的內(nèi)容我們并不知道有什么。而strlen函數(shù)只有遇到'\0'時(shí)才停止,所以返回的個(gè)數(shù)是一個(gè)隨機(jī)值。
故:我們使用strlen函數(shù)時(shí),應(yīng)該檢查字符數(shù)組是否以'\0'為結(jié)束標(biāo)志。
4.strlen函數(shù)的模擬實(shí)現(xiàn)
方式一:
//計(jì)數(shù)器?式
int my_strlen(const char* str)
{
int count = 0;
assert(str);
while (*str)
{
count++;
str++;
}
return count;
}
?方式二:
//不能創(chuàng)建臨時(shí)變量計(jì)數(shù)器,遞歸的方式
int my_strlen(const char* str)
{
assert(str);
if (*str == '\0')
return 0;
else
return 1 + my_strlen(str + 1);
}
??方式三:
int my_strlen(char* s)
{
assert(str);
char* p = s;
while (*p != ‘\0’)
p++;
return p - s;
}
補(bǔ)充知識(shí):assert(斷言):是一個(gè)宏。
assert 的作用是,將括號(hào)中的表達(dá)式計(jì)算出 ,如果其值為假(即為0),那么它會(huì)打印出一條出錯(cuò)信息,然后終止程序的運(yùn)行。這里的assert是防止指針p指向?yàn)镹ULL。
二、strcpy的使用和模擬實(shí)現(xiàn)
1.strcpy()函數(shù)的介紹
strcpy()函數(shù):是將一個(gè)字符串復(fù)制到另一塊空間地址中 的函數(shù),‘\0’是停止拷貝的終止條件,同時(shí)也會(huì)將 '\0' 也復(fù)制到目標(biāo)空間。下面是庫中的strcpy()函數(shù)聲明:
char* strcpy(char* destination,const char* source);
函數(shù)的參數(shù):
char* destination---------目標(biāo)字符串的首地址
const char* source------源地址:被復(fù)制的字符串的首地址,用const修飾,避免修改掉被拷貝的字符串
函數(shù)的返回值類型:
char*:返回的是目標(biāo)字符串的首地址?
2.strcpy()函數(shù)的具體使用
場景一:
#include <stdio.h>
#include <string.h>
int main()
{
char arr[10] = "########";
printf("%s\n", strcpy(arr, "hello"));
return 0;
}
輸出的結(jié)果:?
場景二:?
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
int main()
{
char arr1[10] = "**********";
char arr2[10] = "abcd";
printf("%s\n", strcpy(arr1, arr2));
return 0;
}
輸出結(jié)果:
3.strcpy()函數(shù)的注意事項(xiàng)
1.源字符必須以 '\0'結(jié)束:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
int main()
{
char arr1[10] = "**********";
char arr2[] = { 'a','b','c','d' };
printf("%s\n", strcpy(arr1,arr2));
return 0;
}
這里的代碼會(huì)出錯(cuò),'\0'是停止拷貝的終止條件,arr2字符數(shù)組所在的內(nèi)存空間后面存儲(chǔ)的內(nèi)容并不知道,不遇到 '\0' 拷貝就不會(huì)停止,這就會(huì)導(dǎo)致越界訪問,程序就會(huì)出現(xiàn)問題。?
2.目標(biāo)空間必須足夠大,以確保能放源字符串
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
int main()
{
char arr1[5] = "*****";
char arr2[] = "hello world";
printf("%s\n", strcpy(arr1,arr2));
return 0;
}
這里雖然拷貝成功并將結(jié)果輸出了,但程序卻崩潰了。目標(biāo)空間太小,不足以放置拷貝的源字符串,會(huì)造成溢出的情況?
3.目標(biāo)空間必須可變
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
int main()
{
char* str1 = "hello world";
char str2[10] = "*********";
printf("%s\n", strcpy(str1,str2));
return 0;
}
這里的程序也出現(xiàn)了錯(cuò)誤。str1指向的是常量字符串,是不可以被修改掉的,目標(biāo)空間必須是可以被修改的,因?yàn)橐獙⒖截惖淖址旁谀繕?biāo)空間中。而源字符串可以是能夠修改的,也可以是不能修改的,因?yàn)閟trcpy函數(shù)的第二個(gè)參數(shù)已經(jīng)用const關(guān)鍵字修飾了,保證了拷貝過程中不會(huì)被修改。?
4.strcpy函數(shù)的模擬實(shí)現(xiàn)
char *my_strcpy(char *dest, const char*src)
{
char *ret = dest;
assert(dest != NULL);
assert(src != NULL);
while((*dest++ = *src++))
{
;
}
return ret;
}
三、strcat 的使用和模擬實(shí)現(xiàn)?
1.strcat()函數(shù)的介紹
strcat的函數(shù)原型的聲明為:
char*strcat(char* strDestination, const char* strSource);
其返回值為char*,需要傳入兩個(gè)參數(shù)
strcat函數(shù)可以將一個(gè)字符串追加到另外一個(gè)字符串的后面
2.strcat函數(shù)的具體使用
比如在“hello”后面追加一段“world”就可以用strcat函數(shù)來實(shí)現(xiàn)
#include <stdio.h>
#include <string.h>
int main()
{
char arr1[30] = "hello ";
char arr2[] = "world";
strcat(arr1, arr2);
printf("%s\n", arr1);//追加字符串
return 0;
}
?打印結(jié)果:
3.strcat函數(shù)的注意事項(xiàng)
? 源字符串必須以 '\0' 結(jié)束。
? 目標(biāo)字符串中也得有 \0 ,否則沒辦法知道追加從哪里開始。
? 目標(biāo)空間必須有足夠的大,能容納下源字符串的內(nèi)容。
? 目標(biāo)空間必須可修改。
? 字符串自己給自己追加,如何?
自己給自己追加
char* my_strcat(char* dest, const char* src)
{
char* ret = dest;
assert(dest && src);
//1. 找到目標(biāo)空間的\0
while (*dest)
{
dest++;
}
//2. 拷貝
while (*dest++ = *src++)
{
;
}
return ret;
}
int main()
{
char arr1[20] = "hello ";
my_strcat(arr1, arr1);
printf("%s\n", arr1);
return 0;
}
這樣會(huì)一直追加下去,并且會(huì)造成訪問越界。
4.strcat函數(shù)的模擬實(shí)現(xiàn)
char* my_strcat(char* dest, const char* src)
{
char* ret = dest;
assert(dest != NULL);
assert(src != NULL);
while (*dest)
{
dest++;
}
while ((*dest++ = *src++))
{
;
}
return ret;
}
四、strcmp的使用和模擬實(shí)現(xiàn)
1.strcmp()函數(shù)的介紹
strcmp函數(shù)是C語言中的字符串比較函數(shù),用于比較兩個(gè)字符串的大小。
函數(shù)原型:
int strcmp ( const char * str1, const char * str2 );
- 該函數(shù)接受兩個(gè)參數(shù),分別為要比較的兩個(gè)字符串的指針。
- 返回值為整形,表示兩個(gè)字符串的大小關(guān)系。
? 標(biāo)準(zhǔn)規(guī)定:
? ? ?? 第?個(gè)字符串大于第?個(gè)字符串,則返回大于0的數(shù)字
? ? ?? 第?個(gè)字符串等于第?個(gè)字符串,則返回0
? ? ?? 第?個(gè)字符串小于第?個(gè)字符串,則返回小于0的數(shù)字
? ? ?? 那么如何判斷兩個(gè)字符串? 比較兩個(gè)字符串中對(duì)應(yīng)位置上字符ASCII碼值的大小。
2.strcmp()函數(shù)的具體使用
strcmp函數(shù)的比較規(guī)則是按照字典序進(jìn)行比較,即逐個(gè)字符比較。具體的比較過程如下:
- 若兩個(gè)字符相等,則繼續(xù)比較下一個(gè)字符。
- 若兩個(gè)字符不相等,則返回它們的ASCII碼差值(ASCII碼值大的字符串大)。
#include <stdio.h>
#include <string.h>
int main()
{
char str1[] = "appple";
char str2[] = "banana";
int ret = strcmp(str1, str2);
if (ret == 0)
printf("str1和str2相等\n");
else if (ret > 0)
printf("str1大于str2\n");
else
printf("str1小于str2\n");
return 0;
}
?
3.strcmp函數(shù)的注意事項(xiàng)
1、字符串的比較是按照字典序進(jìn)行的,因此大小寫字母的比較結(jié)果不同。
2、在比較字符串時(shí),需要確保字符串以'\0'結(jié)尾,否則可能會(huì)導(dǎo)致比較結(jié)果不正確。
例如這個(gè)代碼:
#include <stdio.h>
#include <string.h>
int main()
{
char str1[] = "hello";
char str2[] = "hello";
str1[5] = '!';
int ret = strcmp(str1, str2);
if (ret == 0)
printf("str1和str2相等\n");
else if (ret > 0)
printf("str1大于str2\n");
else
printf("str1小于str2\n");
return 0;
}
?結(jié)果如下:
那為什么會(huì)這樣呢?
分析如下文章來源:http://www.zghlxwxcb.cn/news/detail-795126.html
在這段代碼中,我們將str1字符串的結(jié)尾標(biāo)識(shí)符'\0'改成了'!',運(yùn)行代碼后,輸出結(jié)果為"str1大于str2"。這是因?yàn)閟tr1字符串沒有以'\0'結(jié)尾,所以strcmp函數(shù)會(huì)繼續(xù)比較下去,直到遇到str2字符串的結(jié)尾標(biāo)識(shí)符'\0'。由于str1字符串比str2字符串長,所以str1被認(rèn)為是大于str2。文章來源地址http://www.zghlxwxcb.cn/news/detail-795126.html
4.strcmp函數(shù)的模擬實(shí)現(xiàn)
#include <stdio.h>
#include <string.h>
#include <assert.h>
int my_strcmp(const char* str1, const char* str2)
{
assert(str1 && str2);
while (*str1 == *str2)
{
if (*str1 == '\0')
return 0;//相等
str1++;
str2++;
}
if (*str1 > *str2)
return 1;//大于
else
return -1;//小于
}
int main()
{
char str1[] = "appple";
char str2[] = "banana";
int ret = my_strcmp(str1, str2);
if (ret == 0)
printf("str1和str2相等\n");
else if (ret > 0)
printf("str1大于str2\n");
else
printf("str1小于str2\n");
return 0;
}
到了這里,關(guān)于C語言——詳解字符函數(shù)和字符串?dāng)?shù)組(上)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!