Lecture 3 C語言數組與函數

博主不定期更新【保研/推免、C/C++、5G移動通信、Linux、生活隨筆】系列文章,喜歡的朋友【點贊+關注】支持一下吧!


Lecture 3 數組與函數

1. 數組

如何記錄很多數?→ 數組
如何定義一個數組:<類型> 變量名稱[元素數量];

int grades[100];//grades[0]——grades[99]
double weight[20];

注意:數組下標(0—n-1)與數組元素個數(n)不一致
數組越界:segment fault

1.1 數組的集成初始化

定義數組時給數組賦值稱爲數組的集成初始化;
在這裏插入圖片描述

1.2 數組的大小

  • sizeof給出整個數組所佔據的內容的大小,單位是字節;
  • 數組中元素個數 = sizeof(a) / sizeof(a[0])

1.3 數組的遍歷

  數組變量本身不能被賦值,要把一個數組的所有元素交給另一個數組,必須採用遍歷:

錯誤賦值方式:
int a[] = {1, 2, 3, 4, 5, 6, };   int b[] = a;
正確賦值方式:
for ( i=0; i<length; i++) 
{
	b[i]=a[i];
}	

  遍歷數組常見錯誤

  • 循環結束條件是<=數組長度;
  • 離開循環後,繼續用i的值來做數組元素的下標。

1.4 數組作爲函數參數

  • 數組作爲函數參數時,往往必須再用另一個參數來傳入數組的大小
  • 數組作爲函數參數時,不能在[]中給出數組的大小(沒有意義);
  • 也不能在參數列表中或函數內部利用sizeof來計算數組的元素個數(因爲數組是以指針的形式傳進函數
  • 詳見指針的應用場景——“求最大最小值”部分

1.5 實例

1.5.1 統計輸入量0-9中各個數字出現的個數

//統計輸入量0-9中各個數字出現的個數,輸入-1表示結束。
#include <stdio.h>

int main()
{
	const int number = 10;  //數組的大小
	int x;
	int count[number]; //定義數組 (C99:數組大小可以爲一個變量)
	int i;
	/*****初始化數組*****/
	for ( i=0; i<number; i++)
	{
		count[i]=0;
	}
	
	scanf("%d", &x);
	while ( x!=-1)
	{
		if ( x>=0 && x<=9)
		{
			count[x]++; //數組參與運算
		}
		scanf("%d", &x);
	}
	/*****遍歷數組輸出*****/
	for ( i=0; i<number; i++)
	{
		printf("%d: %d\n", i, count[i]);
	}
	
	return 0;
}

1.5.2 選擇排序

  先找出最大的,放到最後面(即與數組中最後一個數交換);固定最後一個,在剩下的數中再找出最大的,放到最後面;重複進行此步驟即可。

詳見:選擇排序&二分搜索

2.函數

  函數是一塊代碼,接收零個或多個參數,做一件事情,並返回零個或一個值。
函數定義:
在這裏插入圖片描述

2.1 void函數

  沒有返回值的函數用void函數名(參數表),不能使用帶值的return(可以沒有return),調用的時候不能做返回值的賦值;如果函數有返回值,則必須使用帶值的return。

2.2 函數聲明

  • 要想把函數寫在main函數後面,需要先寫聲明:函數頭;
  • 函數頭加;構成函數原型;函數原型可以不寫參數名,只寫參數類型

2.3 函數調用

  調用函數:函數名(參數值);  ()起到了表示函數調用的重要作用,即使沒有參數也需要()   如果有參數,則需要給出正確的數量和順序,這些值會被按照順序依次用來初始化函數中的參數。
  從函數中返回值:return停止函數的執行,並送回一個值

  • return;
  • return 表達式;

  調用函數時給的值與參數的類型不匹配是C語言傳統上的最大漏洞,編譯器總是悄悄替你把類型轉換好,但是這很可能不是你所期望的,後續的語言,C++/Java在這方面很嚴格。
  C語言在調用函數時,永遠只能傳值給函數(而不是變量)。每個函數有自己的變量空間,參數也位於這個獨立的空間中,和其他函數沒有關係。

2.4 本地變量

  函數的每次運行,就產生了一個獨立的變量空間,在這個空間中的變量,是函數的這次運行所獨有的,稱作本地變量;定義在函數內部的變量就是本地變量,參數也是本地變量。
  本地變量的規則:

  • 本地變量是定義在塊(即大括號{})內的;程序運行進入這個塊之前,其中的變量不存在;離開這個塊,其中的變量就消失了;
  • 塊外面定義的變量在塊裏面仍然有效;塊裏面定義了和外面同名的變量則掩蓋了外面的;
  • 不能在同一個塊定義同名的變量;
  • 本地變量不會被默認初始化;參數在進入函數的時候被初始化了。

2.5 其他細節

  • 如果確定函數沒有參數,函數定義寫爲void f(void);
    void f(); 表示f函數的參數表未知,並不表示沒有參數;
  • 調用函數時的圓括號裏的逗號是標點符號,不是運算符
    f(a, b)和f((a, b))區別在於前者傳遞了兩個參數,後者傳遞了一個參數。
  • C語言不允許函數嵌套定義

3. 二維數組

定義:int a[3][5]; 通常理解爲a是一個3行5列的矩陣:
在這裏插入圖片描述

3.1 二維數組的遍歷

for ( i=0; i<3; i++)
	{
		for ( j=0; j<5; j++)
		{
			a[i][j] = i*j; 
			//a[i][j]是一個int,表示第i行第j列上的單元
		}
	}

3.2 二維數組的初始化

	int a[][5]=
	{
		{0,1,2,3,4},
		{1,2,3,4,5},
		{2,3,4,5,6},
	};
  • 列數是必須給出的,行數可以由編譯器來數
  • 每行一個{},逗號分隔
  • 最後的逗號可以存在,有古老的傳統
  • 如果省略,表示補零
  • 也可以用定位(C99 ONLY)

  注意:只有定義時可以這樣初始化,定義完成後應通過遍歷方法用for循環初始化;原因在於定義完成後a[][]被視作數組中的一個元素,而不是整個數組
  使用變量定義數組時,定義時不能直接初始化,需要之後利用遍歷來初始化數組。例如:

const int cnt = 3;
int a[cnt][cnt];  
//此處不能直接對數組進行集成初始化,需要之後利用遍歷來初始化數組

3.3 實例分析

tic-tac-toe遊戲,詳見:二維數組應用之tic-tac-toe遊戲勝負判斷

4.幾點注意

  • “代碼複製”是程序質量不良的表現;
  • 算法不一定和人的思考方式相同;單一出口原則(一個return);一專多能是不好的代碼;
  • 小技巧:在程序中平白無故加個大括號,多數時候是爲了調試程序,(觀察程序輸出過程)利用本地變量的規則,方便調試。
  • 收穫:程序運行結果錯誤時,利用編譯器的調試功能,一步一步調代碼,觀察代碼運行過程,一般都可以發現錯誤所在;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章