字符串
- 將字符串到一起就是字符串,有序 / 同類型的 ---> 數(shù)組
- 其實(shí)C語言中的字符串就是一個(gè)特殊的數(shù)組而已
- 如果用數(shù)組表示字符串,那么數(shù)組必須是char類型,而且最后一個(gè)元素必須是\0
- 在c語言中除了可以用字符數(shù)組來表示字符串以外,還可以用雙引號(hào)" " 來表示字符串
以下就是一個(gè)字符串
char str1[] = {'c','w','w','\0'};
// 如果在定義的同時(shí)部分初始化,沒有被賦值的元素會(huì)被自動(dòng)賦值為0;
char str2[5] = {'c','w','w'};
char str3[] = "cww"; // 底層就是 {'c','w','w','\0'};
以下是一個(gè)字符數(shù)組,不是字符串
char str4[] = {'c','w','w'};
printf("str1 = %s\n",str1); // cww
printf("str2 = %s\n",str2); // cww
printf("str3 = %s\n",str3); // cww
printf("str4 = %s\n",str4); // cwwcww
image
- 特別注意:字符串在內(nèi)存中存儲(chǔ)是連續(xù)的,只有遇到\0接結(jié)束
image
字符串常用方法
puts
- 格式: puts(字符數(shù)組名)
- 功能: 把字符數(shù)組中的字符串顯示到控制臺(tái)
- 優(yōu)點(diǎn): 可以換行,可以是任意元素地址
```
char str1[] = "cww";
// printf + %s 輸出不會(huì)自動(dòng)換行,必須手動(dòng)添加\n
printf("str = %s\n",str);
puts(str); // 會(huì)自動(dòng)換行
printf("被換行");
```

