C語言博客作業--結構體
一、PTA實驗作業
題目1:結構體數組按總分排序
1. 本題PTA提交列表

2. 設計思路(偽代碼或流程圖)
calc函數
傳入結構體的地址和長度
定義結構體指針,指向傳入的結構體
for p=stu to stu+n
for i=0 to 2
初始化sum為0
end
end
指針返回初始位置
for p=stu to stu+n
for i=0 to 2
累加sum
end
end
sort函數
定義結構體指針stu,和p2作為內循環指針,max指針存放最大sum的變量地址
定義結構體變量作為交換兩變量
for p=stu to stu+n-1
max存p
for p2=p+1 to stu+n-1
如果p2指的變量里的sum大於max指的變量里的sum
交換兩變量的數據
end
end
3.代碼截圖

4.本題調試過程碰到問題及PTA提交列表情況說明。
前幾次提交時少復制了后面的幾個花括號,導致了幾次編譯錯誤
calc函數sum沒有初始化,導致devc++上答案錯誤
解決方法:遍歷結構體的sum,初始化為0
題目2:計算職工工資
1. 本題PTA提交列表

2. 設計思路(偽代碼或流程圖)
struct staff{
char name[100];
double base,flow,put,actual;
};//name為名字,base為基本工資,flow為浮動工資,put為支出,actual為實際工資
定義n為人數,i為循環變量
輸入n
定義結構數組,長度為n
for i=0 to n-1
輸入單個結構的內容
end
for i=0 to n-1
計算實際工資
end
for i=0 to n-1
輸出
end
3.代碼截圖

4.本題調試過程碰到問題及PTA提交列表情況說明。
定義結構體時基本工資,浮動工資,支出定義成了int,計算的結果卻放到了浮點型的變量里,輸出結果用的是%f,用函數寫是編譯錯誤,去掉函數就變成答案錯誤。

解決方法:改變定義的類型

題目3:通訊錄的錄入與顯示
1. 本題PTA提交列表

2. 設計思路(偽代碼或流程圖)
struct list{
char name[100];
char birthday[100];
char sex;
char tel[100];
char mobil[100];
};//name表示名字,birthday生日,sex性別,tel電話,mobil手機
定義為存入信息數,i為循環變量,num為查找信息編號,n2查找個數
輸入n
定義結構體數組lis【n】
for i=0 to n-1
輸入信息
end
輸入查找信息個數
for i=0 to n2-1
輸入查找信息的編號
如果編號在可用范圍內,輸出信息
否則輸出沒找到
end
3.代碼截圖

4.本題調試過程碰到問題及PTA提交列表情況說明。
答案錯誤:輸出時信息的位置放錯了
解決方法:調整了信息的位置輸出
部分正確:定義電話的時后給的長度不夠
解決方法:加大了電話的數組長度
二、截圖本周題目集的PTA最后排名

