首頁 > 軟體

C語言全面梳理結構體知識點

2022-07-08 14:04:19

一、什麼是結構體

為了更好地模擬現實,需要把各種基本資料型別組合在一起構成一種新的複合資料型別,我們把這種自定義的資料型別稱為結構體。結構體是程式設計師根據實際需求,把各種基本資料型別組合在一起構成的一種新的複合資料型別。

二、結構體的定義

結構體的定義方式共有3種,這裡只用最常見也最常用的一種方式定義,即:

struct 結構體名
{
    成員列表;
}; // 注意這裡的分號不能省略

舉個例子:

struct Student
{
	int age;
	float score;
	char gender;
};

三、結構體變數的定義

結構體與我們經常使用的基本資料型別一樣,它也是一種資料型別,所以我們可以用這一資料型別定義其對應的變數,我們把用結構體型別定義的變數稱為結構體變數。定義結構體變數的方式如下所示:

#include <stdio.h>
struct Student // 定義結構體
{
	int age;
	float score;
	char gender;
};
int main()
{
	struct Student stu; // 定義結構體變數
	return 0;
}

四、結構體變數的初始化

#include <stdio.h>
struct Student // 定義結構體
{
	int age;
	float score;
	char gender;
};
int main()
{
	struct Student stu = { 15, 66.5, 'M' }; // 初始化結構體變數
	return 0;
}

五、結構體變數的賦值

定義結構體變數後,我們可以對其中的成員進行賦值操作,但與初始化不同的是,需要通過結構體變數名.成員名的方式對結構體變數中的每個成員單獨賦值。程式碼如下所示

#include <stdio.h>
struct Student // 定義結構體
{
	int age;
	float score;
	char gender;
};
int main()
{
	struct Student stu; // 定義結構體變數
	stu.age = 15; 		// 對結構體變數中的age成員賦值
	stu.score = 66.5;	// 對結構體變數中的score成員賦值
	stu.gender = 'M';	// 對結構體變數中的gender成員賦值
	return 0;
}

六、參照結構體變數中的成員

方法1:結構體變數名.成員名

#include <stdio.h>
struct Student // 定義結構體
{
	int age;
	float score;
	char gender;
};
int main()
{
	struct Student stu;  // 定義結構體變數
	// 對各成員賦值
	stu.age = 15;
	stu.score = 66.5;
	stu.gender = 'M';
	printf("%d %f %cn", stu.age, stu.score, stu.gender); // 輸出各成員的內容
	return 0;
}

方法2:結構體指標變數名->成員名

#include <stdio.h>
struct Student // 定義結構體
{
	int age;
	float score;
	char gender;
};
int main()
{
	struct Student stu;  // 定義結構體變數
	struct Student * pStu = &stu; //定義結構體指標變數
	// 對各成員賦值
	pStu->age = 15;
	pStu->score = 66.5;
	pStu->gender = 'M';
	printf("%d %f %cn", stu.age, stu.score, stu.gender); // 輸出各成員的內容
	return 0;
}

方法3:(*結構體指標變數名).成員名

#include <stdio.h>
struct Student // 定義結構體
{
	int age;
	float score;
	char gender;
};
int main()
{
	struct Student stu; //定義結構體變數
	struct Student * pStu = &stu; //定義結構體指標變數
	// 對各成員賦值
	(*pStu).age = 15;
	(*pStu).score = 66.5;
	(*pStu).gender = 'M';
	printf("%d %f %cn", stu.age, stu.score, stu.gender); // 輸出各成員的內容
	return 0;
}

七、結構體變數的傳參問題

當我們在一個函數中定義了結構體變數,而想要在另外一個函數中對該結構體變數進行操作時,則需要向被呼叫的函數傳遞引數,那傳遞結構體變數作為引數還是應該傳遞結構體指標變數作為引數呢?這是一個必須要搞清楚的問題。我以下面的程式為例闡述不同情況下的傳參問題:

#include <stdio.h>
#include <string.h>
struct Student // 定義結構體
{
	int age;
	float score;
	char name[100];
};
// 函數宣告
void input_student(struct Student* pStu);
void output_student(struct Student* pStu);
int main()
{
	struct Student stu; // 定義結構體變數
	input_student(&stu);	// 傳遞地址的原因詳見該程式下方
	output_student(&stu);	// 傳遞地址的原因詳見該程式下方
	return 0;
}
// 賦值函數
void input_student(struct Student * pStu)
{
	(*pStu).age = 10;
	pStu->score = 66.5;
	strcpy(pStu->name, "南森"); 
	/* 
		注意這裡不能寫成 pStu->name = "南森";
		這是因為一維陣列名是指標常數,不能對常數進行賦值操作
	*/
}
// 輸出函數
void output_student(struct Student* pStu)
{
	printf("%d %f %sn", (*pStu).age, pStu->score, pStu->name);
}

為什麼要傳遞地址?由於input_student函數要修改主函數中結構體變數stu各個成員的值,所以只能傳輸地址,不能傳輸變數stu,我已經在《C語言之指標知識大總結》這篇文章中詳細敘述了其中的原因。而output_student函數並不需要修改主函數中結構體變數stu各個成員的值,所以此時是可以傳輸變數stu的,但由於變數stu的型別是結構體型別,其所佔位元組數較多,而所有的指標變數都只有四個位元組,所以為了減少記憶體耗用並提高資料傳輸的效率,往往傳輸對應的結構體指標變數。

