字串函式和記憶體操作函式
字串函式和記憶體操作函式
一.字串函式
strlen: 計算給定字串長度
strcpy:字串複製
strcat:字串連線
strcmp:比較字串s1和s2
strstr:判段字串str2是否是str1的字串
strtok:分解字串為一組字串
strerror:獲取系統錯誤資訊
詳解
(1)stelen 函式
strlen所作的是一個計數器的工作,它從記憶體的某個位置(可以是字串開頭,中間某個位置,甚至是某個不確定的記憶體區域)開始掃描,直到碰到第一個字串結束符’\0’為止,然後返回計數器值(長度不包含’\0’)。
應用
int main()
{
char* str = "abcdef" ;
printf("%d\n",strlen(str));
return 0;
}
模擬實現
1.計數器實現
int my_strlen(const char*str)//字串長度是不變的,用const修飾
{
assert(str!=NULL);//assert斷言
int len = 0;
while (*str!='\0')
{
len++;
str++;
}
return len;
}
int main()
{
char* str = "abcdef";
printf("%d\n",my_strlen(str) );
return 0;
}
2.遞迴實現
int my_strlen(const char* str)
{
assert(str != NULL);
if (*str != '\0')
return 1 + my_strlen(str + 1);
else
return 0;
}
int main()
{
char* str = "bite";
int len = my_strlen(str);
printf("%d\n", len);
return 0;
}
3.指標-指標實現
指標-指標的結果是中間元素的個數,定義一個指標存放起始位置,字串指標找到‘\0’後,用字串指標-存放起始位置的指標就是字串長度。
int my_strlen(const char* str)
{
assert(str != NULL);
const char*start = str;//存放起始位置
while (*str != '\0')
{
str++;
}
return str - start;
}
int main()
{
char* str = "abcdef";
printf("%d\n",my_strlen(str));
return 0;
}
(2)strcpy函式
strcpy把含有’\0’結束符的字串複製到另一個地址空間,返回值的型別為char*。
應用
int main()
{
char arr1[20] = "****************";
char arr2[] = "abcdef";
char* ret=strcpy(arr1, arr2);
printf("%s\n", ret);
return 0;
}
模擬實現
char* my_strcpy(char*arr1, const char*arr2)
{
assert(arr1&&arr2);
char*ret = arr1;
while (*arr1++ = *arr2++)
{
;
}
return ret;
}
int main()
{
char arr1[20] = "****************";
char arr2[] = "abcdef";
char* ret=my_strcpy(arr1, arr2);
printf("%s\n", ret);
return 0;
}
(3)strcat函式
把src所指向的字串(包括“\0”)複製到dest所指向的字串後面(刪除dest原來末尾的“\0”)。要保證dest足夠長,以容納被複制進來的*src。*src中原有的字元不變。返回指向dest的指標。
應用
int main()
{
char arr1[20] = "hello ";//目標空間必須足夠大,能容下源字串內容
char arr2[] = "World";
printf("%s",strcat(arr1, arr2));
return 0;
}
模擬實現
char* my_strcat(char*arr1, const char*arr2)
{
assert(arr1&&arr2);
char* ret = arr1;
while (*arr1 )//找到目標空間'\0'的位置
{
arr1++;
}
while (*arr2 !='\0')//將源自符串拷貝到目標空間
{
*arr1++ = *arr2++;
}
return ret;
}
int main()
{
char arr1[20] = "hello ";
char arr2[] = "World";
printf("%s\n", my_strcat(arr1, arr2));
return 0;
}
(4)strcmp函式
strcmp函式是用於比較兩個字串並根據比較結果返回整數。基本形式為strcmp(str1,str2),若str1=str2,則返回零;若str1<str2,則返回負數;若str1>str2,則返回正數
應用
int main()
{
char arr1[] = "abcdef";
char arr2[] = "abc";
int ret = strcmp(arr1, arr2);
printf("%d\n", ret);
return 0;
}
模擬實現
int my_strcmp(char* arr1, char* arr2)
{
assert(arr1&&arr2);
while (*arr1 == *arr2)
{
if (*arr2 == '\0')
return 0;
arr1++;
arr2++;
}
return *arr1 - *arr2;
}
int main()
{
char arr1[] = "abcde";
char arr2[] = "abc";
int ret = my_strcmp(arr1, arr2);
printf("%d\n", ret);
return 0;
}
(5) strstr函式
strstr(str1,str2) 函式用於判斷字串str2是否是str1的子串。如果是,則該函式返回 str1字串從 str2第一次出現的位置開始到 str1結尾的字串;否則,返回NULL。
應用
int main()
{
char arr1[] = "abcde";
char arr2[] = "cd";
char*ret = strstr(arr1, arr2);
printf("%s\n", ret);
return 0;
}
模擬實現
char* my_strstr(const char*arr1, const char*arr2)
{
assert(arr1&&arr2);
const char*pc = arr1;
while (*pc)
{
const char* p1 = pc;
const char* p2 = arr2;
while ((*p1) && (*p2) && (*p1 == *p2))
{
p1++;
p2++;
}
if (*p2 == '\0')
{
return (char*)pc;
}
pc++;
}
return NULL;
}
int main()
{
char arr1[] = "abcded";
char arr2[] = "bc";
char* ret = my_strstr(arr1, arr2);
printf("%s\n", ret);
return 0;
}
(6) strtok函式
分解字串為一組字串。s為要分解的字串,delim為分隔符字元(如果傳入字串,則傳入的字串中每個字元均為分割符)。首次呼叫時,s指向要分解的字串,之後再次呼叫要把s設成NULL。
應用
int main()
{
char *p = "[email protected]";
const char* sep = "@.";
char arr[30];
char*str = NULL;
strcpy(arr, p);//將資料拷貝,處理arr
for (str = strtok(arr, sep); str != NULL; str = strtok(NULL, sep))
{
printf("%s\n", str);
}
return 0;
}
(7) strerror函式
通過標準錯誤的標號,獲得錯誤的描述字串 ,將單純的錯誤標號轉為字串描述,方便使用者查詢錯誤.
應用
#include<stdio.h>
#include<string.h>
#include<errno.h>
int main()
{
FILE * pFile;
pFile = fopen("unexist.ent", "r");
if (pFile == NULL)
printf("Error opening file unexist.ent: %s\n", strerror(errno));
return 0;
}
二.記憶體操作函式
memcpy:拷貝n個位元組(目標區域與源區域不重疊)
memmove:拷貝位元組(目標區域與源區域重疊)
memset:初始化函式
memcmp:比較str1和str2前n個位元組
詳解
(1) memcpy函式
memcpy記憶體拷貝函式,函式原型為void *memcpy(void *destin, void *source, unsigned n);函式的功能是從源記憶體地址的起始位置開始拷貝若干個位元組到目標記憶體地址中,即從源source中拷貝n個位元組到目標destin中
應用
int main()
{
int arr1[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
int arr2[20] = { 0 };
memcpy(arr2, arr1, 16);
return 0;
}
模擬實現
void* my_memcpy(void* dest, const void* str, size_t count)
{
assert(dest&&str);
void* ret = dest;
while (count--)
{
*(char*)dest = *(char*)str;
++(char*)dest;
++(char*)str;
}
return ret;
}
int main()
{
int arr1[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
int arr2[20] = { 0 };
memcpy(arr2, arr1, 16);
return 0;
}
(2) memmove函式
memmove用於拷貝位元組,如果目標區域和源區域有重疊的話,memmove能夠保證源串在被覆蓋之前將重疊區域的位元組拷貝到目標區域中,但複製後源內容會被更改。但是當目標區域與源區域沒有重疊則和memcpy函式功能相同
應用
int main()
{
int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
memmove(arr+2, arr, 16);
return 0;
}
模擬實現
void* my_memmove(void* dest, const void* str, size_t count)
{
assert(dest&&str);
void* ret = dest;
if (dest < str)
{
while (count--)//從前向後交換
{
*(char*)dest = *(char*)str;
++(char*)dest;
++(char*)str;
}
}
else
{
while (count--)//從後向前交換
{
*((char*)dest + count) = *((char*)str + count);
}
}
return ret;
}
int main()
{
int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
memmove(arr+2, arr, 16);
return 0;
}
(3) memset函式
memset是初始化函式。作用是將某一塊記憶體中的內容全部設定為指定的值, 這個函式通常為新申請的記憶體做初始化工作。
(4) memcmp函式
memcmp其功能是把儲存區 str1 和儲存區 str2 的前 n 個位元組進行比較。該函式是按位元組比較的,位於string.h。
如果返回值 < 0,則表示 str1 小於 str2。
如果返回值 > 0,則表示 str2 小於 str1。
如果返回值 = 0,則表示 str1 等於 str2。
應用
int main()
{
char *a = "aBcDeF";
char *b = "AbCdEf";
printf("memcmp(a, b):%d\n", memcmp((void*)a, (void*)b, 6));
return 0;
}