C語言博客作業06--結構體&文件


1.本章學習總結

1.1 學習內容總結

1.結構的介紹


結構(Structure)類型是一種允許程序員把一些數據分量聚合成一個整體的數據類型,一個結構中包含的每個數據分量都有名字。這些數據分量稱為結構成員或者結構分量,結構成員可以是C語言中的任意變量類型,程序員可以使用結構類型來創建適合於問題的數據聚合。
像數組和指針一樣,結構也是一種構造數據類型(或叫派生數據類型),它與數組的區別在於:數組中所有元素的數據類型必須是相同的,而結構中各成員的數據類型可以不同。


2.結構是C語言中一種新的構造數據類型,它能夠把有內在聯系的不同類型的數據匯聚成一個整體,使它們相互關聯;同時,結構又是一個變量的集合, 可以按照對基本數據類型的操作方達單獨使用其成員變量。

3.在C語言中,整型、實型等基本數據類型是被系統預先定義好了的,程序員可以用其直接定義變量。而結構類型是由用戶根據需要,按規定的格式自行定義的數據類型。

4.結構類型定義的一般形式為:


struct 結構名 {
   類型名 結構成員名1;
   類型名 結構成員名2;
   …
   類型名 結構成員名n;
};


5.struct是定義結構類型的關量字,在struct之后,自行命名一個結構名,它必須是一個合法的C標識符。struct與結構名兩者合起來共同組成結構類型名,大括號內的內容是結構所包括的結構成員,也叫結構分量。結構成員可以有多個,這樣,大括號中定義的成員信息被聚合為一個整體並形成了一個新的數據類型。

6.關鍵字struct和它后面的結構名一起組成一個新的數據類型名。結構的定義以分號結束,這是因為C語言中把結構的定義看做一條語句。

7.結構變量可以通過結構成員操作符“.”對某個成員進行引用。

8.如果兩個結構變量的類型相同,可以直接賦值,將一個結構變量的所有成員值都賦給另一個。

9.結構的嵌套定義

  • 一個結構的成員是由合法的C語言數據類型和變量名組成的,進一步地說,在定義結構成員時所用的數據類型也可以是結構類型,這樣就形成了結構類型的嵌套。
  • 結構類型的嵌套定義使成員數據被進一步細分,有利於對數據的深入分析與處理。
  • 在定義嵌套的結構類型時,必須先定義成員的結構類型,再定義主結構類型。

10.結構體變量的定義


<1>單獨定義
單獨定義是指先定義一個結構類型,再定義這種結構類型的變量。
一般形式為:
struct 結構名 {
   類型名 結構成員名1;
   類型名 結構成員名2;
   …
   類型名 結構成員名n;
};
struct 結構名 結構變量名表;

<2>混合定義
混合定義是指在定義結構類型的同時定義結構變量。
一般形式為:
struct 結構名 {
   類型名 結構成員名1;
   類型名 結構成員名2;
   …
   類型名 結構成員名n;
} 結構變量名表;

<3>無類型名定義
無類型名定義是指在定義結構變量時省略結構名,定義結構類型並且同時定義結構變量。
一般形式為:
struct {
   類型名 結構成員名1;
   類型名 結構成員名2;
   …
   類型名 結構成員名n;
} 結構變量名表;

ps:第3種定義形式省略了結構名。要注意的是,由於沒有給出結構名,在此定義語句后面無法再定義這個類型的其他結構變量,除非把定義過程再寫一遍。


11.結構變量的初始化:

  • 結構變量可以初始化,即在定義時對其賦初值。
  • 結構變量的初始化采用初始化表的方法,大括號內各數據項間用逗號隔開,將大括號內的數據項按順序對應地賦給結構變量內各個成員,且要求數據類型一致。

12.C語言規定,結構類型變量的存儲布局按其類型定義中成員的先后順序排列。

13.通常,一個結構類型變量所占的內存空間是其各個成員所占內存空間之和,可以用sizeof計算其所需存儲空間,如sizeof( struct student)或者sizeof(s1),sizeof的運算對象可以是結構類型名,也可以是結構變量名,計算結果以字節為單位。

14.結構變量的使用


