無償分享學習資料,需要的小伙伴評論區或私信dd。。。
無償分享學習資料,需要的小伙伴評論區或私信dd。。。
無償分享學習資料,需要的小伙伴評論區或私信dd。。。
完整資料如下:純干貨、純干貨、純干貨!!!
關注專欄:<后續持續更新>
目錄
數組
一維數組
一維數組的定義:
一維數組的引用:
定義數組的長度與引用數組的下標的區別:
一維數組的初始化:
二維數組
二維數組的定義:
二維數組的引用:
二維數組的初始化:
字符數組
字符數組的定義:
字符數組的初始化:
二維數組的引用:
字符串
字符串常量初始化字符數組
字符串初始化與字符列表初始化的不同:
字符串常量末尾自動加上‘\0’的好處:
字符數組的輸入與輸出
字符串處理函數
數組
分類:一維數組、二維數組 ... n維數組
一維數組
定義:使用數組名加一個下標就能唯一確定數組中的元素的數組就是一維數組。
-
一維數組所占空間:其數據類型 * 長度,例如int a[10]長度為 4(int) ?? 10(長度)=40個字節
一維數組的定義:
格式:
數據類型 數組名[常量表達式]; 例如 int arr[10];
-
數組也屬于變量,只是在內存中占用一片連續的存儲單元,所以都必須先定義后使用,數組名的命名規則也遵循標識符命名規則。
-
定義數組時(即未初始化)必須指定數組的長度。數組的長度只能是整型(包括字符型)的常量或表達式,不能包含變量。
int arr[10],arr2['a'],arr3[10+'a'];//他們都是正確的數組定義 int a=12,arr4[a];//理論上錯誤的數組定義,但目前絕大多數編程軟件已實現。
??注意:c語言明確規定變量不允許做數組長度,即數組不允許動態定義,但是目前絕大多數編程軟件都允許使用變量作數組長度。
-
c語言不允許對變量的長度動態定義,所以不能使用變量定義長度。(如上)
-
數組下標從0開始,即最大下標等于n-1。
int arr[3];//分別為a[0]、a[1]、a[2]
一維數組的引用:
格式:
數組名 [下標]
-
數組的引用是引用數組中的元素,而不能引用整個數組。
printf("%d",arr[0]);//只能是單個引用 printf("%d",arr);//不允許對整個數組進行引用,沒有語法錯誤,但是結果是一個該數組的首地址
-
數組的下標是從0開始的,即a[10]里面的數據為a[0]~a[9],引用時不能超過最大長度。
-
引用時下標可以是整型與字符型的常量、變量、表達式。(即數值)
arr[10]、arr[n]、arr[10+n];//都是正確的引用
-
數組的引用有兩方面作用:
- 單獨賦值。
- 出現在表達式中進行運算。
定義數組的長度與引用數組的下標的區別:
兩者形式上都是一樣的,都是 數組名[表達式],區別在于:
- 首先定義時里面的表達式只能是常量表達式,而引用時還可以是變量表達式。
- 其次兩者含義不同,定義時是為了指定數組的長度,而引用時是為了指定數組中的元素。
int a[10];//數組a包含10個元素。
a[6];//引用數組a中第七個元素。
一維數組的初始化:
定義:在數組定義的同時給各數組元素賦值,這稱為數組的初始化。(使用“初始化列表”的方法實現數組的初始化)
格式:
數據類型 數組名[常量表達式]={初始化列表};
-
對全部數組元素初始化時,可以省略數組的長度。
int arr[3]={1,2,3}; 等價于 int arr[]={1,2,3};
-
只對部分數組元素初始化,其余未初始化元素根據數據類型分別賦0、0.0、'\0'、NULL,注意此時數組長度不能省略。
-
使數組元素全部為0的初始化方法。
int a[3]={0,0,0}; int a[3]={0}; int a[3]={};//這里注意不能省略長度,否則系統無法確定數組長度
-
未初始化的數組與變量相同各元素都是不確定的值,部分初始化其余元素根據數據類型分別賦值0、0.0、'\0'、NULL。
int arr[3];//該數組未初始化,各數組元素為不確定的值 int arr[3]={0};//該數組部分初始化,其余自動賦0,所以全部為0 int arr[3]={}://該數組全部初始化為0,注意這種初始化不能省略數組長度。因為省略長度數組根據初始化列表指定數組大小,此時初始化 //列表為空,形成矛盾,導致數組沒有正確定義。
-
數組的初始化列表個數不能大于數組長度,否則會編譯錯誤。
-
數組初始化列表不能是變量,哪怕是已初始化的變量。【此內容摘自 張玉生-c語言程序設計 課本】
int a=10; int arr[3]={a};//理論上不允許。
??注意:目前絕大多數編譯軟件都允許變量作為數組的初始化列表。
二維數組
定義:使用數組名加兩個下標就能唯一確定數組中的元素(二維數組又稱為矩陣)。
-
二維數組和多維數組的定義、引用、初始化與上面的一維數組要求大體通用。(請學者參考一維數組學習二維數組)
二維數組的定義:
格式:
數據類型 數組名[行(常量表達式)] [列(常量表帶)]; 例如 int arr[2][3];
-
二維數組在內存中是按行存放的,也是按行賦值的。(本質上也是一維數組,在內存中是一片連續的存儲單元)
??注意:用矩陣形式表示二維數組是邏輯上的概念,實際上二維數組在內存中同樣占用一片連續的存儲單元,屬于線性結構。
-
二維數組也必須先定義后使用,數組名遵循標識符命名規則。
-
二維數組(未初始化時)定義時,也必須指定行與列。長度只能是整型(包括字符型)的常量或表達式。
??注意:如果二維數組進行初始化,可以省略行的長度。反之不進行初始化單純定義就必須指定行和列。
二維數組的引用:
格式:數組名 [行下標] [列下標];
-
二維數組的下標都是從0開始的,引用時不能超過最大長度。下標可以是整型與字符型的常量、變量、表達式。(即數值)
-
二維數組的引用可以單獨賦值也可以出現在表達式中進行運算。
二維數組的初始化:
數據類型 變量名 [行] [列]={ {初始化列表1},{初始化列表2}...{初始化列表n} }
-
二維數組是按行存放的,所以也是按行賦初值的。
-
二維數組不管是全部初始化還是部分初始化,可以省略行但是不允許省略列,此時系統會根據第二維的長度推算出第一維的長度。還可以把數據全部放在一對{}中。
int arr[][2]={{1,2},{3,4}};//全部初始化,不允許省略列,可以省略行,此時等價于:int arr[][2]={1,2,3,4} int arr[][2]={{1,2},{3}};//部分初始化,也不允許省略列,可以省略行,此時等價于:int arr[][2]={1,2,3}
部分初始化其余未初始化元素系統自動根據數據類型賦0、0.0、'\0'、NULL。
字符數組
定義:存放字符數據的數組
字符數組的定義:
格式:
一維字符數組:char 數組名[長度];
二維字符數組:char 數組名[行][列];
-
可以使用整型數組來存放字符數據(合法但浪費空間),反之也可以使用字符數組來存放整型數據(注意不要超過字符數據的限值)。
字符數組的初始化:
格式:
一維字符數組:char 數組名[長度]={初始化列表};
二維字符數組:char 數組名[行][列]={{初始化列表1},{初始化列表2}...,{初始化列表n}};
二維數組的引用:
格式:
一維字符數組:數組名 [下標];
二維字符數組:數組名 [行下標] [列下標];
字符串
-
c語言沒有字符串類型,也沒有字符串變量(有字符串常量),字符串是存放在字符數組中的。
-
字符串的結束標志為 '\0'(若字符串沒有'\0'則系統會自動給字符串加上)。'\0'表示ASCII碼為0的字符(空)
-
使用sizeof運算符計算字符串占用的內存空間,strlen字符處理函數計算字符串的長度。
? ?char str[]="hello\0mom";char str2[]="hello\0";printf("str長度:%d\nstr2長度:%d\n",strlen(str),strlen(str2));printf("str占用空間:%d\nstr2占用空間:%d\n",sizeof(str),sizeof(str2));printf("%s\n%s\n",str,str2);輸出結果: str長度:5 str2長度:5 str占用空間:10 str2占用空間:7 hello hello
-
c系統在字符數組存儲字符串常量時,會自動在結尾加上‘\0’作為字符串的結束標識。
char str[]="hello"; printf("%d\n",sizeof str);//6 ??注意:哪怕結尾手動加上'\0',c也會將它作為一個字符串常量的一部分,即仍然加上'\0'。
-
如果一個字符數組遇到一個及以上\0,則以第一個\0為準。
char str[]="hello\0mom\0"; printf("%s\n",str);//hello
-
字符\0不占用列寬。
? ?char str[]="hello\0mom";int i=0;while(i!=9){printf("%c",*(str+i));i++;}//hellomomprintf("\n");
字符串常量初始化字符數組
格式:
char str[]={"字符串"};
char str[]="字符串";
字符串初始化與字符列表初始化的不同:
主要體現在使用字符串初始化字符數組系統會自動在字符串末尾加上‘\0’,而使用字符列表初始化則不會。
char str[]="hello!";
等價于:
char str[]={'h','e','l','l','o','!','\0'};
而不等價于:
char str[]={'h','e','l','l','o','!'};
但是如果給上面的數組加上長度,那么就等價了
char str[8]={'h','e','l','l','o','!',};//因為部分初始化,未初始化的部分系統自動賦\0,雖然后面兩個\0,但是以第一個為準,但是占用空間不等價
同理:
char str[5]="hello";//str雖然是一個字符串,但是最大保存五個,所以最后一個\0沒有保存,他與下面的表達式不等價
char str2[]="hello";
// scanf("%s",str);//給str輸入一個字符串,雖然最后一個\0沒有保存,但是他與上面的表達式是等價的(數組是動態的,可以擴展)
if(strcmp(str,str2)==0){printf("ok");
}else{printf("no");
}
??注意:字符數組并不要求最后一個字符是‘\0’,是否需要加‘\0’根據需求決定,但是由于字符串作為初值時系統會自動加上一個‘\0’,所以使用字符初值表初始化時一般也手動加上一個‘\0’,這樣做便于引用字符數組中的字符串。
char str[]="hello";
char str2={'h','e','l','l','o','\0'};
字符串常量末尾自動加上‘\0’的好處:
char c[]="C program.";
//他在系統中的存儲方式為:C program.\0
scanf("%s",c);//輸入hello
//如果不自動加\0,則數組中最終數據為:hellogram.\0
//若自動加上\0,則最終數據為:hello\0
printf("%s\n",c);//只輸出hello,而不輸入后面的內容。
?
結論:符合人們一般的嘗試,這樣新輸入的字符串可完全代替舊字符串,方便字符串的引用。
字符數組的輸入與輸出
分類:“%c”逐個輸入輸出、“%s“連續輸入輸出
-
字符串在使用%s輸入時,地址列表不加&。輸出時,變量也無需加*取值。
-
多個字符串的連續輸入默認使用空格隔開,遇到空格則認為字符串輸入結束。
-
%s與%c一起出現在scanf輸入時,兩個之間必須加上一個空格作為分隔符。
char c; char b[10]; scanf("%s %c",b,&c);//%s默認采用空格結束,%c又必須與前面連續輸入,所以必須以空格作為分隔符。但是如果%c在%s前面就不 printf("b=%s\nc=%c\n",b,c);//用,系統會把第一個字符給字符變量,后面整個作為字符串給字符數組
-
字符變量也可采用%s輸入,但是輸出時只能使用%c。
-
字符數組與字符串都可以使用%s輸入輸出,使用%c輸入輸出字符數組與字符串時一般配合循環。
-
字符串輸出的字符中不包括‘\0’。
-
scanf函數使用%s輸入字符串時無法處理帶空格的字符串。
字符串處理函數
使用字符串處理函數必須在程序頂部加上string.h頭文件。
-
puts(參數)—輸出一個字符串(輸出后會自動換行)
參數:字符數組或字符串(只能是單個)
puts(str); puts("hello!")
注意:
char c[]="hello"; puts(c+2);//去掉前兩個輸出
-
Gets(參數)—輸入一個字符串(可輸入帶空格的字符串,完成的句子,彌補了scanf的不足)
參數:字符數組(只能是單個,函數的返回值是數組的首地址)
gets(str);//將輸入的字符串保存在字符數組str中,例如輸入 how are you?將該字符串保存給str
注意:gets里面輸入的\0與我們直接賦值的\0是有區別的,電腦會當作兩個字符輸入,其在字符串里面也是占兩個字節空間(scanf也是)
-
strcat(參數1、參數2)—連接兩個字符串
參數:參數均為字符數組,參數2可為字符常量(把數組2接到數組1的后面,結果保存在數組1中,函數的返回值是參數1的首地址)注意若參數1+x,x最大為原數組原本個數。超出則無法覆蓋第一個字符串的\0。
? char str[20]="boy";printf("%s\n",strcat(str,"girl"));//boygirl
重要:strcat兩個參數都是地址,但是第一個參數不能是常量地址。且參數1的長度要大于參數2
-
strcpy(參數1,參數2)—將參數2中的字符串復制給參數1中的字符數組(函數的返回值是參數1的首地址)
參數1:字符數組
參數2:字符串或字符數組
char str[]="hello"; strcpy(str,"ok"); printf("%s\n",str);//ok
注意:strcpy可以充當連接的作用,彌補strcat的不足
char str[20]={"hello!"}; strcpy(str+6,"TOM");//從str的第6個字符后面開始連接 printf("%s",str);//hello!TOM
strcpy會覆蓋目標字符數組中的全部內容
重要:strcpy兩個參數都是地址,但是第一個參數不能是常量地址。且參數1的長度要大于參數2
-
strncpy(參數1,參數2,參數3)—將參數2中的前n個字符賦值到參數1中的前n個字符(函數的返回值是參數1的首地址)
參數1:字符數組
參數2:字符串或字符數組
參數3:數值
char str[20]="boy";strncpy(str,"B",1);printf("%s\n",str);//Boy
重要:strcnpy兩個參數都是地址,但是第一個參數不能是常量地址。且參數1的長度要大于參數2
-
strcmp(參數1,參數2)—比較兩個字符串
參數:參數都可以是字符數組或字符串常量
strcmp(str1,str2); strcmp("hello","hello!");
規則:從左到右依次比較ASCLL碼 結果:如果相等函數返回0,參數1>參數2返回一個正整數,參數2>參數1返回一個負整數
注意:對兩個字符串的比較不允許使用 if(str1>str2)這種格式
-
strlen(參數)—檢測字符串的長度
參數:字符數組或字符串(函數的返回值是字符串的長度)
strlen(str); strlen("hello");
-
Strlwr(參數)—將字符串中的字符全部轉換為小寫字母
參數:字符串或字符數組
strlwr(str1); strlwr("HELLO!");
-
strupr(參數)—將字符串中的字符全部轉換為大寫字母
參數:字符串或字符數組
本章知識補充:
-
?c語言中,主要是根據維度討論數組。以數據類型分類,數組還分為整型數組、實型數組、字符數組、指針數組、自定義類型數組等
-
數組是一組有序數據的集合,在內存中是一片連續的空間。數組中各數據的排列是有一定規律的,下標代表數據在數組中的序號。
-
數組使用數組名和下標來唯一的確定數組中的元素。如 s[0]就表示s數組中第1個元素。
-
數組中的每個數據的數據類型相同。(不能把不同數據類型的數據放在同一數組中)
-
數組與變量相同都必須先定義后使用。
-
定義時不允許省略長度,初始化時一般省略長度(如果數組會進行替換,定義的長度一般大于實際用到的長度)
-
數組的大小在定義或初始化時就是數組的唯一大小,無法修改。
-
數組在使用字符串處理函數重新賦值時,只要沒有覆蓋后面數據,那么只會對指定的數據元素覆蓋,其他元素還是之前的值。但是此時屬于無效字符(特別是字符串)
-
不允許使用賦值運算直接對數組名進行賦值(數組名代表數組首地址)
char str[20]; str={....}或str=str2都是錯誤的
-
初值個數大于定義長度會出現編譯錯誤(不會語法錯誤)
-
數組的初始化列表一般為常量,還可以是變量、符號常量與表達式(只要數據類型一致一般都可以)
注意:張玉生c表明初值表不允許是變量。
int a[2]={N,n,1};//N為符號常量,n是變量
-
數組的引用不會檢測數組的下標,下標越界會出現編譯錯誤,但是仍然會輸出一個不確定的值。(不會語法錯誤)
-
數組中元素的地址使用&獲得(也可以使用&獲取變量的地址,但是c不允許把地址進行加運算。例如&a+&b)
printf("%d",&a[0]);//輸出該數組元素的地址
-
二維數組可以采用一維數組的形式訪問
int b[3][3]={{1,2,3},{4,5,6},{7,8,9}}; printf("%d\n",b[0][3]);//4
-
數組如果定義了長度,sizeof按照定義的長度輸出,若沒有再去根據數組內容判斷。
char str[5]="hel"; printf("%d\n",sizeof(str));//5 int arr[10]; printf("%d\n",sizeof(arr));//40 int arr2[]={1,2}; printf("%d\n",sizeof(arr2));//8
-
c語言不允許函數直接返回一個數組
-
字符串常量可以為空,表示空串,但是字符常量不可以為空。
-
對于一維數組(形參),可以省略數組大小。對于多維數組(形參),不能省略最低維度的長度
float fn(int a[][3]){//數組a不能省略最低維度列的長度,否則會報錯 return 0; }
-
一維數組做函數參數形參可以省略長度,二維數組必須有最低維度長度(聲明時也一樣)
void fn(int arr[][]){}//報錯,最低維度沒有長度 void fn(int arr[]){}//不報錯
-
字符數組與字符串的區別:字符串是用字符數組存儲的,但字符數組不一定就是字符串,字符串一定要有'\0',所以字符數組的長度必須是字符長度+1.