合作者:周政演 031602543 部落格連結魏璐炜 031602136 部落格連結
相同部分
大緻設計思路
根據讨論 制定了兩種思路:
- 将數字與運算符建立映射,利用随機數函數在運算符位置上模拟出四種運算符,舍棄除數為0的情況以及輸出不為整數的情況。
- 将各種情況讨論出來,再一一編碼。
編碼規範
因為想到自己制訂的編碼規範未必規範,是以上網查找了一些編碼規範,經過篩選,共同學習後制訂出了編碼規範。
一、排版:1、關鍵詞和操作符之間加适當的空格。
2.相對獨立的程式塊與塊之間加空行
3.較長的語句、表達式等要分成多行書寫。
4.劃分出的新行要進行适應的縮進,使排版整齊,語句可讀。
5.長表達式要在低優先級操作符處劃分新行,操作符放在新行之首。
二、注釋
1.注釋要簡單明了。
2.邊寫代碼邊注釋,修改代碼同時修改相應的注釋,以保證注釋與代碼的一緻性。
3.在必要的地方注釋,注釋量要适中。注釋的内容要清楚、明了,含義準确,防止
注釋二義性。保持注釋與其描述的代碼相鄰,即注釋的就近原則。
4.對代碼的注釋應放在其上方相鄰位置,不可放在下面。
5.變量、常量的注釋應放在其上方相鄰位置或右方。
三、命名
1.較短的單詞可通過去掉“元音”形成縮寫;
2.較長的單詞可取單詞的頭幾發符的優先級,并用括号明确表達式的操作順序,避
免使用預設優先級。
四、可讀性
1.避免使用不易了解的數字,用有意義的辨別來替代。
2.不要使用難懂的技巧性很高的語句。
3.源程式中關系較為緊密的代碼應盡可能相鄰。
五、變量
1.去掉沒必要的公共變量。
2.構造僅有一個子產品或函數可以修改、建立,而其餘有關子產品或函數隻通路的公共
變量,防止多個不同子產品或函數都可以修改、建立同一公共變量的現象。
3.仔細定義并明确公共變量的含義、作用、取值範圍及公共變量間的關系。
4.明确公共變量與操作此公共變量的函數或過程的關系,如通路、修改及建立等。
六、函數、過程
1.一個函數最好僅完成一件功能。
2.為簡單功能編寫函數。
3.函數的功能應該是可以預測的,也就是隻要輸入資料相同就應産生同樣的輸出。
4.盡量不要編寫依賴于其他函數内部實作的函數。
5.檢查函數所有參數輸入的有效性。
八、程式效率
1.程式設計時要經常注意代碼的效率。
2.在保證軟體系統的正确性、穩定性、可讀性及可測性的前提下,提高代碼效率。
3.不能一味地追求代碼效率,而對軟體的正确性、穩定性、可讀性及可測性造成影
響。
4.程式設計時,要随時留心代碼效率;優化代碼時,要考慮周全。
5.在多重循環中,應将最忙的循環放在最内層。
程式一的實作與結果測試
函數頭
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<stdbool.h>
int get_integer(void);//擷取題目數
void get_number(int *pa,int *pb,int *pc);//擷取數字
char get_sign(void);//擷取運算符号
int value(int,int,char); //求兩個數四則運算的值
bool language=true;
在程式中有五個自定義函數,建立這麼多的自定義函數的目的是簡化main函數,将函數分成許多小的功能,各個函數的功能在代碼中均有注釋。
雙語界面