gets
- 格式:gets(字符數(shù)組名);
- 功能:從鍵盤中輸入一個(gè)字符串
```
char str2[10];
// scanf接收用戶輸入,
// scanf輸入的數(shù)據(jù)中不能有空格/TAB/回車
scanf("%s", &str2);
//gets接收字符串,可以輸入空格/TAB
// gets(str2);
printf("str2 = %s\n", str2);
```
strlen
- 功能:計(jì)算字符串的長(zhǎng)度
- 利用sizeof計(jì)算字符串長(zhǎng)度
```
char str1[] = "cww";
int len = sizeof(str1) / sizeof(str1[0]);
// 注意這里計(jì)算是字符串占用內(nèi)存單元的字節(jié)數(shù)
// 實(shí)際是len = len -1;
```
- 利用系統(tǒng)函數(shù)strlen計(jì)算
- 注意: **在使用strlen要引入頭文件 #include <string.h>;**
```
char str2[] = "cww";
strlen(str2);
```
- 自定義strlen函數(shù)
```
/**
* @brief getStrlen 實(shí)現(xiàn)strlen函數(shù)
* @param str 傳入字符串
* @return len 長(zhǎng)度
*/
int getStrlen (char str[]){
int len = 0;
while(str[len] != '\0'){
len++;
}
return len;
}
```
- 指針版
```
/**
* @brief getStrlen 實(shí)現(xiàn)strlen函數(shù)
* @param str 傳入字符串
* @return len 長(zhǎng)度
*/
int myStrlen(char *str){
int index = 0;
while(*str++){
index++;
}
return index;
}
```
- 注意點(diǎn): *str++ 是先將地址加1在訪問地址所存儲(chǔ)的內(nèi)容;
```
/**
* @brief getStrlen 實(shí)現(xiàn)strlen函數(shù)
* @param str 傳入字符串
* @return len 長(zhǎng)度
*/
int myStrlen(char *str){
char *startP = str;
while(*str++);
str--;
return str - startP;
}
```
strcat
- 注意: 在使用strlen要引入頭文件 #include <string.h>;
- 格式:strcat(字符數(shù)組名1,字符數(shù)組名2);
- 功能:把字符數(shù)組2中的字符串連接到字符數(shù)組1中字符串的后面,
- 注意點(diǎn):前面的數(shù)組必修足夠長(zhǎng),否則在企業(yè)中會(huì)引發(fā)一些未知的BUG
```
char str1[10] = "cww";
char str2[4] = "ppp";
strcat(str1, str2);
printf("str1 = %s\n",str1); // cwwppp
```
- 自己封裝的strcat函數(shù)
```
/**
* @brief myStrcat 實(shí)現(xiàn)字符串的拼接
* @param str1 傳入字符串1
* @param str2 傳入字符串2
*/
void myStrcat(char *str1, char *str2){
//printf("%s\n",str1);
int index = 0;
// 取出str1中存儲(chǔ)的地址
//printf("str1 = %p\n",str1);
//printf("str1 = %c\n",*str1);
while(*str1++) {
index++;
}
//printf("str1 = %p\n",str1);
// while (str1[index] != '\0') {
// index++;
// }
printf("index = %i\n", index);
int value = 0;
while(str2[value] != '\0'){
str1[index] = str2[value];
index++;
value++;
}
// printf("index = %i\n", index);
str1[index] = '\0';
}
```
- 指針版
```
/**
* @brief myStrcat 指針優(yōu)化的strcat函數(shù)
* @param str1 傳入字符串1
* @param str2 傳入字符串2
*/
void myStrcat(char *str1, char *str2){
while(*str1++);
str1--;
while(*str2){
*str1 = *str2;
str1++;
str2++;
}
*str1 = '\0';
}
```
strcpy
- 注意: 在使用strlen要引入頭文件 #include <string.h>;
- 格式: strcpy(字符數(shù)組1,字符數(shù)組名2);
- 功能: 把字符數(shù)組2中的字符串拷貝到字符數(shù)組1中.字符串結(jié)束標(biāo)志'\0'也一同拷貝.
- 注意點(diǎn):前面的數(shù)組必修足夠長(zhǎng),否則在企業(yè)中會(huì)引發(fā)一些未知的BUG
```
char str1[10] = "cww";
char str2[4] = "ppp";
strcpy(str1,str2);
printf("str1 = %s\n",str1); // ppp
printf("str2 = %s\n",str2); // ppp
```
- 自定義strcpy函數(shù)
```
#include <stdio.h>
#include <string.h>
void myStrcpy(char *str1, char *str2);
int main()
{
char str1[] = "cwww";
char str2[] = "ppppp";
//strcpy(str1, str2);
myStrcpy(str1, str2);
printf("str1 = %s\n", str1);
return 0;
}
/**
* @brief myStrcpy 實(shí)現(xiàn)strcpy函數(shù)
* @param str1 傳入字符串1
* @param str2 傳入字符串2
*/
void myStrcpy(char *str1, char *str2){
int index = 0;
while (str2[index] != '\0') {
str1[index] = str2[index];
index++;
}
str1[index] = '\0';
}
```
- 指標(biāo)版
```
/**
* @brief myStrcpy 指針實(shí)現(xiàn)strcpy函數(shù)
* @param str1 傳入字符串1
* @param str2 傳入字符串2
*/
void myStrcpy(char *str1, char *str2){
while(*str2){
*str1 = *str2;
str1++;
str2++;
}
*str1 = '\0';
}
```
strcmp
- 注意: 在使用strlen要引入頭文件 #include <string.h>;
- 格式: strcmp(字符數(shù)組名1,字符數(shù)組名2)
- 功能: 按照ASCII碼順序比較兩個(gè)數(shù)組中的字符串,并右函數(shù)返回值返回比較結(jié)果
- 字符串1 = 字符串2, 返回值 = 0;
- 字符串1 > 字符串2, 返回值 > 0;
- 字符串1 < 字符串2, 返回值 < 0;
- 如果前面的內(nèi)容都相同, 第一個(gè)參數(shù)的個(gè)數(shù)小于第二個(gè)參數(shù), 返回 -1 負(fù)數(shù)
- 如果前面的內(nèi)容都相同, 第一個(gè)參數(shù)的個(gè)數(shù)大于第二個(gè)參數(shù), 返回 1 正數(shù)
```
char str1[10] = "124";
char str2[4] = "123";
int res = strcmp(str1,str2);
printf("res = %i\n", res); // 1
```
- 自定義strcmp
```
#include <stdio.h>
#include <string.h>
int myStrcmp(char *str1, char *str2);
int main()
{
char str1[] = "1224";
char str2[] = "12233";
int res1 = strcmp(str1, str2);
printf("res1 = %i\n", res1);
int res2 = myStrcmp(str1, str2);
printf("res2 = %i\n", res2);
return 0;
}
/**
* @brief myStrcmp 實(shí)現(xiàn)strcmp函數(shù)
* @param str1 傳入第一個(gè)字符串
* @param str2 傳入第二個(gè)字符串
* @return
*/
int myStrcmp(char *str1, char *str2){
int index = 0;
while (str1[index] != '\0' || str2[index] != '\0') {
if(str1[index] > str2[index]){
return 1;
}else if(str1[index] < str2[index]){
return -1;
}
index++;
}
return 0;
}
```
- 指針版
```
/**
* @brief myStrcmp 指針實(shí)現(xiàn)strcmp函數(shù)
* @param str1 傳入第一個(gè)字符串
* @param str2 傳入第二個(gè)字符串
* @return
*/
int myStrcmp(char *str1, char *str2){
while (*str1 || *str2) {
if(*str1 > *str2){
return 1;
}else if(*str1 < *str2){
return -1;
}
str1++;
str2++;
}
return 0;
}
```
字符串?dāng)?shù)組
- 字符串?dāng)?shù)組其實(shí)就是定義一個(gè)數(shù)組保存所有的字符串
char names1[2][6] = {{'c','w','w','\0'},{'p','p','p'}};
char names2[2][6] = {{"cww"},{"ppp"}};
char names3[2][6] = {"cww","ppp"};
- 指針定義字符串
char *str1 = "cww";
char *str2 = "abc";
char *str3 = "def";
char *str{
str1,
str2,
str3
};
// 字符串?dāng)?shù)組的第二種格式
char *str[] = {
"cww",
"abc",
"def"
};