八、傳輸地址帶來的問題

向一個函數傳入某個變數的地址不僅可以修改該變數的值,而且可以提高資料傳輸效率,但這樣做也會有一定的風險。例如上一小結中的程式,其中的output_student函數作為輸出函數並不需要在其內部修改變數的值,而一旦傳入變數的地址,那就意味著output_student函數也可以對該地址所對應的變數進行修改,這樣就導致output_student這個函數非常不安全,那怎麼樣才能實現既可以快速傳輸資料,又可以在不需要修改變數值的函數中禁止該函數修改資料呢?答案很簡單,只需要在形參的指標變數前加上關鍵字const就可以達到這樣的目的。如下所示:

void output_student(const struct Student* pStu)
{
	pStu->score = 88; // 錯誤,因為指標變數pStu前有const修飾,無法修改其對應的普通變數的值
	(*pStu).age = 10; // 錯誤,因為指標變數pStu前有const修飾,無法修改其對應的普通變數的值
	printf("%d %f %sn", (*pStu).age, pStu->score, pStu->name);
}

九、動態結構體陣列

#include <stdio.h>
#include <malloc.h>
// 定義結構體
struct Student
{
	char name[100];
	int age;
	float score;
};
// 函數宣告
int create_array(struct Student**);
void input_array(struct Student*, int);
void bubble_sort(struct Student*, int);
void print(struct Student*, int);
int main()
{
	int length;
	struct Student* pStu;
	length = create_array(&pStu); // 由於要對指標變數pStu的內容進行修改,所以只能傳輸其地址
	input_array(pStu, length);
	bubble_sort(pStu, length);
	print(pStu, length);
	return 0;
}
// 該函數的作用是分配記憶體並構造陣列
int create_array(struct Student** q) // 由於需要接收一級指標變數,所以這裡需要使用二級指標
{
	int length;
	printf("請輸入學生人數:");
	scanf("%d", &length);
	printf("n");
	*q = (struct Student*)malloc(sizeof(struct Student) * length); // 動態分配記憶體構造結構體陣列
	return length;
}
// 該函數的作用是對結構體陣列中的各元素進行賦值
void input_array(struct Student* p, int length)
{
	int i;
	for (i = 0; i < length; i++)
	{
		printf("請輸入第%d個學生的資訊:n", i + 1);
		printf("姓名:");
		scanf("%s", (p + i)->name);
		printf("年齡:");
		scanf("%d", &(*(p + i)).age);
		printf("成績:");
		scanf("%f", &p[i].score);
		printf("n");
	}
}
// 該函數的作用是按照結構體陣列中的score成員從低到高進行氣泡排序
void bubble_sort(struct Student* p, int length)
{
	int i, j;
	struct Student t;
	for (i = 1; i < length; i++)
		for (j = 0; j < length - i; j++)
			if (p[j].score > p[j + 1].score)
			{	
				// 注意:比較的是score的大小,但是需要交換的是結構體陣列中元素的位置,而不是隻交換成員score
				t = p[j];
				p[j] = p[j + 1];
				p[j + 1] = t;
			}
}
// 該函數的作用是輸出結構體陣列中各元素的內容
void print(struct Student* p, int length)
{
	int i;
	printf("按照分數由低到高排序的結果為:n");
	for (i = 0; i < length; i++)
	{
		printf("姓名:%sn", (p + i)->name);
		printf("年齡:%dn", (*(p + i)).age);
		printf("成績:%fn", p[i].score);
		printf("n");
	}
}

十、關鍵字typedef

typedef關鍵字的作用是對資料型別起別名。例如:

#include <stdio.h>
typedef int INTEGER; // 給int取了個別名叫INTEGER,故INTEGER就等同於int
int main()
{
	INTEGER i = 10; // 等同於 int i = 10;
	return 0;
}
#include <stdio.h>
typedef struct Student
{
	char name[100];
	int age;
	float score;
}ST, * PST; // 給 struct Student 起了個別名ST,給 struct Student * 起了個別名叫PST
int main()
{
	ST stu;		// 等同於 struct Student stu;
	PST pStu;	// 等同於 ST * pStu; 也等同於 struct Student * pStu;
	return 0;
}

十一、C++中的參照

使用C++中的參照在向其它函數傳參時可以幫助我們提高編碼效率,嚴蔚敏老師在《資料結構》這本書中也多次使用了C++中的參照。

傳輸普通變數

C語言實現普通變數的傳輸:

#include <stdio.h>
void modify(int* p)
{
	(*p)++;
}
int main()
{
	int i = 10;
	modify(&i);
	printf("%dn", i);
	return 0;
}

C++語言實現普通變數的傳輸:

#include <stdio.h>
void modify(int& i)
{
	i++;
}
int main()
{
	int i = 10;
	modify(i);
	printf("%dn", i);
	return 0;
}

傳輸指標變數

C語言實現指標變數的傳輸:

#include <stdio.h>
#include <malloc.h>
void modify(int** q)
{
	*q = (int *)malloc(sizeof(int));
}
int main()
{
	int * p;
	modify(&p);
	return 0;
}

C++語言實現指標變數的傳輸:

#include <stdio.h>
#include <malloc.h>
void modify(int*& p)
{
	p = (int *)malloc(sizeof(int));
}
int main()
{
	int * p;
	modify(p);
	return 0;
}

到此這篇關於C語言全面梳理結構體知識點的文章就介紹到這了,更多相關C語言結構體內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com