嘿,各位!
Long time no see!
不知不覺地又拖了這麼久......
少說費話,就直接開始吧!
先看看這裏:
博主的編譯環境:(我也推薦大家用Visual Studio 編碼)
VS2017 community
運行環境:
Windows 10
如果不想直接複製的朋友可以從下面的連接裏直接獲取源碼 :
鏈接:https://pan.baidu.com/s/1YOAMrXZm5Jb3A-LgZBwLEA
提取碼:uh57
還有一點得說的,在上一篇博客裏,引用代碼塊有時實在是太長了,
而且以後編寫的代碼量肯定還會更長,所以博主以後都直接用塊引用來放置代碼.
所以從美感上可能說不了什麼了.......當然博主會盡量做到優質的代碼規範
源碼 + 題目 + 運行效果:
P14-1:
/*
14.1 重新編寫複習題 5,用月份名的拼寫代替月份號(別忘了使用strcmp() )。在一個簡單的程序中測試該函數。
*/
#include <stdio.h>
#include <string.h>
#include <ctype.h>#define LENTH 20 //月份名的長度
#define MONTHNUM 12 //12 個月份//月份結構
typedef struct month
{
char month_name[LENTH]; //月份名
char m_name[4]; //月份的縮寫
int days; //月份的天數
}MONTH;//獲取一個月份名
char * Get_Month_Name(char * buf, int lenth);//將字符串轉換成小寫
char * change_into_low(char * string);//從結構中查找月份值,並打印出來
void Chr_Month(struct month * months, int total_month, char * name);//返回一年中到該月爲止(包括該月)的總天數
int total_days_from(MONTH * months, int monthnumber);
int main(void)
{
char name[LENTH] = { '\0' }; //儲存輸入,初始化爲空串//初始化十二個月份,這裏用小寫是爲了方便比較字符串
MONTH months[MONTHNUM] =
{
{"january", "jan", 31},
{"february", "feb", 28},
{"march", "mar", 31},
{"april", "apr", 30},
{"may", "may", 31},
{"june", "jun", 30},
{"july", "jul", 31},
{"august", "aug", 31},
{"september", "sep", 30},
{"october", "otc", 31},
{"november", "nov", 30},
{"december", "dec", 31}
};
//提示用戶輸入1 個月份名
printf("Please enter a month name (q to quit): ");
while (Get_Month_Name(name, LENTH) != NULL)
{
//將輸入轉換成小寫
change_into_low(name);//從結構中查找月份值,並打印出來
Chr_Month(months, MONTHNUM, name);//提示用戶輸入1 個月份名
printf("Please next month name (q to quit): ");
}printf("Bye!\n");
return 0;
}//獲取一個月份名
char * Get_Month_Name(char * buf, int lenth)
{
while (gets_s(buf, LENTH) == NULL || buf[0] == '\0')
{
printf("That's not a value string, try again: ");
continue;
}
if (buf[0] == 'q') //輸入q 以結束程序
return NULL;return buf;
}//將字符串轉換成小寫
char * change_into_low(char * string)
{
while (*string)
{
*string = tolower(*string);
string++;
}return string;
}//從結構中查找月份值,並打印出來
void Chr_Month(struct month * months, int total_month, char * name)
{
for (int ct = 0; ct < total_month; ct++)
{
//查詢對應的月份值
if (strcmp(name, months[ct].month_name) == 0)
{
if (ct + 1 == 1) //如果輸入的是1 月
{
printf("January has %d days.\n", months[0].days);
}
else //輸入的是其他月份
{
printf("There are %d days from %s to %s.\n",
total_days_from(months, ct + 1), months[0].month_name, name);
}
break;
}
//輸入不屬於任何月份
else if (ct + 1 == total_month)
printf("Sorry, there isn't a month named %s\n", name);
}
}//返回一年中1月到 n 月爲止(包括該月)的總天數
int total_days_from(MONTH * months, int monthnumber)
{
int total = 0;
int ct = 0; //count縮寫
for (ct = 1; ct <= monthnumber; ct++)
{
total += months[ct - 1].days;
}
return total;
}
P14-2:
/*
14.2 編寫一個函數,提示用戶輸入日,月。月份可以是月份號,月份名或月份名縮寫。然後該程序應返回
一年中到用戶指定的日子(包括這一天)的總天數
*/
#include <stdio.h>
#include <stdlib.h> //atoi()函數
#include <string.h> //strcmp()函數
#include <ctype.h> //tolower()函數#define LENTH 40 //月份名的最大長度
#define MONTHNUM 12 //12 個月份//月份結構
typedef struct month
{
char month_name[LENTH]; //月份名
char m_name[4]; //月份的縮寫
int days; //月份的天數
int month_n; //月份號
}MONTH;//用戶輸入 結構
struct info
{
char month_name[LENTH]; //月份名(縮寫或者全稱)/月份號
char year[10]; //這倆個使用char類型
char days[10]; //是爲了後面好一口氣轉換成int類型
};//查找兩個空格 格式爲月 日 年之間有兩個空格
int chr_two_spaces(char * string, int length);//獲取年月日信息
char * Get_info(char * buf, int lenth);//將字符串轉換成小寫
char * change_into_low(char * string);//分割用戶的輸入
struct info divide_info(struct info message, char * buf);//返回一年中到該月爲止(包括該月)的總天數
int total_days_from(MONTH * months, int monthnumber);//判斷傳入的字符是否是數字
int judge_digit(char ch);//從結構中查找月份值,並打印出來
void Chr_Month(struct month * months, int total_month, struct info message);int main(void)
{
char info[LENTH] = { '\0' }; //儲存用戶輸入,初始化爲空串
struct info message = //初始化所以信息爲0
{
{'\0'},{'\0'}, {'\0'}
};//初始化十二個月份,這裏用小寫是爲了方便比較字符串
MONTH months[MONTHNUM] =
{
{"january", "jan", 31, 1},
{"february", "feb", 28, 2},
{"march", "mar", 31, 3},
{"april", "apr", 30, 4},
{"may", "may", 31, 5},
{"june", "jun", 30, 6},
{"july", "jul", 31, 7},
{"august", "aug", 31, 8},
{"september", "sep", 30, 9},
{"october", "otc", 31, 10},
{"november", "nov", 30, 11},
{"december", "dec", 31, 12}
};//提示用戶輸入1 個月份名
printf("Please enter a month name, the days and the year, like 10 21 2018 (q to quit): ");
while (Get_info(info, LENTH) != NULL)
{
//分割用戶的輸入
message = divide_info(message, info);//將輸入轉換成小寫
change_into_low(message.month_name);//從結構中查找月份值,並打印出來
Chr_Month(months, MONTHNUM, message);//提示用戶下一個月份名
printf("Please next month name (q to quit): ");
}printf("Bye!\n");
return 0;
}//查找兩個空格
int chr_two_spaces(char * string, int length)
{
int count = 0, i = 0;
while (*string++ != '\0')
{
if (*string == ' ')
count++;
}if (count != 2)
return 0;
else
return 1;
}
//獲取一個月份名
char * Get_info(char * buf, int lenth)
{
while (gets_s(buf, LENTH) == NULL || buf[0] == '\0'
|| buf[0] == ' ' || chr_two_spaces(buf, LENTH) == 0) //處理一些非法輸入
{
if (buf[0] == 'q') //輸入q 以結束程序
return NULL;
//反之提示重新輸入
printf("That's not a value string, try again: ");
continue;
}return buf;
}//將字符串轉換成小寫
char * change_into_low(char * string)
{
while (*string)
{
*string = tolower(*string);
string++;
}return string;
}//分割用戶的輸入
struct info divide_info(struct info message, char * buf)
{
int count = 0, i = 0;//分割月份
while (buf[count] != ' ')
{
message.month_name[i++] = buf[count++];
}
i = 0;
count++;//分割日期
while (buf[count] != ' ')
{
message.days[i++] = buf[count++];
}
i = 0;
count++;//分割年份
while (buf[count] != '\0')
{
message.year[i++] = buf[count++];
}
return message;
}//返回一年中1月到 n 月爲止(包括該月)的總天數
int total_days_from(MONTH * months, int monthnumber)
{
int total = 0;
int ct = 0; //count縮寫
for (ct = 0; ct < monthnumber; ct++)
{
total += months[ct].days;
}
return total;
}//判斷傳入的字符是否是數字
int judge_digit(char ch)
{
if (ch >= '0' && ch <= '9')
return ch - '0';
else
return 0;
}//從結構中查找月份值,並打印出來
void Chr_Month(struct month * months, int total_month, struct info message)
{
int flag = 0; //月份未找到的標記
int num_of_month = atoi(message.month_name); //獲取月份號
int num_of_days = atoi(message.days); //獲取該月已經過去的天數
int num_of_year = atoi(message.year); //獲取當前年號if (num_of_month< 0 || num_of_month> 12) //非法月份
{
printf("The number of the month is invalid.\n");
flag = 1;
return;
}
if (num_of_days < 0 || num_of_days > 31) //非法天數
{
printf("The number of the days is invalid.\n");
return;
}
if (num_of_year < 0) //非法年數
{
printf("The number of the year is invalid.\n");
return;
}for (int ct = 0; ct < total_month; ct++)
{
//輸入的是月份名
if (strcmp(message.month_name, months[ct].month_name) == 0)
{
printf("%d has passed %d days.\n", num_of_year, num_of_days + total_days_from(months, ct));
flag = 1;
break;
}
//如果輸入的是縮寫
else if (strcmp(message.month_name, months[ct].m_name) == 0)
{
printf("%d has passed %d days.\n", num_of_year, num_of_days + total_days_from(months, ct));
flag = 1;
break;
}
//如果是輸入的是月份號
else if (num_of_month != 0) //檢查首字符爲數字 (如果首字符不是數字,則這裏應該是0 )
{
printf("%d has passed %d days.\n", num_of_year, num_of_days + total_days_from(months, num_of_month - 1));
flag = 1;
break;
}
}
if (flag == 0)
printf("The number of the month is invalid.\n");
}
P14-3:
/*
14.3 修改程序清單14.2中的圖書目錄程序,使其按照輸入圖書的順序輸出圖書的信息,
然後按照標題字母的聲明輸出圖書,最後按照價格的升序輸出圖書的信息1)按照輸入圖書的順序輸出圖書的信息
2)按照字母表順序輸出圖書的信息
3)按照價格的升序輸出圖書的信息
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>#define MAXTITLE 40
#define MAXAUTL 40
#define MAXBKS 100 //書籍的最大數量//建立 book 模板
struct book
{
char title[MAXTITLE];
char author[MAXAUTL];
float value;
};//接收輸入函數
char * s_gets(char * st, int n);//拷貝原始數據
void CopySource(struct book * target, struct book * source, int count);//輸出圖書的信息
void ShowInfo(const struct book * Pbook, int count);//將輸入圖書的順序按照標題字母的聲明順序排序
void TitleOrder(struct book * Pbook, int count);//將輸入圖書的順序按照價格的升序輸出圖書
void PriceOrder(struct book * Pbook, int count);int main(void)
{
struct book library[MAXBKS]; // book 類型結構的數組
struct book temp[MAXBKS]; //儲存原始數據的克隆體
int count = 0;printf("Please enter the book title.\n");
printf("Press [entet[ at the start of a line to stop.\n");
while (count < MAXBKS && s_gets(library[count].title, MAXTITLE) != NULL
&& library[count].title[0] != '\0') //獲取書名
{
printf("Now enter the author.\n"); //獲取作者名稱
s_gets(library[count].author, MAXAUTL);printf("Now enter the value.\n");
scanf_s("%f", &library[count].value); //獲取價格count++; //遞增
while (getchar() != '\n')
continue; //清理輸入行
if (count < MAXBKS)
printf("Enter the next title.\n");
}
//結束輸入後
if (count > 0)
{
CopySource(temp, library, count); //拷貝一份數據,用於保存原始數據printf("Here is the list of your books(by root order): \n");
ShowInfo(temp, count); //按原有的順序輸出信息
putchar('\n');printf("Here is the list of your books(by title order): \n");
TitleOrder(temp, count); /* 將結構按照標題進行排序 */
ShowInfo(temp, count); //按標題順序輸出信息
putchar('\n');printf("Here is the list of your books(by price order): \n");
PriceOrder(temp, count); /* 將結構按照價格升序進行排序 */
ShowInfo(temp, count);
putchar('\n');//printf("Here is the list of your books(by root order): \n");
//ShowInfo(library, count); //按原有的順序輸出信息(這段代碼可要可不要)
}
else
{
printf("No books? Too bad.\n");
}return 0;
}//接收輸入函數
char * s_gets(char * st, int n)
{
char * ret_val;
char * find;ret_val = fgets(st, n, stdin);
if (ret_val != NULL)
{
find = strchr(st, '\n'); //查找換行符
if (find != NULL) //如果地址不是NULL
*find = '\0'; //在此放置一個空字符
else
{
while (getchar() != '\n')
continue;
}
}
return ret_val;
}//拷貝原始數據
void CopySource(struct book * target, struct book * source, int count)
{
for (int i = 0; i < count; i++)
{
target[i] = source[i];
}
}//輸出圖書的信息
void ShowInfo(const struct book * Pbook, int count)
{
int index;
for (index = 0; index < count; index++)
{
printf("%s by %s: $%.2f\n", Pbook[index].title, Pbook[index].author, Pbook[index].value);
}
return;
}//將輸入圖書的順序按照標題字母的聲明順序排序(使用冒泡排序)
void TitleOrder(struct book * Pbook, int count)
{
struct book temp;
int top, seek; //使用冒泡排序算法for (top = 0; top < count; top++)
{
for (seek = top + 1; seek < count; seek++)
{
if (strcmp(Pbook[top].title, Pbook[seek].title) > 0)
{
temp = Pbook[top]; //直接將兩個結構進行交換!!!
Pbook[top] = Pbook[seek]; //原本想用指針數組進行排序的,結果發現不會.....
Pbook[seek] = temp;
}
}
}
}//將輸入圖書的順序按照價格的升序輸出圖書
void PriceOrder(struct book * Pbook, int count)
{
struct book temp;
int top, seek; //使用冒泡排序算法for (top = 0; top < count - 1; top++)
{
for (seek = top + 1; seek < count; seek++)
{
if (Pbook[top].value > Pbook[seek].value)
{
temp = Pbook[top]; //交換這兩個結構
Pbook[top] = Pbook[seek];
Pbook[seek] = temp;
}
}
}
}
輸入:
效應:
P14-4:
/*
14.4 編寫一個程序,創建一個有兩個成員的結構模板
a. 第一個成員是社會保險號,第2個成員是一個有三個成員的結構,第一個成員代表名,第2個成員代表中間名,
第三個成員名錶示姓。創建並初始化一個內含5個類型結構的數組。該程序以下面的格式打印數據:
Dribble, Flossie M. -- 302039823
如果有中間名,只打印它的第1個字母,後面加一個點(.);如果沒有中間名,則不用打印點。編寫
一個程序進行打印,把結構數組傳遞給這個函數。b. 修改a部分,傳遞結構的值而不是結構的地址
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>#define MAXLINE 60 //名稱的最大長度
#define MAXSSN 12 //社會保險號最大長度
#define ROWS 5 //五個元素的結構數組//建立name的結構模板------名+姓+中間名
struct name
{
char firstname[MAXLINE]; //名
char middlename[MAXLINE]; //中間名
char lastname[MAXLINE]; //姓
};//建立信息模板-----社會保險號+擁有人
struct Message
{
char ssn[MAXSSN]; //社會保險號
struct name owner; //擁有人
};//打印5個結構信息(A)
void Outtext_A(struct Message info[], int count);//打印結構信息(B)
void Outtext_B(struct Message info);int main(void)
{
//初始化一個結構
struct Message info[ROWS] =
{
{"000000001", {"Alex", "", "Mercer"}},
{"000000002", {"John", "", "Johnson"}},
{"000000003", {"Nancy", "Nick", "Kali"}},
{"000000004", {"Maria", "Lose", "Nin"}},
{"000000005", {"Alice", "Rom", "Geer"}},
};printf("Print by method a:\n"); //以方案A打印
Outtext_A(info, ROWS);printf("Print by method b:\n"); //以方案B打印
for (int i = 0; i < ROWS; i++)
{
Outtext_B(info[i]);
}return 0;
}//打印5個結構信息(A)
void Outtext_A(struct Message info[], int count)
{
int i = 0;
for (i = 0; i < count; i++)
{
printf("%-5s, %-5s ", info[i].owner.firstname, info[i].owner.lastname);
if (info[i].owner.middlename[0] != '\0')
{
printf("%c.", info[i].owner.middlename[0]);
}
printf(" -- %-10s\n", info[i].ssn);
putchar('\n');
}
putchar('\n');
}//打印結構信息(B)
void Outtext_B(struct Message info)
{
printf("%-5s, %-5s ", info.owner.firstname, info.owner.lastname);
if (info.owner.middlename[0] != '\0')
{
printf("%c.", info.owner.middlename[0]);
}
printf(" -- %-10s\n", info.ssn);
putchar('\n');
}
P14-5:
/*
14.5 ----- 編寫一個程序滿足下面的要求:
a. 外部頂一個有兩個成員的結構模板name: 一個字符串儲存名,一個字符串儲存姓。
b. 外部定義一個有3個成員的結構模板student:一個name類型的結構,一個
grade 數組儲存3個浮點型 分數,一個變量儲存三個分數的平均數。
c. 在main()函數中聲明一個內含CSIZE (CSIZE = 4) 個student類型結構的數組,並初始化
這些結構的名字部分。用函數執行g,e,f 和 g 中描述的任務。
d. 以交互的方式獲取每個學生的成績,提示用戶輸入學生的姓名和分數。把分數儲存到grade
數組相應的結構中。可以在main() 函數或其他函數中循環來完成。
e. 計算每個結構的平均分,並把計算後的值賦給合適的成員。
f. 打印每個結構的信息。
g. 打印班級的平均分,即所有結構的數值成員的平均值
*/
#include <stdio.h>
#define MAXLEN 30 //姓名的最大長度
#define CSIZE 4 //建立4個student類型的結構//建立name結構模板 ----名和姓
struct name
{
char fname[MAXLEN];
char lname[MAXLEN];
};//建立student結構模板 ----name +三個分數 + 平均值
struct student
{
struct name name;
double grade[3];
double Average;
};//獲取學生的分數
void GetGrade(struct student info[], int count);//計算每個學生的平均分
void GetAverage(struct student info[], int count);//打印每個學生的信息
void OutInfo(struct student info[], int count);//打印班級的平均分(因爲每個學生的平均分已經計算過,所以只需再次平分四次的平均分就行)
void OutAverage(struct student info[], int count);int main(void)
{
//初始化三個學生的姓名
struct student info[CSIZE] =
{
{{"Alex", "Mercer"}},
{{"Nick", "Joen"}},
{{"Jane", "Kali"}},
{{"Joen", "DIss"}}
};
//獲取學生的成績
GetGrade(info, CSIZE);
//獲取每個學生的平均分
GetAverage(info, CSIZE);
//打印每個學生的信息
OutInfo(info, CSIZE);
//打印班級的平均分
OutAverage(info, CSIZE);
return 0;
}//獲取學生的分數
void GetGrade(struct student info[], int count)
{
for (int i = 0; i < count; i++)
{
printf("What's the mark of %s %s?\n", info[i].name.fname, info[i].name.lname);
while (scanf_s("%lf %lf %lf", &info[i].grade[0], &info[i].grade[1], &info[i].grade[2]) != 3)
{
printf("That's not invatid! Try again:\n");
continue;
}
}
printf("\n");
}//計算每個學生的平均分
void GetAverage(struct student info[], int count)
{
for (int i = 0; i < count; i++)
{
//獲取三科的平均分
info[i].Average = (info[i].grade[0] + info[i].grade[1] + info[i].grade[2]) / 3;
}
}//打印每個學生的信息
void OutInfo(struct student info[], int count)
{
for (int i = 0; i < count; i++)
{
printf("The mark of %s %s is %.2f %.2f and %.2f.\n", info[i].name.fname,
info[i].name.lname, info[i].grade[0], info[i].grade[1], info[i].grade[2]);printf("And the average mark is %.2f.\n", info[i].Average);
printf("\n");
}
}//打印班級的平均分
void OutAverage(struct student info[], int count)
{
double average = 0;
for (int i = 0; i < count; i++)
{
average += info[i].Average;
}printf("The average mark of all is %.2f.\n", average / 4);
}
P14-6:
/*
14.6 ---- 題目太長,就不打了
*/
#include <stdio.h>
#include <stdlib.h> //exit()函數原型#define NAMELINE 30 //球員名的最大長度
#define PLAYERNUM 19 //總計18名球員,爲了方便計數,這裏使用19個
#define FILENAME "Info.txt" //待打開的文件名
#define MAXLINE 256 //每一行可讀取的最大長度
//建立baseball_er 球員信息模板
struct baseball_er
{
//球員號就是結構數組的下標
char PlayerFname[NAMELINE]; //球員名
char PlayerLname[NAMELINE]; //球員姓
int haveBeOnRace; //上場次數
int hitNum; //擊球數
int walkNum; //走壘數
int rbi; //打點數
double average; //安打率
};//將結構內的所有成員初始化爲0
void initStruct(struct baseball_er * player);//獲取一行的數據,返回球員號
int GetLine(FILE * fp, struct baseball_er * player);//把當前行的數據寫入結構內
void write_to_struct(struct baseball_er * target, struct baseball_er * temp);//計算安打率
void GetAverage(struct baseball_er players[], int num);//打印全體球員信息
void PrintAll(struct baseball_er players[], int num);int main(void)
{
//創建一個結構數組-----存儲球員信息
struct baseball_er players[PLAYERNUM];//創建一個baseball_er結構temp
struct baseball_er temp;//fopen_s()返回該類型
errno_t err = 0;
FILE * fp; //文件指針//儲存文件中每一行的數據
char line[MAXLINE] = { '\0' };//儲存當前行的球員號
int PlayerNum = 0;
int times = 0; //循環計數變量//將所有結構成員都初始化爲0
for (int i = 0; i < PLAYERNUM; i++)
{
initStruct(&players[i]);
}
//初始化temp結構
initStruct(&temp);//以只讀模式打開文件
if (err = fopen_s(&fp, FILENAME, "r") != 0)
{
printf("The file '%s' was not opened\n", FILENAME);
exit(EXIT_FAILURE);
}//讀取數據,直到文件結尾
while (feof(fp) == 0)
{
//讀取一行數據
PlayerNum = GetLine(fp, &temp);//把當前行的數據寫入結構內
write_to_struct(&players[PlayerNum], &temp);
}
//計算安打率
GetAverage(players, PLAYERNUM);//打印出所有球員信息
PrintAll(players, PLAYERNUM);fclose(fp);
return 0;
}//將結構內的所有成員初始化爲0
void initStruct(struct baseball_er * player)
{
player->PlayerFname[0] = '\0';
player->PlayerLname[0] = '\0';
player->haveBeOnRace = 0;
player->hitNum = 0;
player->walkNum = 0;
player->rbi = 0;
player->average = 0;
return;
}//獲取一行的數據,返回球員號
int GetLine(FILE * fp, struct baseball_er * temp)
{
int num = 0;//讀取一行數據
fscanf_s(fp, "%d", &num);
fscanf_s(fp, "%s", temp->PlayerFname, NAMELINE);
fscanf_s(fp, "%s", temp->PlayerLname, NAMELINE);
fscanf_s(fp, "%d", &temp->haveBeOnRace);
fscanf_s(fp, "%d", &temp->hitNum);
fscanf_s(fp, "%d", &temp->walkNum);
fscanf_s(fp, "%d", &temp->rbi);return num;
}//把當前行的數據寫入結構內
void write_to_struct(struct baseball_er * target, struct baseball_er * temp)
{
//如果該球員還未寫入過數據
if (target->PlayerFname[0] == '\0')
{
*target = *temp;
}
else
{
target->haveBeOnRace += temp->haveBeOnRace;
target->hitNum += temp->hitNum;
target->walkNum += temp->walkNum;
target->rbi += temp->rbi;
}
return;
}//計算安打率 累計擊中數除以上場次數
void GetAverage(struct baseball_er players[], int num)
{
for (int i = 1; i < num; i++)
{
if (players[i].PlayerLname[0] != '\0')
{
(players[i].average) = (double)players[i].hitNum / players[i].haveBeOnRace;
}
}
}//打印全體球員信息
void PrintAll(struct baseball_er players[], int num)
{
printf("Order \t First name \t Last name \t have been on race \t hitNum \t walkNum \t RBI \t average\n");for (int i = 1; i < num; i++)
{
if (players[i].PlayerFname[0] != '\0')
{
printf("%d) \t %s %15s \t %20d \t\t %d \t\t %d \t\t %d \t\t %.2f \n", i, players[i].PlayerFname, players[i].PlayerLname,
players[i].haveBeOnRace, players[i].hitNum, players[i].walkNum, players[i].rbi, players[i].average);
}
}return;
}
P14-7:
/*
14-7----修改程序清單 14.14,從文件中讀取每條記錄並顯示出來,允許用戶刪除記錄或修改記錄的內容。
如果刪除記錄把空出來的空間留給下一個要讀入的記錄。要修改現有的文件內容,必須用“r + b”模式,
而不是“a + b”模式。而且必須更加註意定位文件指針,防止新加入的記錄覆蓋現有記錄。
最簡單的方法是改動儲存在內存中的所有數據,然後再把最後的信息寫入文件。跟蹤的一個方法是在
book結構中添加一個成員表示是否該項被刪除。
*/
這次源碼有點長,有需要的可以直接去上面的連接下載
頭文件:Functions_name.h
#pragma once
/************頭文件********************/
#include <stdio.h>
#include <stdlib.h> //提供exit()函數原型
#include <string.h> //提供strchr()函數原型
#include <stdbool.h> //提供bool類型
#include <conio.h> //提供getch_()函數原型
/*************************************//************************宏定義*****************************/
#define MAXTITL 40 /* 最大書籍名稱長度 */
#define MAXAUTL 40 /* 最大作者名稱長度 */
#define MAXBKS 10 /* 最大書籍數量 */
#define FILENAME "Info.txt" //保存文件名 名稱
/***********************************************************/
//建立 book 結構
typedef struct book
{
char title[MAXTITL]; //書名
char author[MAXAUTL]; //作者
double value; //價格
}BOOK;
/****************************函數原型***************************************/
//打開文件----失敗則直接退出程序
void Open_File(char const * fname, char const * mode, FILE ** fp);//讀取文件信息
int Read_File(BOOK * book, FILE * fp);//刪除字符串中的換行符
void Delete_n(char * string, int length);//打印菜單
void PrintMenu(void);//獲取用戶的選項輸入
int Get_Choice(void);//獲取字符串輸入
char * s_gets(char * st, int n);//檢驗文件是否已滿----如已滿,則直接退出程序
void File_IsFull(int bookNum);//添加新書--------返回總書籍數目
int Get_Newbook(BOOK library[], int bookNum);//打印所有書籍信息
void Print_books(BOOK library[], int bookNum);//把所有書籍信息寫入文件
void Write_to_File(BOOK library[], FILE * fp, int bookNum);//清理輸入行
void EatLine(void);//初始化一條結構信息-------用於刪除或者修改書籍
void initStruct(BOOK * book);//初始化結構數組
void initARR(BOOK library[], int bookNum);//獲取一個非0的,小於Judge_Num的正整數輸入
int Get_A_Num(int Judge_Num);//刪除結構(書籍)信息
void Delete_book(BOOK library[], int bookNum);//修改結構信息
void ModifyStruct(BOOK library[], int bookNum);//打印 沒有書籍的提示信息
void Print_No_Book(void);
/****************************************************************************/
源文件:main.c
//14.14
#include "Functions_name.h"
int main(void)
{
BOOK library[MAXBKS]; /* 結構數組 */
initARR(library, MAXBKS); //初始化結構數組int bookNum = 0; //書籍數量
FILE * pbooks; //文件指針
int choice = 0; //儲存用戶輸入的選項
bool isQuit = false; //退出程序的標記
//打開文件----失敗則直接退出程序
Open_File(FILENAME, "r", &pbooks);rewind(pbooks); //定義到文件開始
//從文件中讀取書籍信息
while (bookNum < MAXBKS && Read_File(&library[bookNum], pbooks) == 0)
{
bookNum++;
}
File_IsFull(bookNum); //檢驗文件是否已滿----如已滿,則直接退出程序//根據用戶的選項執行程序
while (isQuit != true)
{
PrintMenu(); //打印菜單
choice = Get_Choice(); //獲取用戶輸入的選項switch (choice)
{
case 1: //打印所有書籍信息
Print_books(library, bookNum);
break;case 2: //添加新書,同時更新書籍數目
bookNum = Get_Newbook(library, bookNum);
break;case 3:
if (bookNum != 0) //只有存在書籍的時候纔可以刪除書籍
{
Print_books(library, bookNum); //先打印所有的書籍信息
ModifyStruct(library, bookNum); //再修改書籍信息
}
else
Print_No_Book(); //沒有書
break;case 4:
if (bookNum != 0) //只有存在書籍的時候纔可以刪除書籍
{
Print_books(library, bookNum); //先打印所有的書籍信息
Delete_book(library, bookNum); //刪除一條書籍信息
bookNum--; //總書籍數目減一
}
else
Print_No_Book(); //沒有書
break;case 5:
isQuit = true;
break;
}
EatLine(); //清理輸入行 (我也不知道爲什麼這裏也要清理輸入行, 可能是返回值的問題吧)
}//把所有信息寫入文件
if (bookNum > 0)
{
//先關閉文件,再用"w"模式打開文件,就可以把文件長度截爲零
fclose(pbooks);
Open_File(FILENAME, "w", &pbooks);
////把所有書籍信息寫入文件
Write_to_File(library, pbooks, bookNum);
}puts("Bye.\n");
fclose(pbooks); //關閉文件return 0;
}
//打開文件----失敗則直接退出程序
void Open_File(char const * fname, char const * mode, FILE ** fp)
{
errno_t error; //fopen_s()函數返回該類型的值
if ((error = fopen_s(fp, fname, mode) != 0))
{
fprintf_s(stderr, "Can't open %s file.\n", fname);
exit(1);
}
}//讀取文件信息----讀取成功
int Read_File(BOOK * book, FILE * fp)
{
/****
* 雖然這裏步驟稍多,但用fgets()會比使用gets_s()更好一些
*///讀取書籍名稱
if (fgets(book->title, MAXTITL, fp) == NULL)
{
return -1;
}
else
Delete_n(book->title, MAXTITL); //刪除換行符//獲取作者名稱
if (fgets(book->author, MAXAUTL, fp) == NULL)
{
return -2;
}
else
Delete_n(book->author, MAXTITL);//獲取價格
if (fscanf_s(fp, "%lf\n", &book->value) != 1)
{
return -3;
}
return 0;
}//刪除字符串中的換行符
void Delete_n(char * string, int length)
{
char * find;if (string != NULL)
{
find = strchr(string, '\n'); //查找換行符
if (find != NULL) //找到換行符
{
*find = '\0'; //替換成一個空字符
}
}
}//打印菜單
void PrintMenu(void)
{
system("cls"); //先清除屏幕printf("/***********************************************/\n");
printf("1) Book List\n");
printf("2) Add new books\n");
printf("3) Modify\n");
printf("4) Delete\n");
printf("5) Quit\n");
printf("\n\nInput: ");
}//獲取用戶的選項輸入
int Get_Choice(void)
{
int choice = Get_A_Num(5); //獲取一個小於5的,大於0的正整數return choice;
}//獲取字符串輸入
char * s_gets(char * st, int n)
{
char * ret_val;
char * find;ret_val = fgets(st, n, stdin);
if (ret_val != NULL)
{
find = strchr(st, '\n'); //查抄換行符if (find != NULL) //找到換行符
{
*find = '\0'; //替換成一個空字符
}
else
{
while (getchar() != '\n')
continue; //清理輸入行
}
}
return ret_val;
}//檢驗文件是否已滿----如已滿,則直接退出程序
void File_IsFull(int bookNum)
{
if (bookNum == MAXBKS) //文件已滿
{
fprintf_s(stderr, "The %s file is full.", FILENAME);
exit(2);
}
}//添加新書--------返回總書籍數目
int Get_Newbook(BOOK library[], int bookNum)
{
puts("\nPlease add new book titles.");
puts("Press [enter] at the start of a line to stop.");while (bookNum < MAXBKS && s_gets(library[bookNum].title, MAXTITL) != NULL
&& library[bookNum].title[0] != '\0') //獲取書籍名稱
{
puts("Now enter the author.");
s_gets(library[bookNum].author, MAXTITL); //獲取作者名稱puts("Now enter the value.");
scanf_s("%lf", &library[bookNum].value); //獲取價格
bookNum++;
EatLine(); //清理輸入行
if (bookNum < MAXBKS) //獲取下一條信息
{
puts("Enter the nexty title.");
}
}return bookNum;
}//打印所有書籍信息
void Print_books(BOOK library[], int bookNum)
{
if (bookNum == 0)
{
Print_No_Book(); //沒有書籍
return;
}printf("Here is the list of your books:\n\n");
for (int i = 0; i < MAXBKS; i++)
{
if (library[i].title[0] != '\0')
printf("%s by %s: $%.2f\n", library[i].title, library[i].author, library[i].value);
}
}//把所有書籍信息寫入文件
void Write_to_File(BOOK library[], FILE * fp, int bookNum)
{
for (int i = 0; i < MAXBKS; i++)
{
if (library[i].title[0] != '\0')
{
fprintf_s(fp, "%s\n", library[i].title);
fprintf_s(fp, "%s\n", library[i].author);
fprintf_s(fp, "%.2f\n\n", library[i].value);
}
}
}//清理輸入行
void EatLine(void)
{
char ch;
while ((ch = getchar()) != '\n')
continue;
}//初始化一條結構信息-------用於刪除或者修改書籍
void initStruct(BOOK * book)
{
for (int i = 0; i < MAXTITL; i++)
{
book->title[i] = '\0';
book->author[i] = '\0';
}
book->value = 0;
}//初始化結構數組
void initARR(BOOK library[], int bookNum)
{
for (int i = 0; i < bookNum; i++)
{
initStruct(&library[i]);
}
}//獲取一個非0的,小於Judge_Num的正整數輸入
int Get_A_Num(int Judge_Num)
{
int number = -1;//處理錯誤輸入
while (scanf_s("%d", &number) != 1 || number < 1 || number > Judge_Num)
{
printf("Your input is invalid. Thr again: ");
EatLine(); //清理輸入行
}
EatLine(); //清理輸入行return number;
}//刪除結構(書籍)信息---(這裏的nookNum是從1開始計算的書籍總數目)
void Delete_book(BOOK library[], int bookNum)
{
printf("\nEnter the number of the book which you want to dedete: ");
int number = Get_A_Num(bookNum); //獲取到用戶希望刪除的結構信息的編號+1initStruct(&library[number - 1]); //刪除用戶希望刪除的結構信息
printf("Succeed in deleting!\n");
}//修改結構信息----(這裏的nookNum是從1開始計算的書籍總數目)
void ModifyStruct(BOOK library[], int bookNum)
{
printf("\nEnter the number of the book which you want to modify: ");
int number = Get_A_Num(bookNum) - 1; //獲取到用戶希望修改的結構信息的編號puts("\nPlease add new book titles.");
puts("Press [enter] at the start of a line to stop.");while (number < MAXBKS && s_gets(library[number].title, MAXTITL) != NULL
&& library[number].title[0] != '\0') //獲取書籍名稱(排除非法輸入)
{
puts("Now enter the author.");
s_gets(library[number].author, MAXTITL); //獲取作者名稱puts("Now enter the value.");
scanf_s("%lf", &library[number].value); //獲取價格
EatLine(); //清理輸入行printf("Succeed in modifying the book!\n");
break;
}
}//打印 沒有書籍的提示信息
void Print_No_Book(void)
{
printf("Sorry, there is no book now!\n");
printf("Please add some books over.\n");
}
差不多就是這樣了。
運行效果是完全沒有問題的。功能已經全部實現了!(還差兩題。。。還要兩週.....)
P14-8:
題目:
/*
14-8---- 巨人航空公司的機羣由 12 個作爲的飛機組成。它每天飛行一個航班。根據下面的要求,
編寫一個個座位預訂程序。、a. 該程序使用一個內含 12 個結構的數組。每個結構中包括:一個成員表示座位編號,
一個成員表示座位是否已被預訂,一個成員表示預訂人的名,一個成員表示預訂人的姓。
b. 該程序顯示下面的菜單:To choose a function, enter its letter label:
a) Show number of empty seats
b) Show list of empty seats
c) Show alphabetical list of seats
d) Assign a customer to a seat assignment
e) Delete a seat assignment
f) Quit*/
頭文件:Functions_declarations.h
#pragma once
//Function_declarations.h 包含
//所有的預處理指令
//函數聲明
/************頭文件********************/
#include <stdio.h>
#include <stdlib.h> //提供exit()函數原型
#include <string.h> //提供strchr()函數原型
#include <stdbool.h> //提供bool類型
#include <conio.h> //提供_getch()函數原型(但感覺這裏挺浪費空間的)/****************宏定義***********************/
#define SEATNUM 12 //12 個座位
#define NAMELENGTH 30 //最大名稱的長度 30個字符//航班結構
typedef struct A_Plane_Seat
{
char f_name[NAMELENGTH]; //預訂人的名
char l_name[NAMELENGTH]; //預訂人的姓
bool isOrdered; //是否已經有預訂
int SeatNum; //座位號
}Seat;
/************************函數聲明*********************************///初始化一條結構信息(可用於取消預訂)
void Init_A_Struct(Seat * a_seat);//初始化結構數組
void InitStructArr(Seat Plane_Seats[], int seat_num);//打印菜單函數
void PrintMenu(void);//清空輸入行
void EatLine(void);//獲取一個字符的函數,參數一和二 是獲取字符的範圍(需要謹慎使用範圍)
char Get_A_Character(char fromCh, char endCh);//獲取一個正整數的函數,參數1是限定範圍
int Get_A_Num(int Judge);//獲取字符串輸入
char * s_gets(char * string, int length);//檢索是否有空座位
bool Have_Seat_Empty(Seat Plane_Seats[], int seat_num);//顯示所有空座位的編號
void Print_Empty_Seats(Seat Plane_Seats[], int seat_num);//列表空座位的編號
void List_Empty_Seats(Seat Plane_Seats[], int seat_num);//顯示所有座位的信息
void Print_All_Seats(Seat Plane_Seats[], int seat_num);//添加一個客戶的預訂信息
void Add_A_Custmer(Seat Plane_Seats[], int seat_num);//刪除一名客戶的預訂信息
void Delete_A_Custmer(Seat Plane_Seats[], int seat_num);
源文件:main.c
#include "Functions_declarations.h" //同時編譯(包含預處理指令和函數聲明)
//主函數
int main(void)
{
char choice; //儲存用戶輸入的字符選擇
bool isQuit = false; //用於退出程序的標記
Seat Plane_Seats[SEATNUM]; //結構數組InitStructArr(Plane_Seats, SEATNUM); //初始化結構數組、
while (isQuit != true)
{
PrintMenu(); //打印菜單
choice = Get_A_Character('a', 'f'); //獲取用戶的一個字符輸入switch (choice)
{
case 'a': //顯示所有空座位的編號
Print_Empty_Seats(Plane_Seats, SEATNUM);
break;case 'b': //列表空座位的編號
List_Empty_Seats(Plane_Seats, SEATNUM);
break;case 'c': //顯示所有座位的信息
Print_All_Seats(Plane_Seats, SEATNUM);
break;case 'd': //添加一個客戶的預訂信息
//先打印所有座位的信息
Print_All_Seats(Plane_Seats, SEATNUM);
//添加一名顧客信息
Add_A_Custmer(Plane_Seats, SEATNUM);
break;case 'e': //刪除一個客戶的預訂信息
//先打印所有座位的信息
Print_All_Seats(Plane_Seats, SEATNUM);
//再刪除一名顧客的信息
Delete_A_Custmer(Plane_Seats, SEATNUM);
break;case 'f': //退出程序
isQuit = true;
break;default: //其他情況(理應不可能出現的狀況)
system("cls");
printf("Program error!\n");
exit(EXIT_FAILURE);
break;
}
EatLine(); //等待用戶的隨意輸入
}printf("Thanks for using!\n");
return 0;
}
//初始化一條結構信息(可用於取消預訂)
void Init_A_Struct(Seat * a_seat)
{
bool isInited = false; //判斷是否初始化 預訂信息 的標記
for (int i = 0; i < NAMELENGTH; i++)
{
a_seat->f_name[i] = '\0'; //將姓和名數組中的所有元素都初始化爲0
a_seat->l_name[i] = '\0';
if (isInited == false)
{
a_seat->isOrdered = false; //初始化預訂信息
isInited = true; //只初始化一次
}
}
}//初始化結構數組
void InitStructArr(Seat Plane_Seats[], int seat_num)
{
for (int i = 0; i < seat_num; i++)
{
Init_A_Struct(&Plane_Seats[i]); //初始化預訂人的姓名和預訂信息
Plane_Seats[i].SeatNum = i + 1; //初始化座位編號(只初始化一次!)
}return;
}//打印菜單函數
void PrintMenu(void)
{
system("cls"); //先清屏,再打印菜單
printf("To choose a function, enter its letter label: \n");
printf(" a) Show number of empty seats\n");
printf(" b) Show list of empty seats\n");
printf(" c) Show alphabetical list of seats\n");
printf(" d) Assign a customer to a seat assignment\n");
printf(" e) Delete a seat assignment\n");
printf(" f) Quit\n\n\n");printf("Your input: ");
// printf(" ");
}//清空輸入行
void EatLine(void)
{
int ch;
while (ch = getchar() != '\n')
continue;return;
}//獲取一個字符的函數,參數一和二 是獲取字符的範圍(需要謹慎使用範圍)
char Get_A_Character(char fromCh, char endCh)
{
char choice;//處理非法輸入
while ((choice = getchar()) < fromCh || choice > endCh)
{
printf("Your input is invalid. Put the correct one: ");
EatLine(); //清理輸入行
continue;
}
EatLine(); //清理輸入行return choice;
}//獲取一個正整數的函數,參數1是限定範圍
int Get_A_Num(int Judge)
{
int Num;//處理非法輸入
while ( (scanf_s("%d", &Num) != 1) || Num < 1 || Num > Judge )
{
printf("Your input is invalid. Put the correct one: ");
EatLine(); //清理輸入行
continue;
}
EatLine(); //清理輸入行return Num;
}//獲取字符串輸入
char * s_gets(char * string, int length)
{
char * ret_val;
char * find;ret_val = fgets(string, length, stdin); //獲取字符串輸入
if (ret_val)
{
find = strchr(string, '\n'); //查找換行符
if (find) //如果地址不是 NULL(找到了)
{
*find = '\0'; //將原先的字符替換成換行符
}
else
EatLine(); //如果沒找到,就清理輸入行
}return ret_val;
}bool Have_Seat_Empty(Seat Plane_Seats[], int seat_num)
{
bool Have_Seat = false;for (int i = 0; i < seat_num; i++)
{
if (Plane_Seats[i].isOrdered != true) //檢索有沒有被預訂的座位
{
Have_Seat = true; //檢索到有空位置就退出循環
break;
}
}return Have_Seat;
}//顯示所有空座位的編號
void Print_Empty_Seats(Seat Plane_Seats[], int seat_num)
{
//如果沒座位了 直接返回
if (Have_Seat_Empty(Plane_Seats, seat_num) == false)
{
printf("None of seats is empty.");
return;
}for (int i = 0; i < seat_num; i++)
{
if (Plane_Seats[i].isOrdered != true)
{
printf("\nNo. %d", Plane_Seats[i].SeatNum);
}
}
}//列表空座位的編號
void List_Empty_Seats(Seat Plane_Seats[], int seat_num)
{
//如果沒座位了 直接返回
if (Have_Seat_Empty(Plane_Seats, seat_num) == false)
{
printf("None of seats is empty.");
return;
}for (int i = 0; i < seat_num; i++)
{
if (Plane_Seats[i].isOrdered != true)
{
printf("\nSeat No. %d ", Plane_Seats[i].SeatNum);
}
}
printf("\nare empty now!\n");}
//顯示所有座位的信息
void Print_All_Seats(Seat Plane_Seats[], int seat_num)
{
for (int i = 0; i < seat_num; i++)
{
if (Plane_Seats[i].isOrdered != true) //如果是空座位
{
printf("\nSeat No. %d is empty.", Plane_Seats[i].SeatNum);
}
else //如果已經被預訂了
{
printf("\nSeat No. %d was ordered by %s %s.",
Plane_Seats[i].SeatNum, Plane_Seats[i].f_name, Plane_Seats[i].l_name);
}
}
printf("\n\n");
}//添加一個客戶的預訂信息
void Add_A_Custmer(Seat Plane_Seats[], int seat_num)
{
int Num = 0; //儲存用戶輸入的座位編號//如果沒座位了 直接返回
if (Have_Seat_Empty(Plane_Seats, seat_num) == false)
{
printf("None of seats is empty.");
return;
}
printf("Add a custmer at No.");
Num = Get_A_Num(seat_num); //獲取用戶輸入的座位編號
//如果該座位號已經被預訂,則重新讓用戶輸入一個座位編號
while (Plane_Seats[Num - 1].isOrdered == true)
{
printf("Seat No.%d has been ordered. Input another: ", Num);
Num = Get_A_Num(seat_num);
}
Num--; //將用戶的輸入的編號減一,得到實際的編號//已經獲取到一個空的座位號了 提示輸入顧客的姓名
printf("Please enter the custmer's first name: ");
s_gets(Plane_Seats[Num].f_name, NAMELENGTH);
printf("Enter the custmer's last name: ");
s_gets(Plane_Seats[Num].l_name, NAMELENGTH);Plane_Seats[Num].isOrdered = true;
printf("\n\nSucceed in adding!");
}void Delete_A_Custmer(Seat Plane_Seats[], int seat_num)
{
int Num = 0; //儲存用戶輸入的座位編號
printf("Delete a custmer at No.");
Num = Get_A_Num(seat_num); //獲取用戶輸入的座位編號//如果該座位已經是空座位,就不重複刪除(初始化)
if (Plane_Seats[Num - 1].isOrdered == false)
{
printf("Seat No.%d is empty.", Num);
return;
}
Num--; //將用戶的輸入的編號減一,得到實際的編號
Init_A_Struct(&Plane_Seats[Num]); //初始化該條結構信息
Plane_Seats[Num].isOrdered = false;
printf("\n\nSucceed in Deleting!");}
一切運行正常!
還有剩下的 3 題博主會在一個月內補上的(爲了粉絲,先發出來吧)
呃,畢竟還是個學生....
Alex Mercer(boy) 鳴謝!