三、閱讀代碼
- 編一程序,用指針數組在主函數中輸入十個等長的字符串。用另一函數對它們排序,然后在主函數中輸出10個已排好序的字符串
#include<stdio.h>
#include<string.h>
void sort(char *[]);
int main()
{
int i;
char str[10][6], *p[10];
printf("please input 10 string:/n");
for(i=0;i<10;i++)//首先將10個str的首地址賦值給10個p[i];
p[i]=str[i];//將第i個字符串的首地址賦予指針數組p的第i個元素;
for(i=0;i<10;i++)
scanf("%s",p[i]);//scanf輸入到&p[i]
sort(p);
printf("the output 10 string:/n");
for(i=0;i<10;i++)
printf("%s/n",p[i]);//輸出到p[i];
}
void sort(char *s[])
{
char *temp; int i,j;
for(i=0;i<9;i++)
for(j=0;j<9-i;j++)
if(strcmp(*(s+j),*(s+j+1))>0) {
temp=*(s+j);//*(s+j)指向數組指針,我想應該是字符串的首地址;所以可以直接賦值給temp指針;
*(s+j)=*(s+j+1);
*(s+j+1)=temp;
}
}
這道題指針的做法很有借鑒價值,將第i個字符串的首地址賦予指針數組p的第i個元素,后續就不用再拿二維數組的地址來用,簡化程序,提高可讀性。
- 有n個結構體變量,內含學生學號、姓名和3門課程的成績。要求輸出平均成績最高的學生的信息(包括學號、姓名、3門課程成績和平均成績)。
#include<stdio.h>
#define N 3 //學生數為3
struct student
{
long num;
char name[20];
int score[3];
float aver;
}stu[N];
int main()
{
void input(struct student stu[]);
struct student max(struct student stu[]);
void print(struct student stu);
struct student *p=stu;
input(p);
print(max(p));
return 0;
}
void input(struct student stu[])
{
int i;
printf("請輸入%d個學生的信息(學號、姓名、三門課成績):\n",N);
for(i=0;i<N;i++)
{
scanf("%ld %s %d %d %d",&stu[i].num,stu[i].name,&stu[i].score[0],&stu[i].score[1],&stu[i].score[2]);
stu[i].aver=(stu[i].score[0]+stu[i].score[1]+stu[i].score[2])/3.0;
}
}
struct student max(struct student stu[])
{
int i,m=0;
for(i=1;i<N;i++)
if(stu[i].aver>stu[m].aver) m=i;
return stu[m];
}
void print(struct student stu)
{
printf("\n成績最高的學生是:\n");
printf("學號:%ld\n姓名:%s\n三門課成績:%d %d %d\n平均成績:%5.2f\n\n",
stu.num,stu.name,stu.score[0],stu.score[1],stu.score[2],stu.aver);
}
這道題使用了結構體,但是我覺得更好的地方是用函數來分裝代碼,整個結構很好,值得借鑒。
四、本周學習總結
1.總結本周學習內容。
結構體、共用體、枚舉這種構造數據類型特點。
結構體
struct 結構體名
{
成員表列
} 變量表列;
例:
struct data{
int a;
char b;
double c;
} s1;
結構體變量就像數組一樣,但是不同於數組的是,他內部的元素可以不同,而且結構體內部還可以嵌套,這對於數據的分類管理就起到很大作用。
共用體
union 共用體名
{
成員表列
} 變量表列;
列:
union data
{
int i;
char ch;
float f;
} a, b, c;
1.同一個內存段可以用來存放幾種不同類型的成員,但是在每一瞬間只能存放其中的一種,而不是同時存放幾種。
2.共用體變量中起作用的成員是最后一次存放的成員,在存入一個新成員后,原有成員就失去作用。
3.共用體變量的地址和它的各成員的地址都是同一地址。
4.不能對共用體變量名賦值,也不能企圖引用變量名來得到一個值。
5.共用體類型可以出現在結構體類型的定義中,也可以定義共用體數組。反之,結構體也可以出現在共用體類型的定義中,數組也可以作為共用體的成員。
6.共用體變量的初始化。
(1)union data a=b; //把共用體變量初始化為另一個共用體
(2)union data a={123}; //初始化共用體為第一個成員
(3)union data a={.ch='a'}; //指定初始化項目,按照C99標准
7.共用體變量也可以作為函數的參數和返回值。
共用體的使用大大降低編程時內存的占用,但是使用時也要格外小心,不同於結構體數據所占內存不同,共同體占的內存相同,取值只取最后存放的數,所以使用時要注意。
此外結構體與共用體的定義方式差不多,可以結合起來記憶。
枚舉
enum 枚舉名{
標識符[=整型常數],
標識符[=整型常數],
...
標識符[=整型常數]
} 枚舉變量;
例:
enum weekday{sun,mon,tue,wed,thu,fri,sat};
如果枚舉沒有初始化,即省掉"=整型常數"時, 則從第一個標識符開始,順次賦給標識符0, 1, 2, ...。但當枚舉中的某個成員賦值后,其后的成員按依次加1的規則確定其值。
例如下列枚舉說明后,x1, x2, x3, x4的值分別為0, 1, 2, 3。enum Num{x1, x2, x3, x4}x;
當定義改變成
enum Num
{
x1,
x2=0,
x3=50,
x4
}x;
則x1=0, x2=0, x3=50, x4=51
-
枚舉中每個成員(標識符)結束符是"," 不是";", 最后一個成員可省略","。
-
初始化時可以賦負數, 以后的標識符仍依次加1。
-
枚舉變量只能取枚舉說明結構中的某個標識符常量。
-
枚舉值是常量,不是變量。不能在程序中用賦值語句再對它賦值。例如對枚舉weekday的元素再作以下賦值: sun=5;mon=2;sun=mon; 都是錯誤的。
-
枚舉元素本身由系統定義了一個表示序號的數值,從0 開始順序定義為0,1,2…。如在weekday中,sun值為0,mon值為1, …,sat值為6。
-
只能把枚舉值賦予枚舉變量,不能把元素的數值直接賦予枚舉變量。如: a=sun;b=mon; 是正確的。而: a=0;b=1; 是錯誤的。如一定要把數值賦予枚舉變量,則必須用強制類型轉換,如: a=(enum weekday)2;其意義是將順序號為2的枚舉元素賦予枚舉變量a,相當於: a=tue; 還應該說明的是枚舉元素不是字符常量也不是字符串常量, 使用時不要加單、雙引號。
相比於結構體或共同體,枚舉的定義方法有點類似,但有很大區別,如2所提到,以及系統定義數值要非常注意;枚舉的使用方便了常量的使用,使代碼可讀性大大提高。
遞歸函數原理:
遞歸(recursion)就是子程序(或函數)直接調用自己或通過一系列調用語句間接調用自己,是一種描述問題和解決問題的基本方法。
遞歸通常用來解決結構自相似的問題。所謂結構自相似,是指構成原問題的子問題與原問題在結構上相似,可以用類似的方法解決。具體地,整個問題的解決,可以分為兩部分:第一部分是一些特殊情況,有>直接的解法;第二部分與原問題相似,但比原問題的規模小。實際上,遞歸是把一個不能或不好解決的大問題轉化為一個或幾個小問題,再把這些小問題進一步分解成更小的問題,直至每個小問題都可以直接
解決。因此,遞歸有兩個基本要素:
(1)邊界條件:確定遞歸到何時終止,也稱為遞歸出口。
(2)遞歸模式:大問題是如何分解為小問題的,也稱為遞歸體。遞歸函數只有具備了這兩個要素,才能在有限次計算后得出結果
在遞歸函數中,調用函數和被調用函數是同一個函數,需要注意的是遞歸函數的調用層次,如果把調用遞歸函數的主函數稱為第0層,進入函數后,首次遞歸調用自身稱為第1層調用;從第i層遞歸調用自身稱>為第i+1層。反之,退出第i+1層調用應該返回第i層。
遞歸函數的內部執行過程:
一個遞歸函數的調用過程類似於多個函數的嵌套的調用,只不過調用函數和被調用函數是同一個函數。為了保證遞歸函數的正確執行,系統需設立一個工作棧。具體地說,遞歸調用的內部執行過程如下:
(1)運動開始時,首先為遞歸調用建立一個工作棧,其結構包括值參、局部變量和返回地址;
(2)每次執行遞歸調用之前,把遞歸函數的值參和局部變量的當前值以及調用后的返回地址壓棧;
(3)每次遞歸調用結束后,將棧頂元素出棧,使相應的值參和局部變量恢復為調用前的值,然后轉向返回地址指定的位置繼續執行。
總之,遞歸函數就是將一個復雜的問題分解成幾個相似的小問題,調用函數來解決問題。只需考慮問題的分解,及分解到邊界時如何解決即可,其他部分交給計算機來解決。
2.羅列本周一些錯題。
對於以下結構定義,(*p)->str++中的++加在()。 (2分)
struct { int len; char\ *str; } *p;
A、
指針str上
B、
指針p上
C、
str指向的內容上
D、
語法錯誤
答案:d 錯選:c
分析:*p已經是內容,不能->,如果是p->str++,則++加在指針str上
線性表用順序實現。請填空寫一個求線性表L 中所有奇數之和的算法。
例如:
L=(1,2,3,4,5) 其和為 9(本題結構體定義很不錯。)
#include <stdio.h>
#define N 10
typedef struct sqlist
{
int data[N];
int last;
}LIST;
int Total(List list)
{
return sum;
}
void Show(LIST list)
{
int i;
for(i=0;i<=list.last;i++)
printf("%3d", list.data[i]);
printf("\n");
}
int main()
{
LIST list;
int i,sum;
for(i=0;i<=5;i++)
list.data[i]=i;
list.last=5;
Show(list);
sum=Total(list);
printf("sum=%3d\n",sum);
return 0;
}
參考答案
int sum=0;
for(int i=0;i<=list.last;i++)
if(list.data[i]%2)
sum+=list.data[i];
我的作答
int sum=0,i;
for(i=0;i<list.last;i+=2){
sum+=list.data[i];
}
分析,沒看清楚題目,題目要的是奇數的和,不是下標