1.結構變量成員的引用
使用結構變量主要就是對其成員進行操作。在C語言中,使用結構成員操作符“.”來引用結構成員,格式為:
結構變量名. 結構成員名
在C語言中,對結構變量成員的使用方法與同類型的變量完全相同。
對嵌套結構成員的引用方法和一般成員的引用方法類似,也是采用結構成員操作符“.”進行的。
此外,由於結構成員運算符的優先級屬最高級別,所以一般情況下都是優先執行,即和一般運算符混合運算時,結構成員運算符優先。

2.結構變量的整體賦值
如果兩個結構變量具有相同的類型,則允許將一個結構變量的值直接賦給另一個結構變量。賦值時,將賦值符號右邊結構變量的每一個成員的值都賦給了左邊結構變量中相應的成員。這是結構中唯一的整體操作方式。
只有相同結構類型的變量之間才可以直接賦值。

3.結構變量作為函數參數
在一個由多個函數組成的C語言程序中,如果程序中含有結構類型的數據,就有可能需要用結構變量作為函數的參數或返回值,以便在函數間傳遞數據。
結構變量作為函數參數的特點是,可以傳遞多個數據且參數形式較簡單。但是,對於成員較多的大型結構,參數傳遞時所進行的結構數據復制使得效率較低。


15.一個結構變量只能表示一個實體的信息(比如,變量s1只能表示一個學生信息),如果有許多相同類型的實體,就需要使用結構數組。

16.結構數組


結構數組是結構與數組的結合體,與普通數組的不同之處在於每個數組元素都是一個結構類型的數據,包括多個成員項。

結構數組的定義方法與結構變量類似,例如:
struct student students[50];
定義了一個結構數組 students,它有50個數組元素,從 students[0]到 students [49],每個數組元素都是結構類型 struct student,這樣就可以存儲50個學生的信息。

在定義結構數組時,也可以同時對其進行初始化,其格式與二維數組的初始化類似。

在C語言中,編譯程序為所有結構數組元素分配足夠的存儲單元,結構數組的元素是連續存放的。

由於每個結構數組元素的類型都是結構類型,其使用方法就和相同類型的結構變量一樣。

對結構數組元素成員的引用是通過使用數組下標與結構成員操作符“.”相合的方式來實現的,其一般格式為:
結構數組名 [下標]. 結構成員名

由於結構數組中的所有元素都屬於相同的結構類型,因此,數組元素之間可以直接賦值。


17.指針可以指向任何一種類型的變量,而結構變量也是C語言中的一種合法變量,因此,指針也可以指向結構變量,這就是結構指針。結構指針就是指向結構類型變量的指針。

18.結構類型的數據往往由多個成員組成,結構指針的值實際上是結構變量的首地址,即第一個成員的地址。

19.有了結構指針的定義,既可以通過結構變量直接訪問結構成員,也可以通過結構指針變量間接訪問它所指向的結構變量中的各個成員。具體有兩種形式:


(1)用*p訪問結構成員
如:(*p).num=101;
其中*p表示的是指向的結構變量。注意,(*p)中的括號是不可少的,因為成員運算符“.”的優先級高於“*“的優先級,若沒有括號,則*p.num等價於*(p.num),含義發生了變化,從而會產生錯誤。

(2)用指向運算符->訪問指針指向的結構成員
如:p->num=101;


20.當p指向結構變量s1時,下面3條語句的效果是一樣的:


s1.num=101;
(*p).num=101;
p->num=101;


21結構變量也可以作為函數參數,在參數傳遞時,把實參結構中的每一個成員值傳遞給形參結構的成員。但是,當結構成員數量眾多時,在參數傳遞過程中就需要消耗很多空間。而使用結構指針作為函數參數只要傳遞一個地址值,因此,能夠極大地提高參數傳遞的效率。

22.文件的作用


(1)許多程序在實現過程中,依賴於把數據保存到變量中,而變量是通過內存單元存儲數據的,數據的處理完全由程序控制。當一個程序運行完成或終止運行,所有變量的值不再保存。另外,一般的程序都會有數據輸入與輸出,如果輸入輸出數據量不大,通過鍵盤和顯示器即可解決。當輸入輸出數據量較大時,就會受到限制,帶來不便。

