數組相關)
一、為什么需要數組在編程中我們經常需要處理多個相同類型的數據。比如存儲10個學生的成績如果不用數組就得定義10個單獨的變量score1,score2, …不僅麻煩而且無法用循環統一處理。數組正是為了解決這類問題而生的——它能在內存中連續存儲多個相同類型的數據并通過下標快速訪問每個元素。二、一維數組基礎1. 數組的定義語法格式類型說明符 數組名[常量表達式];例如inta[10];// 定義一個包含10個int元素的數組charstr[32];// 定義包含32個char元素的數組floatarray[5];// 定義包含5個float元素的數組類型說明符可以是基本數據類型int、char、float等也可以是構造類型但不能是void。數組名遵循標識符命名規則字母、數字、下劃線數字不能開頭。常量表達式表示數組元素個數必須是編譯時確定的常量不能是變量。2. 數組元素的訪問通過數組名[下標]訪問元素下標從0開始到元素個數-1結束。a[0]10;// 給第一個元素賦值a[5]99;// 給第六個元素賦值printf(%d,a[0]);// 輸出第一個元素注意下標可以是常量、變量或表達式結果必須為整型。訪問時不要超出范圍否則會越界訪問可能導致程序崩潰或數據錯亂。3. 數組的初始化初始化即在定義時給元素賦初值。全部初始化inta[5]{1,2,3,4,5};局部初始化未初始化的元素自動為0inta[5]{1,2,3};// 前三個為1,2,3后兩個為0初始化全0inta[5]{0};// 所有元素為0inta[5]{0,0,0,0,0};省略數組大小必須初始化inta[]{1,2,3,4,5};// 編譯器自動確定大小為5重要如果不初始化數組元素的值是隨機的內存中遺留的值所以定義時盡量初始化哪怕只是{0}。4. 數組的存儲特性單一性所有元素類型相同。有序性元素按下標從0到N-1順序存儲。連續性數組占用一塊連續的內存空間。這一點非常重要因為連續存儲使得我們可以通過指針和偏移量快速訪問也是數組效率高的原因。三、數組的經典應用排序排序是數組的典型應用。這里以選擇排序為例掌握其思想。選擇排序升序每次從待排序位置開始往后找到最小值放到當前位置。inta[10]{1,2,-3,-4,-5,6,7,8,-9,0};intlensizeof(a)/sizeof(a[0]);// 計算元素個數for(inti0;ilen-1;i){for(intji1;jlen;j){if(a[i]a[j]){// 升序如果前面大于后面交換inttmpa[i];a[i]a[j];a[j]tmp;}}}時間復雜度O(n2)空間復雜度O(1)。選擇排序是不穩定的相同元素相對順序可能改變。四、字符型數組字符串C語言沒有專門的字符串類型而是用字符數組來存儲字符串并以\0ASCII碼0作為結束標志。1. 定義與初始化charstr[32];charstr[32]{h,e,l,l,o};// 不推薦未初始化部分為0charstr[32]{hello};// 推薦charstr[32]hello;// 最常用charstr[]hello;// 自動確定大小為6包含\0注意hello實際占6個字節5個字符 1個\0。2. 輸入與輸出輸出可以使用printf(%s, str)或puts(str)自動換行。輸入可以使用scanf(%s, str)遇空格或Tab停止或gets(str)遇換行停止但危險可能越界。charstr[100]{0};scanf(%s,str);// 輸入 hello world 只讀入 hellogets(str);// 可讀入帶空格的字符串但存在越界風險3. 常用字符串操作函數手寫實現雖然標準庫提供了strlen、strcpy、strcat等但理解其底層實現至關重要。① 求字符串長度 (strlen)統計有效字符個數不包括\0。intmy_strlen(constchar*s){intlen0;while(s[len]!\0){len;}returnlen;}② 字符串拷貝 (strcpy)將源字符串復制到目標數組目標數組空間要足夠。voidmy_strcpy(char*dst,constchar*src){inti0;while(src[i]!\0){dst[i]src[i];i;}dst[i]\0;// 別忘了結束標志}③ 字符串拼接 (strcat)將源字符串追加到目標字符串末尾。voidmy_strcat(char*dst,constchar*src){inti0,j0;while(dst[i]!\0)i;// 找到dst的末尾while(src[j]!\0){dst[i]src[j];i;j;}dst[i]\0;}五、二維數組二維數組可以理解為“數組的數組”常用于存儲矩陣或表格數據。1. 定義與訪問inta[3][4];// 3行4列共12個元素訪問方式a[行下標][列下標]行下標范圍02列下標03。2. 初始化全部初始化分行或不分行inta[3][4]{{1,2,3,4},{5,6,7,8},{9,10,11,12}};inta[][4]{{1,2,3,4},{5,6,7,8},{9,10,11,12}};// 可省略行數inta[3][4]{1,2,3,4,5,6,7,8,9,10,11,12};// 自動按行填充局部初始化未初始化的補0inta[3][4]{{1,2},{3,4,5},{6}};// 第一行1,2,0,0第二行3,4,5,0第三行6,0,0,0注意在初始化時行數可以省略但列數不能省略。3. 二維字符型數組用于存儲多個字符串如學生名單。charstr[3][100]{0};// 3個字符串每個最長99字符charstr[3][100]{hello,world,how};輸入輸出時用gets(str[i])或scanf(%s, str[i])循環處理每一行。六、易錯點與最佳實踐越界訪問下標超出范圍不會報錯但會破壞內存數據務必確保下標在合法范圍內。忘記\0結束符字符數組作為字符串使用時必須保證有\0否則輸出會亂碼。sizeof與strlen的區別sizeof是運算符計算數組占用的總字節數包括\0。strlen是函數計算字符串有效字符個數不含\0。數組名是地址常量不能對數組名賦值如str hello是錯誤的。盡量避免使用gets推薦fgets或scanf配合寬度限制。