這次程式的操作是
擷取題目數
int get_integer(void)
{
int n,num;
char ch;
bool judge=true;
if(language) printf("請輸入0~10的整數題數:\n");
else printf("Please enter 0~10 integer question.");
n=scanf("%d",&num);
if(num>10||num<1)//限定為0~10的題目數
judge=false;
while(n!=1||judge==false)//給使用者再次嘗試的機會
{
if(language) printf("請輸入一個0~10整數,如2,3.\n");
else printf("Please enter 0~10 interger,such as 2,3.\n");
while((ch=getchar())!='\n')
continue;
n=scanf("%d",&num);
if(num>10||num<1)
judge=false;
else
judge=true;
}
return num;
}
該段代碼的作用是擷取題目數,其中代碼排除了0~10以外的題數以及非整數的輸入。循環語句中運用了最近學習的一個小技巧:若是擷取是如ndsjfbs這樣的一段輸入,循環語句會給使用者一次提示并給予他們重新輸入的機會,同時将使用者的錯誤輸入清空。
提供重新輸入的機會
擷取随機數
void get_number(int *pa,int *pb,int *pc)//擷取随機的數字
{
srand(time(NULL));
*pa=rand()%11;
*pb=rand()%11;
*pc=rand()%11;
}
其中srand()rand()來自頭檔案stdlib.h,time()來自頭檔案time.h。srand()用來初始化rand(),而srand()中的time(NULL)是用時間作為參數,使種子不斷變化,進而産生不同的“随機數”。
rand()函數傳回一個整數值,此時将這個整數值用11取餘,就可以得到範圍是0~10的數。
擷取符号
char get_sign(void)//将運算符對應于數字,用随機數模拟随機運算符
{
char sign;
int int_sign;
srand(time(NULL));
int_sign=rand()%4+1;
switch(int_sign)
{
case 1:sign='+';break;
case 2:sign='-';break;
case 3:sign='*';break;
case 4:sign='/';break;
}
return sign;
}
在該自定義函數中,建立了一個數字到運算符号的映射,1、2、3、4對應着字元+、-、*、/。産生一次随機數便能傳回一個運算符,模拟随機産生運算符的功能。
計算二進制表達式的值
int value(int a,int b,char sign)//計算兩個數的四則運算
{
int v;
switch(sign)//注意除數不能為0,整數輸出
{
case '+':v=a+b;break;
case '-':v=a-b;break;
case '*':v=a*b;break;
case '/':v=a/b;break;
}
return v;
}
本次作業隻輸出3個數字的題目,若是一一讨論,将大大增加程式的複雜程度,于是化整為零,編寫出兩個數的運算函數,這樣增加了程式的可讀性和可移植性,若是要增加到4個數字、5個數字的混合運算,隻需在main函數中稍作更改即可。
主函數
int main(void)
{
int i,num,count=0;//num為題數,count用于計算題數
int a,b,c,answer;//abc為計算的數字,answer是使用者輸入的答案
int * pa,* pb,* pc;
pa=&a;pb=&b;pc=&c;//用于擷取數字的函數
char sign1,sign2;
char ch;
printf("選擇中文版請輸入1。\nEnter 0 to choose English.");
scanf("%d",&language);
num=get_integer();
if(language)
printf("請輸入一個整數答案(輸入e結束并得出結果)\n");
else printf("Please enter an integer answer(e to quit and get the result).\n");
for(i=1;i<=num;)//自增符号放于檔案尾,防止用continue剔除不合要求題目時減少了循環次數
{
sign1=get_sign();
sign2=get_sign();
get_number(pa,pb,pc);
if(sign2=='/')//剔除除數為0和答案不為整數的題目
if(c==0||(float)(b/c)==(b/c))continue;
if(sign1=='/')//剔除除數為0和答案不為整數的題目
if(value(b,c,sign1)==0||(float)(b/c)==(b/c))continue;
printf(" %d %c ( %d %c %d)=",a,sign1,b,sign2,c);
if(scanf("%d",&answer)!=1)break;//擷取使用者的答案,輸入e時退出
b=value(b,c,sign2);
if(answer==value(a,b,sign1))
{
if(language)
printf("答案正确!\n");
else printf("You're right!\n");
count++;
}
else {
if(language)printf("答案錯誤!答案為%d\n",value(a,b,sign1));
else printf("It's wrong,the right answer is %d\n",value(a,b,sign1));
}
i++;
}
if(language)printf("正确題數:%d",count);
else printf("You have %d right answer.",count);
return 0;
}
主函數中的循環語句中有多個條件語句,用與剔除各種不符合要求的題目輸出。
完整代碼
測試結果
不足之處
檔案的運作速度過慢,有時要等待數秒才能輸出題目,我們認為原因如下:
- 剔除不符合要求的輸出的條件語句太多,導緻重複的運作過多。
- 随機數的産生是以時間為種子,短時間内系統輸出時間是不變的,是以會産生相同的随機數,這樣這些相同的随機數都會被剔除,直到一個時刻産生符合要求的随機數為止。
分工與合作
github的送出連結
https://github.com/Vancasola/cooperation
差異部分
合作過程以及體會
- 接到題目後,兩個人很快組成一個小組,對題目進行讨論。開始時先讨論清楚題意,然後分享各自的思路,二人綜合之後,決定采用如下思路:将數字與運算符建立映射,利用随機數函數在運算符位置上模拟出四種運算符,舍棄除數為0的情況以及輸出不為整數的情況。031602543先打出主函數的結構,經過讨論後定下子產品,查找資料學習随機數的原理以及使用。由031602543編寫擷取題數、求兩數四則運算函數值、擷取符号的函數,由031602136編寫随機數函數。因為這次作業并不是很難,是以二人隻在git上送出了幾次就把程式寫完了,若是在更大的項目上合作,恐怕需要花費的時間和精力就多得多了,送出和更改的次數也會增加許多。兩個人在編碼的時候,都是使用多組測試資料,将代碼盡量檢查到沒有錯誤,才push上去,這樣減少了對方的工作量。
- 在學習git時遇到了許多問題,其中,在push代碼到倉庫時,總是顯示沒有權限,網絡上普遍的說法時缺少ssh key,需要将sshkey添加到github中的setting裡,嘗試多次後,發現并不奏效,後來向助教學長請教了一下,發現是并未将成員添加到倉庫裡面,這是教程裡面沒有提到的,将成員添加後,就順利地解決了這個問題。
分工
- 031602543 主要負責編碼、調試程式、解決git中遇到的問題、完成随筆。
- 031602136 主要負責界面美化、翻譯、記錄過程。
- 分工github位址