今日開始為電賽復(fù)習(xí)一些必備的算法知識,本文回顧復(fù)習(xí)結(jié)構(gòu)體的概念以及一些基本操作,每個(gè)知識點(diǎn)都有代碼實(shí)踐演示,可以復(fù)制測試查看!
目錄
前言——往日的困惑:
一、結(jié)構(gòu)體基礎(chǔ)知識與用途:
C語言結(jié)構(gòu)體是一種自定義數(shù)據(jù)類型:
結(jié)構(gòu)體可以包含不同的數(shù)據(jù)類型:
結(jié)構(gòu)體包含以下要素與使用方式:?
結(jié)構(gòu)體的主要用途:
?結(jié)構(gòu)體的一般定義形式:
結(jié)構(gòu)體可以理解為存數(shù)據(jù)的模板:
?結(jié)構(gòu)體可以理解為自己定義的一種數(shù)據(jù)類型:
結(jié)構(gòu)體的大小如何計(jì)算:
結(jié)構(gòu)體基礎(chǔ)知識編程實(shí)戰(zhàn)強(qiáng)化:
二、結(jié)構(gòu)體組員的訪問,結(jié)構(gòu)體組員變量的初始化:
?三、結(jié)構(gòu)體數(shù)組的使用:
?四、結(jié)構(gòu)體指針訪問結(jié)構(gòu)體組員:
五、結(jié)構(gòu)體可被typedef 重定義:
前言——往日的困惑:
我在大一初學(xué)C的時(shí)候的感受是十分痛苦的:一些簡單函數(shù)的學(xué)習(xí)可以隨便看倆篇文章或查閱教科書完成,但遇到一些知識點(diǎn)比較多的結(jié)構(gòu)思想時(shí),學(xué)起來是十分沒有效率的,當(dāng)時(shí)我為了學(xué)習(xí)結(jié)構(gòu)體,查閱過大量他人寫的博客筆記,發(fā)現(xiàn)都寫得不盡完整,導(dǎo)致浪費(fèi)了大量時(shí)間去自己整合學(xué)習(xí)結(jié)構(gòu)體的知識,寫本文時(shí)我已經(jīng)寫了近一年有關(guān)單片機(jī)嵌入式的代碼了,已不再是大一時(shí)熱愛算法的少年,因此從今日開始,我打算學(xué)習(xí)充實(shí)自己的算法知識與實(shí)踐能力,并做分享。
為了讓個(gè)位看官不再被不完整的博文困擾,我爭取寫出完整的結(jié)構(gòu)體知識復(fù)習(xí)文章,爭取一篇文章解決大家的疑問,學(xué)會一些結(jié)構(gòu)體的使用手段!
一、結(jié)構(gòu)體基礎(chǔ)知識與用途:
C語言結(jié)構(gòu)體是一種自定義數(shù)據(jù)類型:
它允許將不同類型的數(shù)據(jù)組合在一起,并賦予其一個(gè)名稱,以便更容易地管理和操作這些數(shù)據(jù)。結(jié)構(gòu)體是一種非常有用的工具,用于定義和操作復(fù)雜的數(shù)據(jù)結(jié)構(gòu),實(shí)現(xiàn)數(shù)據(jù)的封裝、傳遞和處理等功能。
結(jié)構(gòu)體可以包含不同的數(shù)據(jù)類型:
如整數(shù)、浮點(diǎn)數(shù)、字符等,甚至可以包含其他結(jié)構(gòu)體。
結(jié)構(gòu)體包含以下要素與使用方式:?
1.名稱:結(jié)構(gòu)體是自己定義的數(shù)據(jù)類型或模板,一個(gè)程序項(xiàng)目中不同用途的結(jié)構(gòu)體需要有不同的名稱來區(qū)分。
2. 數(shù)據(jù)成員:結(jié)構(gòu)體可以包含多個(gè)不同數(shù)據(jù)類型的成員,這些成員可以是基本數(shù)據(jù)類型(如整數(shù)、浮點(diǎn)數(shù)、字符等),也可以是其他自定義的數(shù)據(jù)類型(如數(shù)組、指針、其他結(jié)構(gòu)體等)。
3. 結(jié)構(gòu)體變量:通過結(jié)構(gòu)體定義的模板,可以創(chuàng)建多個(gè)實(shí)際的結(jié)構(gòu)體變量,每個(gè)實(shí)例都具有相同的結(jié)構(gòu)和成員,但可以存儲不同的數(shù)據(jù)。
4. 訪問成員:可以使用結(jié)構(gòu)體變量名和成員名的組合來訪問結(jié)構(gòu)體的各個(gè)成員,并進(jìn)行讀取或賦值操作。
5. 結(jié)構(gòu)體指針:可以使用指向結(jié)構(gòu)體的指針變量,通過指針來訪問和操作結(jié)構(gòu)體的成員,可以實(shí)現(xiàn)更靈活的操作方式。
6. 結(jié)構(gòu)體嵌套:結(jié)構(gòu)體可以作為其它結(jié)構(gòu)體的成員,從而實(shí)現(xiàn)更復(fù)雜的數(shù)據(jù)組織和層次化結(jié)構(gòu)。
7. 結(jié)構(gòu)體作為函數(shù)參數(shù):可以將結(jié)構(gòu)體作為函數(shù)的參數(shù)進(jìn)行傳遞,通過引用傳遞可以修改結(jié)構(gòu)體的值,從而實(shí)現(xiàn)對結(jié)構(gòu)體數(shù)據(jù)的批量處理和操作。
8. 結(jié)構(gòu)體作為函數(shù)返回值:函數(shù)可以返回結(jié)構(gòu)體類型的數(shù)據(jù),從而方便地返回多個(gè)不同類型的結(jié)果。
結(jié)構(gòu)體的主要用途:
1. 定義復(fù)雜的數(shù)據(jù)結(jié)構(gòu):結(jié)構(gòu)體可以用于定義更復(fù)雜的數(shù)據(jù)結(jié)構(gòu),比如鏈表、樹等。通過將不同類型的數(shù)據(jù)組合在一起,可以更好地組織、訪問和操作數(shù)據(jù)。
2. 數(shù)據(jù)封裝:結(jié)構(gòu)體可以將相關(guān)的數(shù)據(jù)封裝在一起,形成一個(gè)單個(gè)實(shí)體,從而更好地進(jìn)行管理。通過封裝數(shù)據(jù),可以提高代碼的可讀性、可維護(hù)性和可擴(kuò)展性。
3. 傳遞和返回多個(gè)值:使用結(jié)構(gòu)體可以方便地傳遞和返回多個(gè)值,而不需要使用單獨(dú)的參數(shù)或全局變量。這對于某些函數(shù)需要返回多個(gè)結(jié)果或需要傳遞多個(gè)相關(guān)的參數(shù)時(shí)非常有用。
4. 數(shù)據(jù)庫和文件處理:結(jié)構(gòu)體可以方便地表示和處理數(shù)據(jù)庫中的記錄,以及文件中的數(shù)據(jù)。通過定義適當(dāng)?shù)慕Y(jié)構(gòu)體,可以更好地管理數(shù)據(jù)庫和文件的數(shù)據(jù)。
?結(jié)構(gòu)體的一般定義形式:
struct + 結(jié)構(gòu)體名稱
{
成員列表;
};
?結(jié)構(gòu)體變量的定義可以放在結(jié)構(gòu)體的聲明之后:
struct Student //定義一個(gè)名為Student的結(jié)構(gòu)體
{
char name[20]; //姓名
int id; //學(xué)號
int age; //年齡
};
struct Student stu; //定義一個(gè)結(jié)構(gòu)體變量
結(jié)構(gòu)體變量的定義也可以在結(jié)構(gòu)體聲明的同時(shí)定義,這樣就簡化了代碼:
struct Student //定義一個(gè)名為Student的結(jié)構(gòu)體
{
char name[20]; //姓名
int id; //學(xué)號
int age; //年齡
}stu; //在結(jié)構(gòu)體聲明的同時(shí)定義一個(gè)結(jié)構(gòu)體變量stu
結(jié)構(gòu)體可以理解為存數(shù)據(jù)的模板:
?此處注意旨在講明,結(jié)構(gòu)體是從什么時(shí)候開始才占用內(nèi)存空間的:
結(jié)構(gòu)體它并不實(shí)際儲存數(shù)據(jù),它本身不分配內(nèi)存空間來存儲實(shí)際數(shù)據(jù),我們不能將其看作一個(gè)或者很多變量,正確理解它的方式應(yīng)該是將其看作一種存儲數(shù)據(jù)的模板,數(shù)據(jù)會以我們對結(jié)構(gòu)體定義的方式進(jìn)行排列組合,只有我們定義結(jié)構(gòu)體變量或者結(jié)構(gòu)體數(shù)組時(shí),才會申請分配一塊空間來存儲實(shí)際的數(shù)據(jù)。
?結(jié)構(gòu)體可以理解為自己定義的一種數(shù)據(jù)類型:
此處為解明,結(jié)構(gòu)體定義完后,再定義結(jié)構(gòu)體變量是什么意思,可以類比為什么。
我們從上表可以了解到,int是C語言中的一個(gè)基本數(shù)據(jù)類型,它本身不占用空間,只有在我們用這個(gè)數(shù)據(jù)類型定義變量時(shí)會開辟一條空間,比如我定義了int a;此時(shí)就會為變量a開辟一片4字節(jié)的空間,我們也可如此認(rèn)為,結(jié)構(gòu)體與int類似,只不過它存儲的數(shù)據(jù)成員有哪些、結(jié)構(gòu)體名稱是什么,都要我們自行定義,比如我定義一個(gè)結(jié)構(gòu)體,名稱是student,定義完結(jié)構(gòu)體后,student就可以被看做一個(gè)數(shù)據(jù)類型的名稱了,我可以用其定義變量了,比如:struct student B;這樣就定義了一個(gè)結(jié)構(gòu)體變量B,后續(xù)我們也會學(xué)習(xí)如何獲取它每個(gè)成員的數(shù)據(jù)。
結(jié)構(gòu)體的大小如何計(jì)算:
我們定義完結(jié)構(gòu)體變量B之后,其占用內(nèi)存空間大小該怎么計(jì)算呢?
首先列出一些 常用數(shù)據(jù)類型的占用內(nèi)存大?。?/p>
在C語言中,常用的數(shù)據(jù)類型及其所占的內(nèi)存大?。ㄔ谝话闱闆r下)如下所示:
1. char:1字節(jié)
2. int:4字節(jié)
3. float:4字節(jié)
4. double:8字節(jié)
5. short:2字節(jié)
6. long:4或8字節(jié)(取決于操作系統(tǒng))
7. long long:8字節(jié)
8. unsigned char:1字節(jié)
9. unsigned int:4字節(jié)
10. unsigned short:2字節(jié)
11. unsigned long:4或8字節(jié)(取決于操作系統(tǒng))
12. unsigned long long:8字節(jié)
結(jié)構(gòu)體占用內(nèi)存大小可以通過函數(shù)直接計(jì)算:
可以直接用sizeof進(jìn)行計(jì)算:sizeof(struct MyStruct);
結(jié)構(gòu)體基礎(chǔ)知識編程實(shí)戰(zhàn)強(qiáng)化:
學(xué)習(xí)實(shí)現(xiàn)的功能如下:
定義一個(gè)結(jié)構(gòu)體,定義結(jié)構(gòu)體變量,并輸出計(jì)算其占用內(nèi)存大小
代碼:
#include "stdio.h"
//定義結(jié)構(gòu)體
struct student{
char name;
int age;
};
int main()
{
//定義結(jié)構(gòu)體變量B
//利用結(jié)構(gòu)體去定義變量的時(shí)候,必須加上struct,不能省略
struct student B;
//定義變量用于存儲計(jì)算結(jié)構(gòu)體大小
int size;
//計(jì)算結(jié)構(gòu)體大小
size=sizeof(struct student);
//輸出這個(gè)大小
printf("%d",size);
return 0;
}
結(jié)果演示:
?文章來源地址http://www.zghlxwxcb.cn/news/detail-516794.html
二、結(jié)構(gòu)體組員的訪問,結(jié)構(gòu)體組員變量的初始化:
雖然結(jié)構(gòu)類似一個(gè)數(shù)組,只是數(shù)組每個(gè)元素的數(shù)據(jù)類型都是相同的,而結(jié)構(gòu)中每個(gè)元素成員的數(shù)據(jù)類型是可以不同的。
結(jié)構(gòu)體不像數(shù)組那樣使用下標(biāo)去訪問其中的各個(gè)元素,而用結(jié)構(gòu)體成員運(yùn)算符點(diǎn)(.)。
即訪問成員的一般形式是:結(jié)構(gòu)體變量名.成員名
在定義完結(jié)構(gòu)體,在定義結(jié)構(gòu)體變量以后,我們可以與定義變量一樣給它立即初始化一些值。
接下來直接進(jìn)行編程實(shí)戰(zhàn)展示:
學(xué)習(xí)實(shí)現(xiàn)功能:
1.定義結(jié)構(gòu)體、結(jié)構(gòu)體變量
2.定義結(jié)構(gòu)體變量時(shí)就初始化結(jié)構(gòu)體變量的成員值,并直接輸出打印
3.改變結(jié)構(gòu)體變量成員的值,并輸出
?代碼:
#include "stdio.h"
//定義結(jié)構(gòu)體
struct student{
char name;
int age;
};
int main()
{
//定義結(jié)構(gòu)體變量B
//利用結(jié)構(gòu)體去定義變量的時(shí)候,必須加上struct,不能省略
//同時(shí)初始化組員 name與 age 分別為 A 18
struct student B={'A',18};
//訪問輸出結(jié)構(gòu)體變量B的倆個(gè)組員name與 age
printf("name=%c,age=%d\n",B.name,B.age);
//改變結(jié)構(gòu)體變量B組員 age的值
B.age=21;
//訪問輸出結(jié)構(gòu)體變量B的倆個(gè)組員name與 age
printf("name=%c,age=%d\n",B.name,B.age);
return 0;
}
結(jié)果演示:
?普通變量訪問結(jié)構(gòu)體成員的值只需用“=”即可:
//定義結(jié)構(gòu)體
struct student{
char name;
int age;
};
struct student B={'A',18};
int AB;
AB=B.age;
?三、結(jié)構(gòu)體數(shù)組的使用:
我們從類比普通的數(shù)據(jù)類型開始講解,比如大家最熟悉的int,我們都知道語句int A;可以定義一個(gè)變量A來存儲整數(shù)形數(shù)據(jù),當(dāng)我們需要一連串有規(guī)律、有1~9之類的下標(biāo),得以便捷訪問的許多整形數(shù)據(jù)時(shí),就需要定義一個(gè)整數(shù)形數(shù)組了:int? A[10];
當(dāng)然,我們之前有了解過,結(jié)構(gòu)體可以看作為數(shù)據(jù)類型,因此也可定義為數(shù)組形式!
我們直接實(shí)戰(zhàn)學(xué)習(xí)一下:
1.定義結(jié)構(gòu)體、結(jié)構(gòu)體數(shù)組
2.輸出結(jié)構(gòu)體數(shù)組
?代碼:
#include "stdio.h"
//定義結(jié)構(gòu)體
struct student{
char name;
int age;
};
int main()
{
int i;
//定義結(jié)構(gòu)體數(shù)組 有5個(gè)下標(biāo)
struct student AB[5];
//改變結(jié)構(gòu)體各個(gè)數(shù)組變量各個(gè)組員的值
AB[0].name='A';AB[0].age=18;
AB[1].name='B';AB[1].age=19;
AB[2].name='C';AB[2].age=20;
AB[3].name='D';AB[3].age=21;
AB[4].name='E';AB[4].age=22;
AB[5].name='F';AB[5].age=23;
for(i=0;i<5;i++)
{
//訪問輸出結(jié)構(gòu)體變量B的倆個(gè)組員name與 age
printf("name=%c,age=%d\n",AB[i].name,AB[i].age);
}
return 0;
}
結(jié)果演示:
?
?
?四、結(jié)構(gòu)體指針訪問結(jié)構(gòu)體組員:
指針與指針變量是兩個(gè)不同的概念,指針是某個(gè)普通變量的地址,所以可以理解為,指針就是地址,地址就是指針。指針變量是一種變量,它的作用是存儲其它變量的地址。
?指針就是一個(gè)變量,用來存放地址,地址標(biāo)識一塊空間。
?以下代碼是使用指針操作char數(shù)據(jù)類型的實(shí)例:
int main()
{
char ch = 'w'; //創(chuàng)建一個(gè)char類型的變量去存放字符'w'
char *pc = &ch;//創(chuàng)建一個(gè)字符指針變量,去存放
*pc = 'a';//將字符'a'存放到pc地址所指向的字符,也就是把pc所指向的字符更改成字符'a'
return 0;
}
經(jīng)過以上代碼的學(xué)習(xí),我們發(fā)現(xiàn),結(jié)構(gòu)體也是一種數(shù)據(jù)類型,因此也可以被指針指向結(jié)構(gòu)體的地址:
?關(guān)鍵代碼:
//定義一個(gè)結(jié)構(gòu)體指針p去指向結(jié)構(gòu)體變量B
struct student *p = &B;
(*p).name = 'B'; //等價(jià)于p -> name= 'B'; //名字修改為B
(*p).age = 23; //等價(jià)于p -> age = 23; //將年齡修改為23
?全部代碼:
起初結(jié)構(gòu)體存的是 name=A,age=18,并先打印輸出
在定義結(jié)構(gòu)體指針指向地址,修改指針后,變成了name=B,age=23,并打印輸出
#include "stdio.h"
//定義結(jié)構(gòu)體
struct student{
char name;
int age;
};
int main()
{
//定義結(jié)構(gòu)體變量B
//利用結(jié)構(gòu)體去定義變量的時(shí)候,必須加上struct,不能省略
//同時(shí)初始化組員 name與 age 分別為 A 18
struct student B={'A',18};
//訪問輸出結(jié)構(gòu)體變量B的倆個(gè)組員name與 age
printf("name=%c,age=%d\n",B.name,B.age);
//定義一個(gè)結(jié)構(gòu)體指針p去指向結(jié)構(gòu)體變量B
struct student *p = &B;
(*p).name = 'B'; //等價(jià)于p -> name= 'B'; //名字修改為B
(*p).age = 23; //等價(jià)于p -> age = 23; //將年齡修改為23
//訪問輸出結(jié)構(gòu)體變量B的倆個(gè)組員name與 age
printf("name=%c,age=%d\n",B.name,B.age);
return 0;
}
【注】結(jié)構(gòu)體成員如果是字符串,不能直接通過賦值號“=”去修改值,可以通過C語言中的拷貝函數(shù)strcpy去修改值。
五、結(jié)構(gòu)體可被typedef 重定義:
typedef 為C語言的關(guān)鍵字,作用是為一種數(shù)據(jù)類型定義一個(gè)新名字,這里的數(shù)據(jù)類型包括內(nèi)部數(shù)據(jù)類型(int,char等)和自定義的數(shù)據(jù)類型(struct等)。
使用 typedef 定義新類型的方法(步驟):
在傳統(tǒng)的變量聲明表達(dá)式里,用(新的)類型名替換變量名,然后把關(guān)鍵字 typedef 加在該語句的開頭就可以了。
但此處的替換的意思不是說原先的關(guān)鍵字不能用了:
比如我寫了typedef int u32;
此句是給int 這個(gè)關(guān)鍵字起了一個(gè)別名,叫u32,
以后我想定義一個(gè)int類型的數(shù)據(jù),可以這么寫:u32 A;(等價(jià)與 int A;)
并且int A;這樣的寫法依舊合法,可以使用。
而在結(jié)構(gòu)體中的用法如下:
#include "stdio.h"
//重定義結(jié)構(gòu)體 student名稱為 ST
typedef struct student{
char name;
int age;
}ST;
//重定義的名稱 ST可以理解為 寫ST就等價(jià)于寫struct student
int main()
{
//定義結(jié)構(gòu)體變量B ,我們可以發(fā)現(xiàn)此時(shí)不需要寫 struct了,節(jié)省了代碼量
//同時(shí)初始化組員 name與 age 分別為 A 18
ST B={'A',18};
//訪問輸出結(jié)構(gòu)體變量B的倆個(gè)組員name與 age
printf("name=%c,age=%d\n",B.name,B.age);
return 0;
}
可以發(fā)現(xiàn),定義結(jié)構(gòu)體變量B 時(shí)不需要寫 struct了,節(jié)省了代碼量!
結(jié)果演示:
?文章來源:http://www.zghlxwxcb.cn/news/detail-516794.html
?
到了這里,關(guān)于C語言算法筆記1:結(jié)構(gòu)體、結(jié)構(gòu)體數(shù)組實(shí)戰(zhàn)講解的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!