(2)文件是解決上述問題的有效辦法,它通過把數據存儲在磁盤文件中,得以長久保存。當有大量數據輸入時,可通過編輯工具事先建立輸入數據的文件,程序運行時將不再從鍵盤輸入,而從指定的文件上讀入,從而實現數據一次輸入多次使用。同樣量數據輸出時,可以將其輸出到指定文件,不受屏幕大小限制,並且任何時候可以查看結果文件。一個程序的運算結果還可以作為其他程序的輸入,進行進一步加工。


23.文件的概念


(1)文件系統功能是操作系統的重要功能和組成部分。每個文件都有文件名,並且有自己的屬性。文件可以通過應用程序創建,如運行“記事本”程序,輸入一些數據,輸入文件名,就會在磁盤中產生一個文本文件。

(2)在操作系統中,文件是指駐留在外部介質(如磁盤等)中的一個有序數據集,可以是源文件、目標程序文件、可執行程序,也可以是待輸入的原始數據,或是一組輸出的結果。

(3)源文件、目標文件和可執行程序可稱為程序文件,輸入輸出數據可稱為數據文件。數據文件還可分為各種類型,如文本文件、圖像文件、聲音文件等。

(4)使用應用程序時,通常保存功能實現把數據從內存寫入到文件,這就是所謂的“存盤”。打開功能實現把磁盤文件的內容讀入到內存。

(5)C語言處理的文件與 Windows XP等操作系統的文件概念相同,但C語言中的文件類似於數組、結構等,是一種數據組織方式,是C語言程序處理的對象。

(6)編輯文件時,輸入的數據先是在內存中,保存后,數據才被寫入到磁盤中。


24.文件的特點:數據永久保存,數據長度不定,數據按順序存取。

25.文本文件和二進制文件


(1)在C語言中,按數據存儲的編碼形式,數據文件可分為文本文件和二進制文件兩種。

(2)文本文件是以字符ASCII碼值進行存儲與編碼的文件, 其文件的內容就是字符。二進制文件是存儲二進制數據的文件。

(3)從文件的邏輯結構上看,C語言把文件看作數據流,並將數據按順序以一維方式組織存儲,這正好與數據文件的動態存取和操作順序一致。根據數據存儲的形式,文件的數據流又分為字符流和二進制流,前者稱為文本文件(或字符文件),后者稱為二進制文件。

(4)C語言源程序是文本文件,其內容完全由ASCII碼構成,通過”記事本”等編輯工具可以對文件內容進行查看、修改等。

(5)C程序的目標文件和可執行文件是二進制文件,它包含的是計算機才能識機器代碼,如果也用編輯工具打開,會看到稀奇古怪的符號,即通常所說的亂碼。

(6)對於具體的數據選擇哪一類文件進行存儲,應該由需要解決的問題來決定,並在程序的一開始就定義好。


26.緩沖文件系統


應用程序進行文件數據的訪問:
由於系統對磁盤文件數據的存取速度與內存數據存取訪問的速度不同,面且文件數量較大,數據從磁盤讀到內存或從內存寫到磁盤文件不可能瞬間完成,所以為了提高數據存取訪問的效率,C程序對文件的處理采用緩沖文件系統的方式進行,這種方式要求程序與文件之間有一個內存緩沖區,程序與文件的數據交換通過對該緩沖區來進行。


27.fopen()、fscanf()、fclose()是文件操作的函數,在stdio.h中定義。

28.共用體

  • 共同體和結構體類似,也是一種構造類型的數據結構。
  • 在進行某些算法得時候,需要使幾種不同類型的變量存到同一段內存單元中,幾個變量間相互重疊,這種幾個不同的變量共同占用一段內存的結構,在C語言中,被稱作"共用體"類型結構,共用體所有成員占有同一段地址空間。
  • 共用體的大小是其占內存長度最大的成員的大小。
  • 一般定義形式

  union 共用體名
  { 
       成員聲明
       成員聲明  
       ...
    } 變量表列;


29.枚舉類型

  • 枚舉是指將變量的值一一列舉出來,變量只限於列舉出來的值的范圍內取值。枚舉類型也是構造類型。
  • 一般定義方法

enum 枚舉名 { 枚舉值1, 枚舉值2, ...} 變量列表


  • 在定義枚舉類型的時候枚舉元素可以用等號給它賦值,用來代表它的數值,在程序中,不能再次對枚舉元素賦值,因為枚舉元素是常量。
  • 定義一個變量是枚舉類型,可以先定義一個枚舉類型名,然后再說明這個變量是該枚舉類型。

