C語言筆記
內容提要
數組
字符串基本操作
字符串相關函數
綜合案例:學生成績管理系統
數組
字符串基本操作
在用格式化說明符%s進行輸入輸出時,其輸入輸出項均為數組名。但在輸入時,相鄰兩個
字符串之間要用空格分隔,系統將自動在字符串后加\0
。在輸出時,遇到結束符\0
作
為輸出結束標志。
對于字符串的操作,我們需要使用到一些系統提供的API函數。
字符串輸入
scanf
語法:
scanf("%s",數組名)
注意:采用scanf進行字符串輸入,要求字符串中不能有空格,否則字符串遇到空格就結束
案例:
#include <stdio.h>int main(int argc,char *argv[]){// 創建一個char數組,用來存儲姓名char name[20];printf("請輸入您的名字:\n");scanf("%s", name); // 用字符數組接收一個控制臺輸入的字符串常量printf("您的姓名是%s\n", name);return 0;}
注意:采用scanf進行字符串輸入,要求字符串中不能有空格,否則字符串遇到空格就會結束
fgest
語法:
fgets(數組名,數組容量,stdin);
功能:
從鍵盤錄入一個字符串常量到字符數組,返回字符數組的地址(首地址,默認返回的
地址,一般用12位16進制數表示)
說明:
采用fgets進行字符串輸入,可獲取所有輸入的字符串,包含\n,在實際的字符串處理
時,我們可能需要手動處理\n
案例:
#include <stdio.h>int main(int argc,char *argv[]){// 創建一個字符數組,用來存儲姓名char name[20]; // 只是創建數組,必須指定容量;如果初始化,可以省略容量。// 計算數組容量int len = sizeof(name) / sizeof(name[0]);printf("請輸入您的姓名:\n");fgets(name, len, stdin);printf("您的姓名是%s\n", name);return 0;}
注意:
①如果輸入的字符串不包括空格和換行,可以用scanf。
②如果輸入的字符串包括空格和換行,可以用fgest。
gets 危險的【C11移出】
語法:
gets(數組名);
功能:
從鍵盤錄入一個字符串常量到字符數組,返回字符數組的地址(首地址,默認返回的
地址,一般用12位16進制數表示)
說明:
采用gets進行字符串輸入,可獲取所有輸入的字符串,包含 \n
,在實際的字符串處
理時,我們可能需要處理 \n
。
案例:
#include <stdio.h>int main(int argc,char *argv[]){// 創建一個字符數組,用來存儲姓名char name[20]; // 只是創建數組,必須指定容量;如果初始化,可以省略容量。// 計算數組容量int len = sizeof(name) / sizeof(name[0]);printf("請輸入您的姓名:\n");gets(name);printf("您的姓名是%s\n", name);return 0;}
字符串輸出
printf
語法:
printf("%s",數組名);
案例:
#include <stdio.h>int main(int argc,char *argv[]){// 創建一個字符數組,用來存儲姓名char name[20]; // 只是創建數組,必須指定容量;如果初始化,可以省略容量。// 計算數組容量int len = sizeof(name) / sizeof(name[0]);printf("請輸入您的姓名:\n");fgets(name, len, stdin);printf("您的姓名是%s\n", name);.// %s支持字符串常量,也支持字符數組,都是以字符串形式輸出return 0;}
fputs
語法:
fputs(數組名,stdout);
功能:輸出一個字符串
說明:字符串可以包括轉義字符(\
開頭的字符)
案例:
#include <stdio.h>int main(int argc,char *argv[]){char arr[] = "hi yifanjiao\neat!\n";// 第1種輸出printf("%s", arr);// 第2種輸出fputs(arr, stdout);return 0;}
puts 危險的【C11移出】
語法:
puts(數組名稱);
功能:輸出一個字符串
說明:字符串可以包含轉義字符
案例:
#include <stdio.h>int main(int argc,char *argv[]){char arr[] = "hi yifanjiao\neat!\n";// 第1種輸出printf("%s", arr);// 第2種輸出puts(arr);return 0;}
字符串相關函數
字符串拼接
語法:
strcat(字符數組,需要拼接的字符串或者字符數組或者字符指針);
解釋:
①這里的字符串,可以是字符串常量,也可以是字符數組或者字符指針,參數1必須是字符數組。
②這里需要將字符串2拼接到字符串1,所以需要字符串1有足夠大的空間去容納字符串2。
引入:
#include <string.h>
案例:
需求:將兩個字符串拼接為一個字符串
分析:
代碼:
#include <stdio.h>// 使用字符串相關函數需要引入必要的頭文件#include <string.h>int main(int argc,char *argv[]){// 創建一個字符數組,用來接收控制臺輸入char name[20];printf("請輸入您的名字:\n");// 通過控制臺輸入字符串(支持空格)fgets(name, sizeof(name) / sizeof(name[0]), stdin);// 輸出拼接 strcat返回拼接后的字符串fputs(strcat(name, "你好!"), stdout);printf("\n");// char str[50];// fputs(strcat(str, strcat(name, "你好!")), stdout);return 0;}
注意:
① 參數1
必須是字符數組,長度必須足夠大,以便于能夠容納被鏈接的字符串。
② 連接后系統將自動取消參數1
后面的結束符 \0
③ 參數2
可以是字符數組名,也可以是指針,也可以是字符串常量,如:strcat(s1,"def"); strcat(s1,s2);
字符串拷貝
語法:
strcpy(數組名,字符串);
解釋:簡單來說,類似于將一個字符串賦值給一個字符數組。這個函數一般用來做賦值處理。
引入:
#include <string.h>
說明:這個函數適合給字符串賦值
char str[20] = "**培"; // 正確,字符數組的初始化,字符串初始化char str[20] = "**培"; str = "*佳"; // 錯誤,不能對數組進行賦值char str[20] = "**凡"; strcpy(str, "**林");// 正確,利用函數實現類似賦值的操作
注意: strcat和strcpy的區別:
strcat: 凡 + 鴻 → 凡鴻 (追加)
strcpy: 凡 + 鴻 → **鴻 (覆蓋)
案例:
#include <stdio.h>#include <string.h>int main(int argc,char *argv[]){// 需求:對數組賦值char name[50] = "hello";printf("打印初始化后的數組:%s\n", name);// 對一個數組賦:// name = "**鴻"; // 數組一旦創建,就無法改變,所以不能對數組進行賦值// 通過 strcpy(字符數組,字符數組/字符常量/字符指針)實現給數組賦值strcpy(name, "my");// my | mylloprintf("打印重新賦值后的數組:%s\n", name);return 0;}
字符串比較
語法:
strcmp(字符串1,字符串2);
注意:這里的字符可以是字符串常量、字符數組、字符指針。
引入:
#include <string.h>
功能:如果是英文,比較兩個字符串對應位置字符ASCII的大小
返回值:
如果字符串1 等于 字符串2,返回0
如果字符串1 大于 字符串2,返回正數(>0)
如果字符串1 小于 字符串2,返回負數(<0)
說明:
① 執行這個函數時,自左向右逐個比較對應字符的ASCII的值,直到發現了不同字符或字
符串結束符\0為止
② 對字符串不能用數值型比較符。比如:"abc" == "abc"
,這種比較是錯誤的。
③ 字符串1與字符串2可以是字符數組、字符指針、字符串常量。
案例:
需求:通過控制臺輸入用戶名和密碼,并進行校驗
代碼:
#include <stdio.h>#include <string.h>int main(int argc,char *argv[]){// 用戶登陸案例// 創建兩個變量,用來存儲用戶名和密碼char username[20], password[8];printf("---------用戶登錄--------\n");printf("請輸入您的用戶名:\n");scanf("%s",username);// 數組名本身就是一個地址(首元素的首地址)printf("請輸入您的密碼:\n");scanf("%s",password);// 校驗if (!strcmp(username,"admin") && !strcmp(password,"123456"))// 相等:strcmp(..) == 0printf("登錄成功!\n");elseprintf("用戶名或者密碼錯誤!\n");return 0;}
字符串長度
語法:
strlen(字符串);
引用:
#include <string.h>
注意:返回字符串中包括的字符的實際個數。遇到\0結束,不包括\0,如果數組中不存在\0就以數組的實際長度作為字符串長度
案例:
需求:字符串長度案例
代碼:
#include <stdio.h>#include <string.h>int main(int argc,char *argv[]){// 測試數據1char s1[] = {'h','i','\0','h','i','\0'};printf("數組長度:%lu\n字符串長度:%lu\n",sizeof(s1)/sizeof(s1[0]), strlen(s1));// 數組長度:6,字符串長度:2// 測試數據2char s2[] = "hi\0hi\0";// 使用雙引號包裹的內容稱之為 字符串常量,字符串常量默認會有一個結尾的\0printf("數組長度:%lu\n字符串長度:%lu\n",sizeof(s2)/sizeof(s2[0]), strlen(s2));// 數組長度:7,字符串長度:2// 測試數據3char s3[] = {'h','e','l','l','o'};// strlen()判斷一個字符串的長度,優先判斷是否存在\0,如果不存在,就返回數組實際長度,因編譯器原因,處理機制也有所不同。printf("數組長度:%lu\n字符串長度:%lu\n",sizeof(s3)/sizeof(s3[0]), strlen(s3));// 數組長度:5,字符串長度: 5,這種寫法不安全,不同編譯器編譯結果不同// 測試數據4char s4[] = "hello";printf("數組長度:%lu\n字符串長度:%lu\n",sizeof(s4)/sizeof(s4[0]), strlen(s4));// 數組長度:6,字符串長度:5return 0;}
案例
需求:輸入一行字符,統計其中有多少個單詞,單詞之間使用空格隔開。舉例:ILOVE YOU
分析:采用通過空格統計單詞的方法。具體是:
① 用連續若干個空格算一個、一行開頭的空格不計的方法決定單詞數目;
② 從第一個字符開始逐個檢查字符串中的每一個字符。若查到某一字符非空格,而其前面的字符是空格,則表示新單詞開始,讓計數變量num++。否則,當前字符非空格,前面字符也非空格,則非新單詞,num不變;
③ 用變量word=0或1來表示前面字符是空格或不是空格。則:
代碼:
#include <stdio.h>#include <ctype.h>int main(int argc,char *argv[]){// 創建一個數組,用來接收控制臺錄入的字符串char string[100];// 創建2個變量,word:統計字符是否是空字符(空字符:0,非空字符:1),num:用來統計單詞個數int num = 0, word = 0;// 創建一個變量,用來存儲遍歷到的字符char c;// 通過控制臺錄入字符串printf("請輸入一句話:\n");fgets(string, sizeof(string)/sizeof(string[0]), stdin);// 遍歷for (int i = 0; (c = string[i])!='\0'; i++){if (isspace(c)) // 判斷一個字符是否是空格,等價于 if (c == ''){// 如果是空格,標記word = 0;}else{// 如果上一個字符是空格,就需要統計單詞if (!word) // 等價于 word == 0{// 標記word為非空格word = 1;// 統計單詞個數num ++;}}}printf("%s\n中有%d個單詞!\n", string, num);return 0;}
案例
有三個字符串,要求找出其中最大者。
分析:設計一個二維字符數組str3,即3行20列。
① 可把str[0]、str[1]、str[2]看作3個一維字符數組,各有20個元素;
② 用gets函數分別輸入3個字符串到str[0]、str[1]、str[2]中 ;
③ 用字符串函數對str[0]、str[1]、str[2]進行比較,得到最大者。
#include <stdio.h>#include <string.h>int main(int argc,char *argv[]){// 創建一個數組,用來存儲最大的字符串char max[50];// 創建一個數組,用來存儲3個用來參與比較的字符串char str[3][50]/* = {"apple","orange","egg"}*/;int i;// 通過循環控制臺輸入printf("請輸入3個測試字符串:\n");for (i = 0; i < 3; i++){fgets(str[i],50,stdin);}// 比較if (strcmp(str[0],str[1]) > 0) strcpy(max, str[0]);else strcpy(max,str[1]);if (strcmp(str[2],max) > 0) strcpy(max,str[2]);printf("\n三個字符串中最大的字符串是%s\n!", max);return 0;}