例如: 
enum weekday{sun,mon,tue,wed,thu,fri,sat}; 
定義了一個枚舉類型名 enum weekday,然后定義變量為該枚舉類型。
例如: 
enum weekday day; 
當然,也可以直接定義枚舉類型變量。
例如: 
enum weekday{sun,mon,tue,wed,thu,fri,sat} day; 
其中,sum,mon,…,sat 等稱為枚舉元素或枚舉常量,它們是用戶定義的標識符。


30.文件讀寫and將文件中數據讀進結構體數組

①打開文件


使用fopen可以創建文件,還可以用來打開已經存在的文件、向文件中追加數據或者覆蓋已經存在的文件中的數據,具體是哪種取決於文件的打開方式。


文件打開方式
使用方式 含義
"r" 打開一個文本文件只讀
"w" 打開一個文本文件只寫
"a" 對一個文本文件添加
"rb" 打開一個二進制文件只讀
"wb" 打開一個二進制文件只寫
"ab" 對一個二進制文件添加
"r+" 打開一個文本文件讀/寫
"w+" 生成一個文本文件讀/寫
"a+" 打開一個文本文件讀/寫
"rb+" 打開二進制文件讀/寫
"wb+" 生成二進制文件讀/寫
"ab+" 打開二進制文件讀/寫

②關閉文件


文件一旦使用完畢,應用關閉文件函數把文件關閉,以避免文件的數據丟失等錯誤。

關閉文件通過調用fclose()函數,其一般形式是:    
fclose(文件指針);

正常完成關閉文件操作時,fclose()函數返回值為0。如返回非零值則表示有錯誤發生。


③將文件中數據讀進結構體數組


(1)字符讀寫函數:fgetc和fputc 
(2)字符串讀寫函數:fgets和fputs 
(3)數據塊讀寫函數:fread和fwrite 
(4)格式化讀寫函數:fscanf和fprintf 
ps:使用以上函數都要求包含頭文件stdio.h


1.2 本章學習體會

1.2.1 學習體會

  • 這一段時間電腦總是壞[・`Д´・ ],生氣啊,導致這段時間代碼寫得比較少,比較匆匆忙忙的。
  • 這次PTA中把上次上機考試的題目放了進去,考試時考得很差,結構后來翻回去一寫,也不止當時的分數啊,ε=(´ο`*)))唉,努力學習吧,不過還是有的題不太理解,望老師能在超星平台上多發布些講解視頻。
  • 嵌套的題比較少,一些地方也不知道為什么,運算過程有時候也寫不對,(╯‵□′)╯︵┻━┻,返回return不清楚為什么只返回剛開始輸入的參數
  • 學習了結構之后,發現結構是一個比較好用的東西,(`∀´)ノ亻!可以在里面定義不同類型的變量,引用時也很方便,還可以用typedef來重新換個簡單的名字。
  • 學習文件中,我真的認認真真,仔仔細細地把書看了好幾遍,但是有些代碼還是讀不懂o(╥﹏╥)o,好郁悶,不過,文件的好處在我看來就是使得代碼更條理清晰,就是關於文件的函數有點多,不太好區別。
  • 最后想要說的就是這次的大作業,好難(# ̄…… ̄#)…………具體困難看下面吧......

1.2.2 代碼累計

我的代碼量(不包括重復)

代碼量(行)
4 241
5 506
6 771
7 842
8 793
9 724
10 1980
11 983
12 879
13 545
14 479
15 539
16 721
累計 11224

2.綜合作業--“我愛成語”

2.0題目介紹


本次作業要編寫一個成語游戲。用戶登錄后,系統隨機出若干個成語,如果答對則得分。用戶得分寫入成績文件。系統能對用戶成績排名。


主要功能:

  • 登陸。需要輸入正確用戶名和 密碼,才能登陸系統。錯誤提示錯誤的信息。
  • 成語游戲。從成語文件中隨機抽一個成語,隨機展示2個漢字,用戶猜剩余漢字。如果答對,則得分。錯誤,給相應信息。
  • 排名。系統跟用戶得分排名。
  • 退出。

要求:

  • 本次作業必須建工程實現C的多文件。其中結構體定義、函數定義等都要封裝在自定義頭文件中。一個模塊對應一個.h文件和.c文件。數據定義和數據實現分離。
  • 用戶登錄、排名信息的數據請封裝結構體實現。
  • 涉及3個數據文件user.txt、ranking.txt、idiom.txt
  • 盡量減少全局變量使用,數據傳遞通過地址、參數等傳遞。學會利用函數形參、返回值實現獨立功能。
  • 菜單界面友好,任何一步都能隨時推出,程序也 不會崩潰。程序界面要有清屏。
  • 盡量寫一個函數調試一個函數,保證函數能讀寫文件數據再做下面內容。

數據說明:

  • user.txt :用戶名、密碼
  • ranking.txt:用戶名,答題總分數、最后答題時間。注意:答題分數是每次分數的積累,如答對一題5分,下一次同一個用戶名再玩,這里數據能累加或更新。
  • idiom.txt:成語、成語解釋。注意:給大家數據還包含數字,建議對數據預處理下,把數據改造成規范格式。成語:成語解釋。出現其他如【】、數字等都過濾掉。數據統一格式才好讀寫。

擴展功能:

  • 本題可以做一個成語字典,用戶輸入成語,可以查詢相應成語解釋。這個查詢可以是模糊查詢,就是用戶只輸入一個漢字也可以查詢所有相關的成語內容。
  • 游戲玩法可以多樣,比如也可以做成語接龍,你寫一個成語,根據最后一個漢字,系統能接龍下一個成語。如果是人機互玩,不是接龍規則,可提示。

2.1文件介紹

2.1.1頭文件介紹

idiom.h

  • 結構體
    • 結構體IDIOM:用於存儲成語本身及其釋義
  • 函數
    • 函數ListMenu:主菜單
    • 函數GetChoice:用戶作出選擇
    • 函數GetIdiomData:查看成語及釋義
    • 函數GetIdiomVocabulary:查看成語
    • 函數FillBlanks:成語填字
    • 函數IdiomSolitaire:成語接龍

users.h

  • 結構體
    • 結構體USER:用戶登錄名稱及密碼
  • 函數
    • 函數Landing:用戶輸入賬號及密碼
    • 函數Checking:檢測賬號及密碼是否匹配


2.1.2函數實現文件介紹

文件1:Main.cpp

  • 調用目錄列表函數ListMenu()和用戶做選擇函數GetChoice()

文件2:ListMenu.cpp

  • 定義ListMenu函數輸出菜單,並且調用用戶登錄界面,以及用戶做出選擇
    • ListMenu()函數是主菜單
    • 調用Landing()函數引入賬號和密碼的代碼

文件3:GetChoice.cpp

  • 用戶做出選擇並且調用相應的函數
    • GetChoice()函數輸入選擇


文件4:Function.cpp

  • 用戶選擇后相應的函數進行相應的功能
    • GetIdiomData()函數用來輸出文件中的內容,也就是查看成語及釋義
    • GetIdiomVocabulary()函數是只輸出‘:’前面的成語
    • InPut()函數可以實現在文件中添加成語及其釋義



文件5:FillBlanks.cpp

  • 成語填字游戲的程序
    • FillBlanks()函數用來進行填字游戲



2.2運行結果

2.2.1登錄界面


2.2.2游戲界面


ps:還有一些問題

2.2.3排名界面


ps:還有一些問題

2.3大作業總結

2.3.1碰到問題及解決辦法

  • 在分裝成語和釋義時,剛開始運用老師上課的辦法,會出現亂碼,后來老師重新發了一個分裝的代碼,比較好理解。
  • 在成語填字游戲中不知道如何去挖空,然后通過同學的指導知道了可以在輸出字符串時用‘_’來代替輸出
  • 新增成語時增加的總會把第一個成語代替掉,還沒有找到解決辦法
  • 排名中不知道怎么弄出所用時間

2.3.2小結

  • 在這次的大作業中,我學會了很多,尤其是關於結構體方面的知識,通過幾位同學代表的演示,我清晰地認識到了自己與他人的差距很大,我現在在老師的基礎作業上還有問題的時候,他們已經學會拓展創新,由此,我更需要趕緊向前。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM