當前位置:首頁 » 編程語言 » c語言課堂設計總結
擴展閱讀
webinf下怎麼引入js 2023-08-31 21:54:13
堡壘機怎麼打開web 2023-08-31 21:54:11

c語言課堂設計總結

發布時間: 2022-10-17 00:44:17

1. c語言課程設計報告要求

一 、 設計題目

萬年歷的設計

二 、設計要求

1、能夠顯示星期;

2、能夠顯示年月日;

3、能夠修改;

4、當系統時間變動時,能自動跳到相應的時間。

三 、 設計目的

1. 通過本項課程設計,可以培養獨立思考、 綜合運用所學有關相應知識的能力,能更好的鞏固《C語言程序設計》課程學習的內容,掌握 工程軟體設計的基本方法,強化上機動手編程能力,闖過理論與實踐相結合的難關!更加了解了c語言的好處和其可用性!同時增加了同學之間的團隊合作精神!更加也體會到以後在工作中團隊合作的重要性和必要性!

2. 通過C語言課程設計,使學生了解高級程序設計語言的結構,掌握基本的程序設計過程和技巧,掌握基本的分析問題和利用計算機求解問題的能力,具備初步的高級語言程序設計能力。為後續各門計算機課程的學習和畢業設計打下堅實基礎。

四 、設計思想及過程

【一】由於萬年歷具有以下特點:

1。平年365天(52周+1天),閏年366天(52周+2天)。平年2月28天,閏年2月29天。

由於公元1月1日設為星期六,故3月1日為星期三。 ——注意這個「三」

為使演算法達到最簡,故本演算法以「星期」為計算單位。且選3月1日為基月。

2。每400年整一閏,或每4年且不為百年的一閏。(原因:地球繞太陽一周的時間是365天5小時46秒,為了使一年的天數為整數,將一年的天數定為365天,餘下的時間積累起來,四年就是23小時15分4秒,將近一天,把這一天加在某年的二月而成29天,該年稱為閏年,其它年稱為平年。但四年加一天又多用了44分56秒,這個數積滿400年為三天。因此400年中只能有97個閏年,所以凡能被400整除,或不能被100整除但能被4整除的年份為閏年。)

所以百年%4=0閏或(年%4=0並且年<>0)閏。

3。每 4年(3個平年+1個閏年)共208周+5天 ——注意這個「5天」

每百年共100*(208周+5天)-1天=5217周+5天 ——注意這個「5天」(整百年暫設為平年)

每400年共4*(5217周+5天)+1天(整400年閏)=20871周+0天——注意這個「0天」和

「1天」(4個整百年只有一個閏年)

即400年一輪回!(原來萬年歷400年前是一家)

【二】根據萬年歷以上特點進行編寫:

首先對萬年歷年、月、日進行編寫,編寫程序先定義每月的天數為28天,如月份為1、3、5、7、8、10、12就定義天數為31天反之如果月份為4、6、9、11就輸出天數為30天,由上可見2月份為28天但是如果為閏年就有29天就要定義另一個函數#define Year(x) (x%4==0&&x%100!=0||x%400==0) ? 1:0當為閏年時可得1加上該程序便可得到每月的天數。 具體程序見(五、萬年歷程序)

再對其中的星期進行編寫:由於公元1月1日設為星期六,故3月1日為星期三,可以用萬年3月1日星期演算法(特別是那個三)

由於其公式為:

某年3月1日星期幾=(3天+百年%4*5天+年/4*5天+年%4+月星期表+日-1天)%7

某年3月1日星期幾=(百年%4*5天+年/4*5天+年%4+月星期表+日+2天)%7

或 某年3月1日星期幾=(百年%4*5天+年+年/4+月星期表+日+2天)%7

閏4百年3月1日星期演算法(百年%4=0)

其公式為:

某年3月1日星期幾=(年+年/4+月星期表+日+2天)%7

例:0000年3月1日星期幾=(0+0/4+0+1+2)%7=3%7=星期三

1600年3月1日星期幾=(0+0/4+0+1+2)%7=3%7=星期三

2000年3月1日星期幾=(0+0/4+0+1+2)%7=3%7=星期三

2001年3月1日星期幾=(1+1/4+0+1+2)%7=4%7=星期四

2004年3月1日星期幾=(4+4/4+0+1+2)%7=8%7=星期一

2008年3月1日星期幾=(8+8/4+0+1+2)%7=13%7=星期六

2042年3月1日星期幾=(42+42/4+0+1+2)%7=55%7=星期六

平4百年3月1日星期演算法(百年%4<>0)

其公式為:

某年3月1日星期幾=(百年%4*5天+年+年/4+月星期表+日+2天)%7

例:1700年3月1日星期幾=(17%4*5+0+0/4+0+1+2)%7=8%7=星期一(注意:1700年是平年)

1800年3月1日星期幾=(18%4*5+0+0/4+0+1+2)%7=13%7=星期六(注意:1800年是平年)

1900年3月1日星期幾=(19%4*5+0+0/4+0+1+2)%7=18%7=星期四(注意:1900年是平年)

1901年3月1日星期幾=(19%4*5+1+1/3+0+1+2)%7=19%7=星期五

1918年3月1日星期幾=(19%4*5+18+18/4+0+1+2)%7=(15+22+3)%7=40%7=星期五

1958年3月1日星期幾=(19%4*5+58/4*5+58%4+3)%7=(15+70+2+3)%7=90%7=星期六

1988年3月1日星期幾=(19%4*5+88/4*5+88%4+3)%7=(15+110+0+3)%7=128%7=星期二

1999年3月1日星期幾=(19%4*5+99/4*5+99%4+3)%7=(15+120+3+3)%7=141%7=星期一

2100年3月1日星期幾=(21%4*5+0/4*5+0%4+3)%7=(5+0+0+3)%7=8%7=星期一(注意:2100年是平年)

2101年3月1日星期幾=(21%4*5+1/4*5+1%4+3)%7=(5+0+1+3)%7=9%7=星期二

2102年3月1日星期幾=(21%4*5+2/4*5+2%4+3)%7=(5+0+2+3)%7=10%7=星期三

2103年3月1日星期幾=(21%4*5+3/4*5+3%4+3)%7=(5+0+3+3)%7=11%7=星期四

2104年3月1日星期幾=(21%4*5+4/4*5+4%4+3)%7=(5+1+0+3)%7=9%7=星期二(注意:2104年是閏年)

9999年3月1日星期幾=(99%4*5+99/4*5+99%4+3)%7=(120+15+3+3)%7=141%7=星期一

註:按400年一輪回!(400年前是一家)的說法

1600年,2000年是一樣的;

1700年,2100年是一樣的;

1800年,2200年是一樣的;

1900年,2300年是一樣的。

其中萬年某日星期演算法

其公式為:

某日星期幾=(百年%4*5天+年+年/4+月星期表+日+2天)%7

通同星期偏差表

閏年 1月 2月 3月 4月 5月 6月 7月 8月 9月 10月 11月 12月

天數 31 29 31 30 31 30 31 31 30 31 30 31

星期 3 6 0 3 5 1 3 6 2 4 0 2

平年 1月 2月 3月 4月 5月 6月 7月 8月 9月 10月 11月 12月

天數 31 28 31 30 31 30 31 31 30 31 30 31

星期 4 0 0 3 5 1 3 6 2 4 0 2

為對以上的萬年歷星期的演算法是正確的對其進行了以下的計算:

⒈對於二十世紀任意日期可以用公式某日星期幾=(百年%4*5天+年+年/4+平年月星期表+日+2天)%7=(19%4*5天+年+年/4+平年月星期表+日+2天)%7=(15天+年+年/4+平年月星期表+日+2天)%7以下就是根據上面對其進行的計算:

1900年元旦 1日=(0/4*5+0%4+1+3)%7=(0+0+4)%7=4

1月表=4(平年) 故 4+4=1 即1900年元旦是星期一

1949年國慶 1日=(49/4*5+49%4+1+3)%7=(60+1+4)%7=2

10月表=4(平年) 故 4+2=6 即1949年國慶是星期六

1999年12月31日 31日=(99/4*5+99%4+31+3)%7=(120+3+34)%7=3

12月表=2(平年) 故 2+3=5 即1999年12月31日是星期五

⒉對於二十一世紀新前年蟲演算法(20%4*5=0)可以用公式:某日星期幾=(百年%4*5天+年+年/4+閏年月星期表+日+2天)%7 =(20%4*5天+年+年/4+閏年月星期表+日+2天)%7以下就是根據上面對其進行的計算:

2000年元旦 1日=(0+0/4+1+2)%7=(0+0+1+2)%7=3

1月表=3(閏年) 故 3+3->6 即2027年元旦是星期六

2018年春節 16日=(18+18/4+16+2)%7=(18+4+16+2)%7=5

2月表=0(平年) 故 0+5=5 即2018年春節是星期五

2099年12月31日 31日=(99/4*5+99%4+31+2)%7=(120+3+33)%7=2

12月表=2(平年) 故 2+2=4 即2099年12月31日是星期四

對於上面的分析以及公式的推論和計算證明可以對萬年歷中的星期進行了編寫具體編寫程序見(五 、萬年歷程序)中。

五 、萬年歷源程序

#include"stdio.h"

#include"dos.h"

#include"conio.h"

#include"stdlib.h"

#define Year(x) (x%4==0&&x%100!=0||x%400==0) ? 1:0 /*判斷閏年*/

int numofMonth(int y,int m){

int day,t=28;

if(m==1||m==3||m==5||m==7||m==8||m==10||m==12)

day=31; /*定義以上月份為31天*/

else if(m==4||m==6||m==9||m==11)

day=30; /*定義以上月份為30天*/

else{t+=Year(y);

day=t;} /*閏年二月29天,平年28天*/

return day;}

int numofYear(int y){

int t=365; /*平年365天*/

t+=Year(y);/*閏年366天*/

return t;}

int numofbeforeDays(int y,int m,int d){

int sum=d,i;

for(i=1;i<m;i++)

sum+=numofMonth(y,i);

return sum;}

int numofafterDays(int y,int m,int d){

int sum=0,i;

for(i=m;i<=12;i++)

sum+=numofMonth(y,i);

sum-=d;

return sum;}

int isDay(int y,int m,int d){

int year=1900,month=1,week=1,i; /*定義萬年歷是從1900年開始*/

long sum=0;

for(i=year;i<y;i++)

sum+=numofYear(i);

for(i=1;i<m;i++)

sum+=numofMonth(y,i);

/* ++sum;*/

i=sum%7;

week=(week+i)%7;

return week;}

void empty(int n){

int i;

for(i=0;i<n;i++)

printf("%*c",6,' ');}

void OutPutCalender(int y,int m,int d)/*計算x年x月x是星期幾*/{

int week,i,num,t;

week=isDay(y,m,1);

printf("%6d/%02d/%02d\n",y,m,d);

printf("%6s%6s%6s%6s%6s%6s%6s\n","Sun","Mon","Tue","Wed","Thu","Fri","Sat");

empty(week);

num=numofMonth(y,m);

for(i=1;i<=num;i++){

printf("%6d",i);

t=(week+i)%7;

if(t==0)

printf("\n");} /*游標移到下一行*/

printf("\n");}

long numBTDays(int y1,int m1,int d1,int y2,int m2,int d2)/*定義兩個不同日期*/{

int i;

long sum=0;

for(i=y1+1;i<y2;i++)

sum+=numofYear(i);

if(y1==y2){ sum-=d1;

for(i=m1;i<m2;i++)

sum+=numofMonth(y1,i);

sum+=d2;}

else{sum+=numofafterDays(y1,m1,d1);

sum+=numofbeforeDays(y2,m2,d2);}

return sum;}

int Select_mean(){

int sm;

printf("1. OutPut Calender\n"); /*輸出當前月份的日歷*/

printf("2. Help\n"); /*幫助*/

printf("0. Quit\n"); /*退出*/

printf("Please enter choose(0--2):"); /*從0-2中選擇*/

do

scanf("%d",&sm); /*輸入sm*/

while(sm<0||sm>3);

return sm;}

void Help()/*輸出幫助欄的內容*/{

printf(" 1. OutPut Calender\n");

printf(" 2. System Help\n");

printf(" 0. Quit\n");

printf("Page Up: Up year\n"); /*上一年*/

printf("Page Down: next year\n"); /*下一年*/

printf(" --> : next month\n"); /*上一月*/

printf(" <-- : Up month\n");/*下一月*/}

main(){

int year=2006,year1=2006,month,day,y1,m1,d1,y2,m2,d2,c,t; /*定義運行後的日期是2006年*/

int inkeySCAN,inkey; /*輸入鍵盤操作信息*/

union REGS inregs,outregs;

inregs.h.ah=0x2a;

intdos(&inregs,&outregs);

/* year=outregs.xcx; */

month=outregs.h.dh;

day=outregs.h.dl;

year1=year;

printf("%d/%02d/%02d\n",year,month,day);

while(1)/*當選擇為1時,執行以下語句*/{

switch(Select_mean()){

case 1:

OutPutCalender(year,month,day);

while(1){

inkey=bioskey(0);

inkeySCAN=(inkey&0xFF00)>>8;

if(inkeySCAN==77){

if(month==12){month=1;year1++;

OutPutCalender(year1,month,day);/*輸出日歷*/}

else{month++;

OutPutCalender(year1,month,day);

}}

if(inkeySCAN==75){

if(month==1){month=12;year1--;

OutPutCalender(year1,month,day);}

else{month--;OutPutCalender(year1,month,day);}}

if(inkeySCAN==73){

if(year1==1900) year1=year;

else{year1--;OutPutCalender(year1,month,day);}}

if(inkeySCAN==81){

year1++;OutPutCalender(year1,month,day);}

if(inkeySCAN==28)break;}

break; /*終止循環*/

case 2:

Help();

break;

case 0:

exit(0);

default:

printf("Enter ERROR!\n");

break;} }

}

六 運行過程

1.雙擊TC

1. 當對上面的程序進行了調試後運行會出現下面所示:

第一行所顯示的就是系統時間!滿足了第一條要求「顯示年、月、日」。

而當改變系統時間後!再運行該程序上面的日期也隨系統時間改變,所以滿足第四條「當系統時間變動時,能自動跳到相應的時間。」

2. 在游標處按下「1」後回車,將會顯示:

以上的顯示也證明了條件的第2條可以「顯示星期!」

3. 在游標處按下「2」後回車,將會顯示:

按著幫助所講進行了運行可知:按「 Page Up 」鍵其下面接著會顯示上一年該月的萬年歷,按「 Page Down 」鍵其下面會接著顯示下一年該月的萬年歷;按「 ← 」鍵下面將會接著顯示當年上一個月的萬年歷,按「 → 」鍵將會接著在下面顯示去下一個月的萬年歷。

4.

由上所顯示鍵入「0」後將會退去該程序。

由以上運行的結果可知該c語言所設計的萬年歷滿足設計要求!

七、在C語言編程中常見錯誤

C語言的最大特點是:功能強、使用方便靈活。C編譯的程序對語法檢查並不象其它高級語言那麼嚴格,這就給我們留下「靈活的餘地」,但還是由於這個靈活給程序的調試帶來了許多不便,尤其對我們這些初學C語言的人來說,經常會出一些連自己都不知道錯在哪裡的錯誤。看著有錯的程序,不知該如何改起,我通過這次編程,也積累了一些C編程時常犯的錯誤:

1. 書寫標識符時,忽略了大小寫字母的區別。
編譯程序把a和A認為是兩個不同的變數名,而顯示出錯信息。C語言認為大寫字母和小寫字母是兩個不同的字元。習慣上,符號常量名用大寫,變數名用小寫表示,以增加可讀性。

2.忽略了變數的類型,進行了不合法的運算。
%是求余運算,得到a/b的整余數。整型變數a和b可以進行求余運算,而實型變數則不允許進行「求余」運算。

3.將字元常量與字元串常量混淆。
混淆了字元常量與字元串常量,字元常量是由一對單引號括起來的單個字元,字元串常量是一對雙引號括起來的字元序列。C規定以「\」作字元串結束標志,它是由系統自動加上的,所以字元串「a」實際上包含兩個字元:『a'和『\',而把它賦給一個字元變數是不行的。

4.忽略了「=」與「==」的區別。
在C語言中,「=」是賦值運算符,「==」是關系運算符。如:
if (a==3) a=b;
前者是進行比較,a是否和3相等,後者表示如果a和3相等,把b值賦給a。由於習慣問題,初學者往往會犯這樣的錯誤。

5.忘記加分號。
分號是C語句中不可缺少的一部分,語句末尾必須有分號。
a=1 b=2
編譯時,編譯程序在「a=1」後面沒發現分號,就把下一行「b=2」也作為上一行語句的一部分,這就會出現語法錯誤。改錯時,有時在被指出有錯的一行中未發現錯誤,就需要看一下上一行是否漏掉了分號。
{ z=x+y;
t=z/100;
printf("%f",t);
}
對於復合語句來說,最後一個語句中最後的分號不能忽略不寫(這是和PASCAL不同的)。

6.多加分號。
對於一個復合語句,如:
{ z=x+y;
t=z/100;
printf("%f",t);
};
復合語句的花括弧後不應再加分號,否則將會畫蛇添足。
又如:
if (a%3==0);
I++;
本是如果3整除a,則I加1。但由於if (a%3==0)後多加了分號,則if語句到此結束,程序將執行I++語句,不論3是否整除a,I都將自動加1。
再如:
for (I=0;I<5;I++);
{scanf("%d",&x);
printf("%d",x);}
本意是先後輸入5個數,每輸入一個數後再將它輸出。由於for()後多加了一個分號,使循環體變為空語句,此時只能輸入一個數並輸出它。

7.輸入變數時忘記加地址運算符「&」。
int a,b;
scanf("%d%d",a,b);
這是不合法的。Scanf函數的作用是:按照a、b在內存的地址將a、b的值存進去。「&a」指a在內存中的地址。

8.輸入數據的方式與要求不符。scanf("%d%d",&a,&b);輸入時,不能用逗號作兩個數據間的分隔符,如下面輸入不合法:
3,4
輸入數據時,在兩個數據之間以一個或多個空格間隔,也可用回車鍵,跳格鍵tab。
scanf("%d,%d",&a,&b);C規定:如果在「格式控制」字元串中除了格式說明以外還有其它字元,則在輸入數據時應輸入與這些字元相同的字元。下面輸入是合法的:
3,4
此時不用逗號而用空格或其它字元是不對的。
3 4 3:4
又如:
scanf("a=%d,b=%d",&a,&b);
輸入應如以下形式:
a=3,b=4

9.輸入字元的格式與要求不一致。
在用「%c」格式輸入字元時,「空格字元」和「轉義字元」都作為有效字元輸入。
scanf("%c%c%c",&c1,&c2,&c3);
如輸入a b c
字元「a」送給c1,字元「 」送給c2,字元「b」送給c3,因為%c只要求讀入一個字元,後面不需要用空格作為兩個字元的間隔。

10.輸入輸出的數據類型與所用格式說明符不一致。
例如,a已定義為整型,b定義為實型
a=3;b=4.5;
printf("%f%d\n",a,b);

語法錯
邏輯錯 運行錯
0.忘記定義變數:
main()
{x=3;y=6;
printf(「%d\n」,x+y);

11.C語言的變數一定要先定義才能使用;

12.輸入輸出的數據的類型與所用格式說明符不一致
int a=3;float b=4.5;printf(「%f%d\n」,a,b);
它們並不是按照賦值的規則進行轉換(如把4.5轉換為4),而是將數據在存儲單元中的形式按格式符的要求組織輸出(如b佔4個位元組,只把最後兩個位元組的數據按%d,作為整數輸出)

13.未注意int型數據的數值范圍
int型數據的數值范圍(-32768~32768)
int num=89101;
printf(「%d」,num);
會將超過低16位的數截去從而得到23563
注意:定義了long型,而在輸出時仍用」%d」說明符,仍會出現以上錯誤
14.輸入變數時忘記使用地址符
scanf(「%d%d」,a,b);
15.輸入時數據的組織與要求不符
對scanf函數中格式字元串中除了格式說明符外,對其他字元必須按原樣輸入
16.誤把」=「作為」等於」比較符
「=「為附值運算符
「==「為比較運算符
17.語句後面漏分號
{
t=a;
a=b;
b=t
}
它是pascal的語法
18.不該加分號的地方加了分號
if(a>b);
printf(「a is larger than b\n」);
for(i=0;i<10;i++);
{
scanf(「%d」,&x);
printf(「%d\n」,x*x);
}
19.對應該有花括弧的復合語句,忘記加花括弧
sum=0;
i=1;
while(i<=100)
sum=sum+1;
i++;
20.括弧不配對
while((c=getchar()!=『#』)

putchar(c);
11.在用標識時,忘記了大寫字母和小寫字母的區別
{
int a,b,c;
a=2;
b=3;
C=A+B;
printf(「%d+%d=%D」,A,B,C);
}
12.引用數組元素時誤用發圓括弧
{
int i,a(10);
for(i=0;i<10;i++)
scanf(「%d」,&a(i));
}
13.在定義數組時,將定義的」元素個數」誤認為是」可使用的最大下標值
{
int a[10]={1,2,3,4,5,6,7,8,9,10};
int i;
for(i=1;i<=10;i++)
printf(「%d」,a[i]);
}
14.對二維或多維數組的定義和引用的方法不對
{
int a[5,4];

printf(「%d」,a[1+2,2+2]);

}
15.誤以為數組名代表數組中全部元素
{int a[4]={1,2,3,4};
printf(「%d%d%d%d」,a);
}
16.混淆字元數組與字元指針的區別
main()
{
char str[40];
str=「Computer and c」;
printf(「%s\n」,str);
}
17.在引用指針變數之前沒有對它賦予確定的值
{
char *p;
scanf(「%s」,p);
}
{
char *p,c[20];
p=c;
scanf(「%s」,p);
}
18.switch語句的各分支中漏寫 break語句
混淆字元和字元串的表示形式

char sex;
sex=「M」;

19.使用自加(++)和自減(--)運算符時出的錯誤
{
int *p,a[5]={1,3,5,7,9};
p=a;
printf(「%d」,*p++);
}
注意於*(++p)的區別;
20.所調用的函數在調用語句之後才定義,而又在調用前未加說明
main()
{float x,y,z;
x=3.5;y=-7.6;
z=max(x,y);
printf(「%f」,z);
}
編譯時不給出出錯信息,但運行結果將與原意不符。這種錯誤尤其需要注意。

八、心得體會

1. 目前流行的計算機日歷程序,比較典型的是Windows各版本中的日歷程序以及基礎於該程序所開發的各種應用程序中的日歷程序。然而,這些程序都千篇一律的局限在一個很短的時間范圍內。(Windows各個版本一般都局限在1980年至2099年這一范圍內),但是,在很多情況下,特別是在眾多的科學研究領域中,一個時間跨度較大的日歷程序是很有參考價值的。C程序設計語言充分發揮了其自身無與倫比的優越性,用極短的程序文本填補了這一領域的空白,同時用鐵的事實強有力的告訴世人:C程序設計語言作為計算機語言家族的新生事物,其發展前景是極為廣闊的。

2. 經過上一個學期對《C程序設計》的學習,我們學習了理論知識,了解了C語言程序設計的思想,這些知識都為我們的下一步學習打下了堅實的基礎。通過課程設計,一方面是為了檢查我們一個學期來我們學習的成果,另一方面也是為了讓我們進一步的掌握和運用它,同時也讓我們認清自己的不足之處和薄弱環節,加以彌補和加強。

3. 通過對c語言萬年歷的設計進一步的鞏固了用c語言編寫程序,並且有利於更好的掌握c語言!

4. 在萬年歷的編寫過程中也體會到了做事情一頂要細心、認真。更加知道了要掌握好基礎知識。還有體會到了成功的感覺!在萬年歷的設計過程中更加體會到了團隊合作的重要性,「一個諸葛亮比不上三個臭皮匠。」知道了只有團隊合作才會更好的完成設計!也體會到以後在工作中團隊合作的必要性和重要性!

5. 通過本項課程設計也培養了我獨立思考、 綜合運用所學有關相應知識的能力,掌握 工程軟體設計的基本方法,強化上機動手編程能力,闖過理論與實踐相結合的難關!

6. 由於C語言是近年在國內外得到迅速推廣應用的一種語言。C語言功能豐富,表達能力強,使用靈活方便,應用面廣,目標程序效率高,可移植性好,既具有高級語言的優點,又具有低級語言的許多特點。通過這次的c語言程序設計更加了解了c語言的好處和其可用性!

7. 在這次課程設計中也知道了自己的動手能力不強有待進一部的提高!在設計過程中不能夠把書本上的知識與實踐相結合,這也就增加了設計不好該程序的想法!在設計過程中的一次次設計錯誤增加了我放棄的想法!不過經過大家的努力終於完成了課程設計!完成該程序後想起自己以前的每一次對自己失去信心,就覺得並不是在知識掌握上打敗了,而是自己對自己缺乏信心!只要自己對自己不失去信心相信就可以完成那些以前認為完成不了的事情!也讓我懂得了要想成功首先就必須有很強的自信心!懂得了自己以後要在做任何事情時都要自信!當自己都不相信自己能夠成功時還可能會獲得成功嗎?

8. 在C語言程序設計的過程中也知道了自己在以前的學習中有很大的不足導致在設計過程中出現了很多的問題,有些地方看不懂也不知道怎麼去設計,但是在設計過程中也學習了很多,掌握了自己以前沒有學好的知識,雖然一時可以掌握完以前沒有學好的知識,不過也給自己敲響了警鍾,在學習中不可以伏於表面,要想學好每一門課程都要踏踏實實,做什麼都不是給別人看的!都是要更好的掌握該門知識,提高自己的自身的修養,提高自己的能力!為以後的工作打下良好的知識基礎和技能基礎!

九、參考文獻

⒈譚浩強編著.C程序設計第二版〔M〕.北京:清華大學出版社,1999

⒉陳朔鷹,陳英編著.C語言趣味程序百例精解〔M〕.北京:北京理工大學出版社,1994

⒊電腦知識與技術學術交流版〔J〕2005.2 (備註:來自網路資源)

⒋Herbert Schildit著. 戴健鵬譯. C語言大全 (第二版)〔M〕.北京:電子工業出版社,1994

⒌譚浩強,張基溫,唐永炎編著. C語言程序設計教程.〔M〕北京: 高等教育出版社,1992

⒍秦友淑,曹化工編著. C語言程序設計教程. 〔M〕武漢:華中理工大學出版社,1996

⒎曹衍龍,林瑞仲,徐慧 編著.C語言實例解析精粹 〔M〕北京:人民郵電出版社,2005.3

⒏黃明等編著.21世紀進階輔導C語言程序設計. 〔M〕大連理工大學出版

2. C語言程序設計課程講什麼內容

C語言程序設計課程是入門級的程序設計課程,針對沒有或很少具有編程經驗的在職人員。課程通過學習C語言編程的基礎語法,對程序設計有一個基本的認識,為後續計算機專業課程以及面向對象程序設計課程的學習打下基礎。 課程主要內容:C語言程序基本結構及相關概念、變數、函數、語句、if條件語句、switch條件語句、for循環語句、while循環語句、數組、指針、字元串、結構體。

3. c語言課程設計(學生成績管理系統) 急求參考 (不要網上那些下的,別人都可以下到的!)

C語言課程設計任務書
一、題目: 學生成績管理
二、目的與要求
1. 目的:
(1)基本掌握面向過程程序設計的基本思路和方法;
(2)達到熟練掌握C語言的基本知識和技能;
(3)能夠利用所學的基本知識和技能,解決簡單的程序設計問題
2. 要求
基本要求:
1. 要求利用C語言面向過程的編程思想來完成系統的設計;
2. 突出C語言的函數特徵,以多個函數實現每一個子功能;
3. 畫出功能模塊圖;
4. 進行簡單界面設計,能夠實現友好的交互;
5. 具有清晰的程序流程圖和數據結構的詳細定義;
6. 熟練掌握C語言對文件的各種操作。
創新要求:
在基本要求達到後,可進行創新設計,如系統用戶功能控制,對管理員級和一般級別的用戶系統功能操作不同
三、信息描述
輸入一個班10個學生的學號和每個學生考試三門功課(數學、英語、計算機基礎)的成績。編程計算出每個學生的總分和平均分,並按學生成績優劣排序,最後列印一張按高分到低分名次排序的成績單。要求:
1)排序用一個函數實現。
2)列印的成績單表項包括:序號,學號、數學、英語、計算機、總分、平均分。
3)按實驗報告電子模板格式填寫實驗內容。
四、功能描述
1. 學生基本信息及成績所選科目成績的錄入。
2. 基本信息的查詢(分系、班級;分科目)與修改。
3. 對每系或每班各科成績進行分析(即求單科平均成績、及格率和優秀率);
4. 對所開課程的成績分析(求其平均成績,最高分和最低分);
5. 對學生考試成績進行排名(單科按系別或班級進行排名,對每一個班級,同一學期學生總體成績進行排名,並顯示各科成績信息)
五、解決方案
1. 分析程序的功能要求,劃分程序功能模塊。
2. 畫出系統流程圖。
3. 代碼的編寫。定義數據結構和各個功能子函數。
4. 程序的功能調試。
5. 完成系統總結報告以及使用說明書
六、進度安排
此次課程設計時間為兩周,分四個階段完成:
1. 分析設計階段。指導教師應積極引導學生自主學習和鑽研問題,明確設計要求,找出實現方法,按照需求分析、總體設計、詳細設計這幾個步驟進行。
2. 編碼調試階段:根據設計分析方案編寫C代碼,然後調試該代碼,實現課題要求的功能。
3. 總結報告階段:總結設計工作,寫出課程設計說明書,要求學生寫出需求分析、總體設計、詳細設計、編碼、測試的步驟和內容。
4. 考核階段。
#include <stdio.h>
#include <stdlib.h>
#define STU_NUM 10 /*宏定義學生的數量*/
struct student /*定義一個結構體用來存放學生學號、三門課成績、總分及平均成績*/
{
char stu_id[20]; /*學生學號;*/
float score[3]; /*三門課成績;*/
float total; /*總成績;*/
float aver; /*平均成績;*/
};
/*排序用一個函數來實現*/
void SortScore(student *stu,int n)
{
student stud;
for(int i = 0; i < n-1; i++)
for(int j = i+1 ; j < n; j++)
{
if(stu[i].total < stu[j].total)
{
stud = stu[i];
stu[i] = stu[j];
stu[j] = stud;
}
}
}
int main( )
{
student stu[STU_NUM]; /*創建結構體數組中有10個元素,分別用來保存這10個人的相關信息。*/
/*輸入這十個學生的相關信息*/
for(int i = 0; i<STU_NUM; i++)
{
printf("請輸入第%d個學生的學號:",i+1);
scanf("%s",&stu[i].stu_id);
printf("輸入第%d個學生的數學成績:",i+1);
scanf("%f",&stu[i].score[0]);
printf("輸入第%d個學生的英語成績:",i+1);
scanf("%f",&stu[i].score[1]);
printf("輸入第%d個學生的計算機成績:",i+1);
scanf("%f",&stu[i].score[2]);
stu[i].total = stu[i].score[0]+stu[i].score[1]+stu[i].score[2];
stu[i].aver = stu[i].total/3;
}
printf("\n");

SortScore(stu,STU_NUM);/*調用排序函數*/
/*輸出排序後的各學生的成績*/
for(i = 0 ; i < STU_NUM; i++)
{
printf("序號: %d\t",i);
printf("學號:%s\t",stu[i].stu_id);
printf("數學:%f\t",stu[i].score[0]);
printf("英語:%f\t",stu[i].score[1]);
printf("計算機:%f\t",stu[i].score[2]);
printf("平均成績:%f\t",stu[i].aver);
printf("總分:%f\t",stu[i].total);
printf("\n\n");
}
return 0;
}
註:(源程序中主要標識符含義說明)
#define STU_NUM 10 /*宏定義學生的數量*/
struct student /*定義一個結構體用來存放學生學號、三門課成績、總分及平均成績*/
{
char stu_id[20]; /*學生學號;*/
float score[3]; /*三門課成績;*/
float total; /*總成績;*/
float aver; /*平均成績;*/
}
實驗結果:
輸入 :(只輸入後面的數字,前面的文字是自己產生的)。
請輸入第1個學生的學號:001
輸入第1個學生的數學成績:1
輸入第1個學生的英語成績:1
輸入第1個學生的計算機成績:1
請輸入第2個學生的學號:002
輸入第2個學生的數學成績:2
輸入第2個學生的英語成績:2
輸入第2個學生的計算機成績:2
請輸入第3個學生的學號:003
輸入第3個學生的數學成績:3
輸入第3個學生的英語成績:3
輸入第3個學生的計算機成績:3
請輸入第4個學生的學號:004
輸入第4個學生的數學成績:4
輸入第4個學生的英語成績:4
輸入第4個學生的計算機成績:4
請輸入第5個學生的學號:005
輸入第5個學生的數學成績:5
輸入第5個學生的英語成績:5
輸入第5個學生的計算機成績:5
請輸入第6個學生的學號:006
輸入第6個學生的數學成績:6
輸入第6個學生的英語成績:6
輸入第6個學生的計算機成績:6
請輸入第7個學生的學號:007
輸入第7個學生的數學成績:7
輸入第7個學生的英語成績:7
輸入第7個學生的計算機成績:7
請輸入第8個學生的學號:008
輸入第8個學生的數學成績:8
輸入第8個學生的英語成績:8
輸入第8個學生的計算機成績:8
請輸入第9個學生的學號:009
輸入第9個學生的數學成績:9
輸入第9個學生的英語成績:9
輸入第9個學生的計算機成績:9
請輸入第10個學生的學號:010
輸入第10個學生的數學成績:10
輸入第10個學生的英語成績:10
輸入第10個學生的計算機成績:10
輸出:
序號: 0 學號:010 數學:10.000000 英語:10.000000 計算機:10.000000
平均成績:10.000000 總分:30.000000

序號: 1 學號:009 數學:9.000000 英語:9.000000 計算機:9.000000
平均成績:9.000000 總分:27.000000

序號: 2 學號:008 數學:8.000000 英語:8.000000 計算機:8.000000
平均成績:8.000000 總分:24.000000

序號: 3 學號:007 數學:7.000000 英語:7.000000 計算機:7.000000
平均成績:7.000000 總分:21.000000

序號: 4 學號:006 數學:6.000000 英語:6.000000 計算機:6.000000
平均成績:6.000000 總分:18.000000

序號: 5 學號:005 數學:5.000000 英語:5.000000 計算機:5.000000
平均成績:5.000000 總分:15.000000

序號: 6 學號:004 數學:4.000000 英語:4.000000 計算機:4.000000
平均成績:4.000000 總分:12.000000

序號: 7 學號:003 數學:3.000000 英語:3.000000 計算機:3.000000
平均成績:3.000000 總分:9.000000

序號: 8 學號:002 數學:2.000000 英語:2.000000 計算機:2.000000
平均成績:2.000000 總分:6.000000

序號: 9 學號:001 數學:1.000000 英語:1.000000 計算機:1.000000
平均成績:1.000000 總分:3.000000
七、撰寫課程設計報告或課程設計總結
課程設計報告要求:
總結報告包括需求分析、總體設計、詳細設計、編碼(詳細寫出編程步驟)、測試的步驟和內容、課程設計總結、參考資料等,不符合以上要求者,則本次設計以不及格記。

C語言常見錯誤
書寫標識符時,忽略了大小寫字母的區別
main()
{
int a=5;
printf("%d",A);
}
編譯程序把a和A認為是兩個不同的變數名,而顯示出錯信息。C認為大寫字母和小寫字母是兩個不同的字元。習慣上,符號常量名用大寫,變數名用小寫表示,以增加可讀性。
2.忽略了變數的類型,進行了不合法的運算。
main()
{
float a,b;
printf("%d",a%b);
}
%是求余運算,得到a/b的整余數。整型變數a和b可以進行求余運算,而實型變數則不允許進行「求余」運算。
3.將字元常量與字元串常量混淆。
char c;
c="a";
在這里就混淆了字元常量與字元串常量,字元常量是由一對單引號括起來的單個字元,字元串常量是一對雙引號括起來的字元序列。C規定以「\」作字元串結束標志,它是由系統自動加上的,所以字元串「a」實際上包含兩個字元:『a'和『\',而把它賦給一個字元變數是不行的。
4.忽略了「=」與「==」的區別。
在許多高級語言中,用「=」符號作為關系運算符「等於」。如在BASIC程序中可以寫
if (a=3) then …
但C語言中,「=」是賦值運算符,「==」是關系運算符。如:
if (a==3) a=b;
前者是進行比較,a是否和3相等,後者表示如果a和3相等,把b值賦給a。由於習慣問題,初學者往往會犯這樣的錯誤。
5.忘記加分號。
分號是C語句中不可缺少的一部分,語句末尾必須有分號。
a=1
b=2
編譯時,編譯程序在「a=1」後面沒發現分號,就把下一行「b=2」也作為上一行語句的一部分,這就會出現語法錯誤。改錯時,有時在被指出有錯的一行中未發現錯誤,就需要看一下上一行是否漏掉了分號。
{ z=x+y;
t=z/100;
printf("%f",t);
}
對於復合語句來說,最後一個語句中最後的分號不能忽略不寫(這是和PASCAL不同的)。
6.多加分號。
對於一個復合語句,如:
{ z=x+y;
t=z/100;
printf("%f",t);
};
復合語句的花括弧後不應再加分號,否則將會畫蛇添足。
又如:
if (a%3==0);
I++;
本是如果3整除a,則I加1。但由於if (a%3==0)後多加了分號,則if語句到此結束,程序將執行I++語句,不論3是否整除a,I都將自動加1。
再如:
for (I=0;I<5;I++);
{scanf("%d",&x);
printf("%d",x);}
本意是先後輸入5個數,每輸入一個數後再將它輸出。由於for()後多加了一個分號,使循環體變為空語句,此時只能輸入一個數並輸出它。
7.輸入變數時忘記加地址運算符「&」。
int a,b;
scanf("%d%d",a,b);
這是不合法的。Scanf函數的作用是:按照a、b在內存的地址將a、b的值存進去。「&a」指a在內存中的地址。
8.輸入數據的方式與要求不符。①scanf("%d%d",&a,&b);
輸入時,不能用逗號作兩個數據間的分隔符,如下面輸入不合法:
3,4
輸入數據時,在兩個數據之間以一個或多個空格間隔,也可用回車鍵,跳格鍵tab。
②scanf("%d,%d",&a,&b);
C規定:如果在「格式控制」字元串中除了格式說明以外還有其它字元,則在輸入數據時應輸入與這些字元相同的字元。下面輸入是合法的:
3,4
此時不用逗號而用空格或其它字元是不對的。
3 4 3:4
又如:
scanf("a=%d,b=%d",&a,&b);
輸入應如以下形式:
a=3,b=4
9.輸入字元的格式與要求不一致。
在用「%c」格式輸入字元時,「空格字元」和「轉義字元」都作為有效字元輸入。
scanf("%c%c%c",&c1,&c2,&c3);
如輸入a b c
字元「a」送給c1,字元「 」送給c2,字元「b」送給c3,因為%c只要求讀入一個字元,後面不需要用空格作為兩個字元的間隔。
10.輸入輸出的數據類型與所用格式說明符不一致。
例如,a已定義為整型,b定義為實型
a=3;b=4.5;
printf("%f%d\n",a,b);
編譯時不給出出錯信息,但運行結果將與原意不符。這種錯誤尤其需要注意。
11.輸入數據時,企圖規定精度。
scanf("%7.2f",&a);
這樣做是不合法的,輸入數據時不能規定精度。
12.switch語句中漏寫break語句。
例如:根據考試成績的等級列印出百分制數段。
switch(grade)
{ case 'A':printf("85~100\n");
case 'B':printf("70~84\n");
case 'C':printf("60~69\n");
case 'D':printf("<60\n");
default:printf("error\n");
由於漏寫了break語句,case只起標號的作用,而不起判斷作用。因此,當grade值為A時,printf函數在執行完第一個語句後接著執行第二、三、四、五個printf函數語句。正確寫法應在每個分支後再加上「break;」。例如
case 'A':printf("85~100\n");break;
13.忽視了while和do-while語句在細節上的區別。
(1)main()
{int a=0,I;
scanf("%d",&I);
while(I<=10)
{a=a+I;
I++;
}
printf("%d",a);
}
(2)main()
{int a=0,I;
scanf("%d",&I);
do
{a=a+I;
I++;
}while(I<=10);
printf("%d",a);
}
可以看到,當輸入I的值小於或等於10時,二者得到的結果相同。而當I>10時,二者結果就不同了。因為while循環是先判斷後執行,而do-while循環是先執行後判斷。對於大於10的數while循環一次也不執行循環體,而do-while語句則要執行一次循環體。
14.定義數組時誤用變數。
int n;
scanf("%d",&n);
int a[n];
數組名後用方括弧括起來的是常量表達式,可以包括常量和符號常量。即C不允許對數組的大小作動態定義。
15.在定義數組時,將定義的「元素個數」誤認為是可使的最大下標值。
main()
{static int a[10]={1,2,3,4,5,6,7,8,9,10};
printf("%d",a[10]);
}
C語言規定:定義時用a[10],表示a數組有10個元素。其下標值由0開始,所以數組元素a[10]是不存在的。
16.初始化數組時,未使用靜態存儲。
int a[3]={0,1,2};
這樣初始化數組是不對的。C語言規定只有靜態存儲(static)數組和外部存儲(exterm)數組才能初始化。應改為:
static int a[3]={0,1,2};
17.在不應加地址運算符&的位置加了地址運算符。
scanf("%s",&str);
C語言編譯系統對數組名的處理是:數組名代表該數組的起始地址,且scanf函數中的輸入項是字元數組名,不必要再加地址符&。應改為:
scanf("%s",str);
18.同時定義了形參和函數中的局部變數。
int max(x,y)
int x,y,z;
{z=x>y?x:y;
return(z);
}
形參應該在函數體外定義,而局部變數應該在函數體內定義。應改為:
int max(x,y)
int x,y;
{int z;
z=x>y?x:y;
return(z);
}
C語言心得體會
通過這次實訓,增加了我學習軟體技術的興趣,雖然還不明確軟體技術包含的具體內容,但從C語言這門課程開始,已發現程序設計的樂趣,在學習C語言的過程中也學到了許多計算機應用基礎知識,對計算機的機體也有了一個大體的了解。
這次實訓是老師給了范常式序,經過自己的改寫,實現要求。先做簡單的輸出,一步步的再做其它圖案,在實際操作過程中犯的一些錯誤還會有意外的收獲,感覺實訓很有意思。在具體操作中對這學期所學的C語言的理論知識得到鞏固,達到實訓的基本目的,也發現自己的不足之出,在以後的上機中應更加註意,同時體會到C語言具有的語句簡潔,使用靈活,執行效率高等特點。發現上機實訓的重要作用,特別是對數組和循環有了深刻的理解。
通過實際操作,學會 C語言程序編程的基本步驟、基本方法,開發了自己的邏輯思維能力,培養了分析問題、解決問題的能力。深刻體會到「沒有做不到的,只有想不到的」,「團結就是力量」,「實踐是檢驗真理的標准」,「不恥下問」……的寓意。
計時在此希望以後應多進行這樣的實訓,加長設間,培養學生獨立思考問題的能力,提高實際操作水平。
八、參考資料 :《C語言程序設計教程》

4. c語言實驗報告心得

c語言實驗心得:
1、只有頻繁用到或對運算速度要求很高的變數才放到data區內,如for循環中的計數值。
2、其他不頻繁調用到和對運算速度要求不高的變數都放到xdata區。
3、常量放到code區,如字型檔、修正系數。
4、邏輯標志變數可以定義到bdata中。
在51系列晶元中有16個位元組位定址區bdata,其中可以定義8*16=128個邏輯變數。這樣可以大大降低內存佔用空間。定義方法是: bdata bit LedState;但位類型不能用在數組和結構體中。
5、data區內最好放局部變數。
因為局部變數的空間是可以覆蓋的(某個函數的局部變數空間在退出該函數是就釋放,由別的函數的局部變數覆蓋),可以提高內存利用率。當然靜態局部變數除外,其內存使用方式與全局變數相同;
6、確保程序中沒有未調用的函數。
在Keil C里遇到未調用函數,編譯器就將其認為可能是中斷函數。函數里用的局部變數的空間是不釋放,也就是同全局變數一樣處理。這一點Keil做得很愚蠢,但也沒辦法。
7、如果想節省data空間就必須用large模式。
將未定義內存位置的變數全放到xdata區。當然最好對所有變數都要指定內存類型。
8、使用指針時,要指定指針指向的內存類型。
在C51中未定義指向內存類型的通用指針佔用3個位元組;而指定指向data區的指針只佔1個位元組;指定指向xdata區的指針佔2個位元組。如指針p是指向data區,則應定義為: char data *p;。還可指定指針本身的存放內存類型,如:char data * xdata p;。其含義是指針p指向data區變數,而其本身存放在xdata區。

以前沒搞過C51,大學時代跟單片機老師的時候也是搗鼓下匯編,現在重新搞單片機,因為手頭資料不多,找到一些C51的程序,發現裡面有這些關鍵字,不甚明了,沒辦法只好找了下,發現如下描述:

從數據存儲類型來說,8051系列有片內、片外程序存儲器,片內、片外數據存儲器,片內程序存儲器還分直接定址區和間接定址類型,分別對應code、data、xdata、idata以及根據51系列特點而設定的pdata類型,使用不同的存儲器,將使程序執行效率不同,在編寫C51程序時,最好指定變數的存儲類型,這樣將有利於提高程序執行效率(此問題將在後面專門講述)。與ANSI-C稍有不同,它只分SAMLL、COMPACT、LARGE模式,各種不同的模式對應不同的實際硬體系統,也將有不同的編譯結果。

在51系列中data,idata,xdata,pdata的區別

data:固定指前面0x00-0x7f的128個RAM,可以用acc直接讀寫的,速度最快,生成的代碼也最小。

idata:固定指前面0x00-0xff的256個RAM,其中前128和data的128完全相同,只是因為訪問的方式不同。idata是用類似C中的指針方式訪問的。匯編中的語句為:mox ACC,@Rx.(不重要的補充:c中idata做指針式的訪問效果很好)

xdata:外部擴展RAM,一般指外部0x0000-0xffff空間,用DPTR訪問。

pdata:外部擴展RAM的低256個位元組,地址出現在A0-A7的上時讀寫,用movx ACC,@Rx讀寫。這個比較特殊,而且C51好象有對此BUG,建議少用。但也有他的優點,具體用法屬於中級問題,這里不提。

三、有關單片機ALE引腳的問題

"單片機不訪問外部鎖存器時ALE端有正脈沖信號輸出,此頻率約為時鍾振盪頻率的1/6.每當訪問

外部數據存儲器是,在兩個機器周期中ALE只出現一次,即丟失一個ALE脈沖."這句話是不是有毛

病.我覺得按這種說法,應該丟失3個ALE脈沖才對,我一直想不通是怎麼回事,希望大蝦們幫幫我.

小弟感激涕零.

答:

其他所有指令每6個機器周期發出一個ALE,而MOVX指令佔用12個機器周期只發出一個ALE

四、如何將一個INT型數據轉換成2個CHAR型數據?

經keil優化後,char1=int1/256,char2=int1%256或char1=int1>>8,char2=int1&0x00ff效率是一樣的。

五、在KEIL C51上模擬完了,怎樣生成HEX文件去燒寫??

右鍵點項目中Target 1,選第二個,在OUTPUT中選中CREAT HEX

六、typedef 和 #define 有何不同??

typedef 和 #define 有何不同》》》 如

typedef unsigned char UCHAR ;

#define unsigned char UCHAR ;

typedef命名一個新的數據類型,但實際上這個新的數據類型是已經存在的,只不過是定義了

一個新的名字.

#define只是一個標號的定義.

你舉的例子兩者沒有區別,但是#define還可以這樣用

#define MAX 100

#define FUN(x) 100-(x)

#define LABEL

等等,這些情況下是不能用typedef定義的

七、請問如何設定KELC51的模擬工作頻(時鍾)

用右鍵點擊左邊的的target 1,然後在xtal一欄輸入

八、不同模塊怎樣共享sbit變數,extern不行?

把SBIT定義單獨放到一個.H中,每個模塊都包含這個.h文件

九、C51中對於Px.x的訪問必須自己定義嗎?

是的。

如sbit P17 = 0x97;即可定義對P1.7的訪問

十、SWITCH( )語句中表達式不可以是位變數對嗎?

可以用位變數:

#include

#include

void main()

{

bit flag;

flag=0;

switch(flag)

{

case '0':{printf("0\n");break;}

case '1':{printf("1\n");break;}

default:break;

}

}

bit 變數只有兩種狀態,if 語句足夠啦,!!!

十一、const常數聲明占不佔內存???

const 只是用來定義「常量」,所佔用空間與你的定義有關,如:

const code cstStr[] = {"abc"};

佔用代碼空間;而如:

const char data cstStr[] = {"abc"};

當然佔用內存空間。

另外,#define 之定義似乎不佔用空間。

十二、philips的單片機P89C51RD+的擴展RAM在C51中如何使用?

試一試將auxr.1清0,然後在c語言中直接聲明xdata類型的變數

十三、BUG of Keil C51

程序中用如下語句:

const unsigned char strArr[] = {"數學"};

結果發現strArr[] 內容為 {0xCA,0xD1,0xA7},真奇怪!

凡是有0xfd,則會通通不見了,所以只能手工輸入內碼了,例如 uchar strArr[]=

{0xCA,0xfd,0xd1,0xa7}(用Ultraedit會很方便)。

十四、Keil C51中如何實現代碼優化?

菜單Project下Option for target "Simulator"的C51.

看到Code optimization了嗎?

十五、請教c的!和 ~ 符號有甚區別??

!是邏輯取反,~是按位取反。

十六、c51編程,讀埠,還要不要先輸出1?

我怎麼看到有的要,有的不要,請高手給講講,到底咋回事?謝了

要輸出1的,除非你能保證之前已經是1,而中間沒有輸出過其他值。

十七、當定時器1(T1)用於產生波特率時,P3^5還是否可以用作正常的I/O口呢?

p3.5完全可以當普通的io使用

十八、C51中 INT 轉換為 2個CHAR?

各位高手:

C51中 INT 轉換為 CHAR 如何轉換諸如:

X = LOW(Z);

Y = HIGH(Z);

答:

x=(char)z;

y=(char)(z>>8);

十九、如果我想使2EH的第7位置1的話,用位操作可以嗎?

現在對位操作指令我一些不太明白請各位多多指教:

如 SETB 07H 表示的是20H.7置1,對嗎?(我在一本書上是這么看到的)

那麼如果我想使2EH的第7位置1的話,象我舉的這個例子怎麼表示呢?謝謝!

SETB 77H

setb (2eh-20h)*8+7

20h-2fh每位元組有8個可位操作(00h-7fh),其它RAM不可位直接操作

二十、char *addr=0xc000 和char xdata *addr=0xc000有何區別?

char *addr=0xc000;

char xdata *addr=0xc000;

除了在內存中佔用的位元組不同外,還有別的區別嗎?

char *addr=0xc000; 是通用定義,指針變數 addr 可指向任何內存空間的值;

char xdata *addr=0xc000; 指定該指針變數只能指向 xdata 中的值;

後一種定義中該指針變數(addr)將少佔用一個存儲位元組。

uchar xdata *addr=0xc000;指針指向外ram;

如果:data uchar xdata *addr=0xc000;指針指向外ram但指針本身存在於內ram(data)



以此類推可以idata uchar xdata *addr=0xc000;pdata uchar xdata *addr=0xc000;

data uchar idata *addr=0xa0;.........

二十一、while(p1_0)的執行時間?

假設,P1_0為單片機P1口的第一腳,請問,

while(P1_0)

{

P1_0=0;

}

while(!P1_0)

{

P1_0=1;

}

以上代碼,在KEIL C中,需要多長時間,執行完。能具體說明while(P1_0)的執行時間嗎?

模擬運行看看就知道了,

我模擬了試了一下,約14個周期

二十二、怎樣編寫C51的watchdog程序?

各位大蝦,我用KEIL C51 編寫了一個帶外部開門狗的程序,可程序無法運行起來,經過查

找,發現程序在經過C51編譯後,在MAIN()函數的前部增加了一端初始化程序,等到進入

主程序設置開門狗時,開門狗已經時間到,將我的程序復位了,請問我怎樣才能修改這一端

初始花程序,使他一運行,就設置開門狗?

可以在startup.a51中加入看門狗刷新指令,當然用匯編,然後重新編譯startup.a51

,將他和你的程序連接即可。新的startup.a51會自動代替系統默認的啟動模塊。

二十三、keil C51 怎樣把修改的startup.a51 加到工程文件中

直接加入即可

注意不要改動?STACK,?C_START,?C_STARTUP等符號。startup.a51直接加入項目,不用修改也可。可在內面自己修改匯編的一些限制或堆棧指針。

二十四、關於波特率的設置

我在設定串口波特率時發現一個問題:在晶體震盪器為11.0592MHz時,若設9600BPS的話,

TH1=0XFD,TL1=0XFD,而要設19200BPS的話,TH1、TL1有否變化,如果沒變,為什麼?

如果變了,又為什麼?(因為我看書上倆個是一樣的),希望大家點撥。

答:

當電源控制寄存器(PCON)第BIT7(SMOD)為1時波特率加倍。

TH1和TL1的值不變.

二十五、如何在C中聲明保留這部分RAM區不被C使用?

我不知道在C源程序中怎麼控制這個,但在匯編程序中加入下面一段就行:

DSEG AT 20H

AA: DS 10

這樣C51就不會佔用20H--29H了

或者在c51里這樣定義:

uchar data asm_buff[10] _at_ 0x20;

二十六、問浮點運算問題

我在用C51時發現它對傳遞浮點參數的個數有限制,請問:

1)參數是以全局變數的形式傳遞的,請問以全局變數的形式傳遞的參數也有限制嗎?

2)這種傳遞浮點參數的限制有多少呢?

3)float*float的結果是float類型還是double類型?能否直接賦值給float類型的變數?

答:

由於KEIL C51的參數傳遞是通過R0-R7來傳遞的,所以會有限制。

不過KEIL提供了一個編譯參數,可以支持更多參數的傳遞。具體

的內容見KEIL的PDF文檔。

我建議你把多個要傳遞的參數定義到指針或結構體中去,傳遞參

數通過指針或結構進行,這樣好一些。

第3個問題回答是YES,你自己試試不就知道了。

二十七、如何在某一個地址定義ram

用_at_ 命令,這樣可以定位靈活一點的地址

uchar xdata dis_buff[16] _at_ 0x6020 ;//定位RAM

將dis_buff[16]定位在0x6020開始的16個位元組

二十八、keil c中,用什麼函數可以得到奇偶校驗位?

例如32位數據,將四個位元組相互異或後檢查P即可,若耽心P被改變,可用內嵌匯編。

#include

unsigned char parity(unsigned char x){

x^=x;

if(P)return(1);

else return(0);

}

unsigned char parity2(unsigned int x){

#pragma asm

mov a,r7

xrl ar6,a

#pragma endasm

if(P)return(1);

else return(0);

}

5. C語言實驗報告總結

你只需要按那個模版就行,那些內容就改成你的作業
班級: 學號: 姓名:
實驗9 指針

一、實驗目的

(1)掌握指針概念,並定義與使用它。

(2)使用數組的指針和指向數組的指針變數。

(3)使用字元串的指針和指向字元串的指針變數。

二、實驗內容

1. 將一個3*3的矩陣轉置,用函數實現。

2. 有n個人圍成一圈,順序排號。從第一個人開始報數(1~3),凡報到3的人退出,問第幾號的人能留下。

三、實驗環境

硬體:(1)學生用微機

(2)多媒體實驗教室

軟體:(1)Windows XP 中文操作系統

(2)VC++ 6.0

四、實驗結果

程序1:

#include<stdio.h>

void main()

{

void move(int *pointer);

int a[3][3],*p,i;

printf("input marix:\n");

for(i=0;i<3;i++)

scanf("%d %d %d",&a[i][0],&a[i][1],&a[i][2]);

p=&a[0][0];

move(p);

printf("matrix:\n");

for(i=0;i<3;i++)

printf("%d %d %d\n",a[i][0],a[i][1],a[i][2]);

}

void move(int *pointer)

{

int i,j,t;

for(i=0;i<3;i++)

for(j=i;j<3;j++)

{

t=*(pointer+3*i+j);

*(pointer+3*i+j)=*(pointer+3*j+i);

*(pointer+3*j+i)=t;

}

}

程序2:

#include<stdio.h>

void main()

{

int i,k,m,n,num[50],*p;

printf("input num of person:");

scanf("%d",&n);

p=num;

for(i=0;i<n;i++)

*(p+i)=i+1;

i=0;

k=0;

m=0;

while(m<n-1)

{

if(*(p+i)!=0)k++;

if(k==3)

{

*(p+i)=0;

k=0;

m++;

}

i++;

if(i==n)i=0;

}

while(*p==0)p++;

printf("the last num is %d\n",*p);

}

結果1:(就是程序運行之後出現的框,截圖後粘貼這里)

結果2:

五、總結:

通過這個實驗的學習, 基本掌握了指針的基本用法。

6. 課程設計的目的和意義

以下是我做課程設計時寫的,希望能夠幫你
目的:
根據課堂講授內容,學生做相應的自主練習,消化課堂所講解的內容;通過調試典型例題或習題積累調試C程序的經驗;通過完成輔導教材中的編程題,逐漸培養學生的編程能力、用計算機解決實際問題的能力。
C語言課程設計過程總結:
回顧起此次課程設計,至今我仍感慨頗多,從理論到實踐,在整整半個月的日子裡,我學到很多很多的東西,不僅鞏固了以前所學過的知識,而且學到了很多在書本上所沒有學到過的內容。通過這次課程設計使我懂得了理論與實際相結合是很重要的,只有理論知識是遠遠不夠的,只有把所學的理論知識與實踐相結合起來,從理論中得出結論,才是真正的知識,才能提高自己的實際動手能力和獨立思考的能力。在設計的過程遇到了各種各樣的問題,同時在設計的過程中發現了自己的不足之處,對以前所學過的知識理解得不夠深刻,掌握得不夠牢固,通過這次課程設計,把以前所學過的知識重新溫故,鞏固了所學的知識。

7. c語言課程的總結

1.先學習C語言的基礎知識。現在正在學C語言的在校學生可以直接進入第2步學習。
2.按照《C語言程序設計入門學習六步曲》進行上機練習。
3.在上機練習時要養成良好的編程風格。點擊查看C語言的編程風格

4.積極參加C、C++興趣小組,養成和老師與同學交流習慣,從而相互收益。有時別人不經意的一句話可能使你茅塞頓開--「一句話點醒夢中人」。

5.及時總結自己的學習經驗,養成寫C語言日記的習慣。軟體有編程日記功能。

6.從網上或教材上找一個自己感興趣的題目(選題時根據自己的能力,可先易後難,培養自己的成就感,如果有了成就感,即使再苦再累還是感覺C語言學習是一件快樂的事,同學們喜歡打游戲,經常通宵達旦地玩游戲也樂而不疲就是這個道理)進行實戰訓練,提高自己的C語言綜合應用能力。

7. 由於C語言靈活、強大,初學者要全面地掌握它是不可能的,因此在學習C語言的過程中,不要在細枝末節上浪費精力(比如++、--用於表達式的計算,實際上是沒有意義的),但一定要熟練掌握C語言的流程式控制制語句、數組、函數、指針等基礎知識的應用,為學習面向對象程序設計打下堅實的基礎。如果這些知識你學不好,要後續學習好C++、可視化的程序設計Visual C++或C++Builder就像空中樓閣,是不現實的。
C語言程序設計入門學習六步曲

筆者在從事教學的過程中,聽到同學抱怨最多的一句話是:老師,上課我也能聽懂,書上的例題也能看明白,可是到自己動手做編程時,卻不知道如何下手。發生這種現象的原因有三個:

一、所謂的看懂聽明白,只是很膚淺的語法知識,而我們編寫的程序或軟體是要根據要解決問題的實際需要控製程序的流程,如果你沒有深刻地理解C語言的語句的執行過程(或流程),你怎麼會編寫程序解決這些實際問題呢?

二、用C語言編程解決實際問題,所需要的不僅僅是C語言的編程知識,還需要相關的專業知識。例如,如果你不知道長方形的面積公式,即使C語言學得再好你也編不出求長方形的面積的程序來。

三、C語言程序設計是一門實踐性很強的課程,「紙上談兵」式的光學不練是學不好C語言的。例如,大家都看過精彩自行車雜技表演,假如,你從來沒有騎過自行車,光聽教練講解相關的知識、規則、技巧,不要說上台表演、就是上路你恐怕都不行。

出現問題原因清楚了,那麼如何學習呢?請你看【C語言學習六步曲】

在程序開發的過程中,上機調試程序是一個不可缺少的重要環節。「三分編程七分調試」,說明程序調試的工作量要比編程大得多。這里以如何上機調試C程序來說明C語言的學習方法。

第一步、驗證性練習

在這一步要求按照教材上的程序實例進行原樣輸入,運行一下程序是否正確。在這一步基本掌握C語言編程軟體的使用方法(包括新建、打開、保存、關閉C程序,熟練地輸入、編輯C程序;初步記憶新學章節的知識點、養成良好的C語言編程風格)。
初學者最容易犯的錯誤是:

1、沒有區分開教材上的數字1和字母l,字母o和數字0的區別,造成變數未定義的錯誤。另一個易錯點是將英文狀態下的逗號,分號;括弧()雙引號""輸入出入成中文狀態下的逗號,分號;括弧(),雙引號「」造成非法字元錯誤。

2、C語言初學者易犯語法錯誤:使用未定義的變數、標示符(變數、常量、數組、函數等)不區分大小寫、漏掉「;」、「{」與「}」、「(」與「)」不匹、控制語句(選擇、分支、循環)的格式不正確、調用庫函數卻沒有包含相應的頭文件、調用未C聲明的自定義函數、調用函數時實參與形參不匹配、數組的邊界超界等。

3、修改C語言語法錯誤時要注意以下兩點:

(1)、由於C語言語法比較自由、靈活,因此錯誤信息定位不是特別精確。例如,當提示第10行發生錯誤時,如果在第10行沒有發現錯誤,從第10行開始往前查找錯誤並修改之。

(2)、一條語句錯誤可能會產生若干條錯誤信息只要修改了這條錯誤,其他錯誤會隨之消失。特別提示:一般情況下,第一條錯誤信息最能反映錯誤的位置和類型,所以調試程序時務必根據第一條錯誤信息進行修改,修改後,立即運行程序,如果還有很多錯誤,要一個一個地修改,即,每修改一處錯誤要運行一次程序。
第二步、照葫蘆畫瓢
在第一步輸入的C程序的基礎上進行試驗性的修改,運行一下程序看一看程序結果發生了什麼變化,分析結果變化的原因,加深新學知識點的理解。事實上這和第一步時同步進行的,實現「輸入」加深知識的記憶,「修改」加深對知識的理解。記憶和理解是相輔相成的,相互促進。

例如:將最簡單的Hello World!程序
#include "stdio.h"
int main()
{
printf("Hello World!\n");
return 0;
}
中的

printf("Hello World!\n");

中的Hello World!改成你的姓名,運行一下程序,看有什麼變化?

再如求1+2+3...+100的和的程序

#include <stdio.h>

main()

{

int i,sum=0;

for(i=1;i<=100;i++)
{
sum=sum+i;
}
printf("sum=%d\n",sum);
}

第1次將for(i=1;i<=100;i++)中的100改成50,運行一下程序,看有什麼變化?

第2次將for(i=1;i<=100;i++)中的i++改成i=i+2,運行一下程序,看有什麼變化?

找出程序結果變化的原因,就加深了對C語句的理解。

第三步、不看教材看是否能將前兩步的程序進行正確地輸入並運行。

在這一步要求不看教材,即使程序不能運行,看能否將其改正,使其能正確運行。目的是對前兩步的記憶、理解進一步強化。

第四步、增強程序的調試能力

在教材中每章都有C語言初學者易犯的錯誤,按照易出錯的類型,將教材中的正確的程序改成錯誤的程序,運行一下程序,看出現的錯誤信息提示,並記下錯誤信息,再將程序改成正確的,運行一下程序。這樣反復修改,就能夠學習C語言程序發生錯誤的原因和修改錯誤的能力。

注意:每次只改錯一個地方,目的是顯示發生該錯誤的真正原因,避免一次改動多個地方,搞清發生錯誤的真正原因,切記!!!!

注意:上機調試程序時要帶一個記錄本,記下英文錯誤提示信息和解決該錯誤問題的方法,積累程序調試經驗,避免在編程犯同樣的錯誤,切記!!!!。

例如,將Hello World程序中語句

printf("Hello World!\n");

中的;改成中文的分號;

運行一下程序,看有什麼結果?

調試程序是一種實踐性很強的事,光紙上談兵是是沒用的,就像游泳運動員只聽教練講解示範,而不親自下水練習,是永遠學不會游泳的。

即使在優秀的程序員編寫程序也會犯錯誤的,可能事最低級的語法錯誤,但他能快速發現錯誤並改正錯誤,而我們C語言初學者面對錯誤提示,不知道發生了什麼錯誤,如何改正,這就事差別。

第五步、研究典型的C語言程序,提高程序設計能力

C語言初學者遇到最多的困惑是:上課也能聽懂,書上的例題也能看明白,可是到自己動手做編程時,卻不知道如何下手。發生這種現象的原因是:所謂的看懂聽明白,只是很膚淺的語法知識,而沒有深刻地理解C語言的語句的執行過程(或流程)。

計算機是按照人的指令(編寫的程序)去執行的,如果不知道這些C語句在計算機中是如何執行的,你怎麼回靈活運用這些知識去解決實際問題呢?

解決問題的方法是要先理解C語言各種語句的流程(即計算機是如何執行這些語句的過程),然後研讀現成C語言經典程序,看懂別人事如何解決問題的,以提高自己的程序設計能力。
第六步、研究課程設計源成序,提高C語言的綜合應用能力.

8. c語言學習總結300字

1.最初接觸C語言時要弄清楚各種變數的定義方法,特別是常用的類型,int、float、char等等,還要掌握各種類型的輸入、輸出格式。這一步做到後,上機就沒有多大的問題了。
2.在對函數的學習過程中,一定要弄明白函數的作用和具體格式。值得強調的是在寫循環程序時,一定要弄清楚循環的條件。
3.對每一個知識點,都應該立即編出對應的程序,有時可能還會有語法錯誤,碰到更好的方法也可以試一下,很多時候你想想代碼怎麼寫和你真的寫出來了是有很大的差距的。
4.學習時一定有很多疑惑的,要及時弄清楚。
5.找一本好的課本,我並不推薦譚浩強的《C語言程序設計》,因為這本書把知識點講的太細碎太理論。我推薦《c語言程序設計:現代方法》這本書,書中奧妙非凡,值得深讀體驗。
6.不要認為上課認真聽課有用,寫程序不可能從課堂上學會太多的,偉大的程序員或者是很多的黑客,不是老師教出來的,你的有自己的想法自己的思路自己的,學習一門語言才有用,也才會得到別人傳教不了的東西。

9. C語言課程設計 貪吃蛇

2.1程序功能介紹

貪吃蛇游戲是一個經典小游戲,一條蛇在封閉圍牆里,圍牆里隨機出現一個食物,通過按鍵盤四個游標鍵控制蛇向上下左右四個方向移動,蛇頭撞倒食物,則食物被吃掉,蛇身體長一節,同時記10分,接著又出現食物,等待蛇來吃,如果蛇在移動中撞到牆或身體交叉蛇頭撞倒自己身體游戲結束。

2.2程序整體設計說明

一個游戲要有開始部分,運行部分,結束部分(實際上開始部分與運行部分是一體的)。

2.2.1設計思路

這個程序的關鍵是表示蛇的圖形以及蛇的移動。用一個小矩形表示蛇的一節身體,身體每長一節,增加一個矩形塊,蛇頭用兩節表示。移動時必須從蛇頭開始,所以蛇不能向相反方向移動,也就是蛇尾不能改作蛇頭。如果不按任何鍵,蛇自行在當前方向上前移,當游戲者按了有效的方向鍵後,蛇頭朝著指定的方向移動,一步移動一節身體,所以當按了有效的方向鍵後,先確定蛇頭的位置,然後蛇身體隨著蛇頭移動,圖形的實現是從蛇頭的新位置開始畫出蛇,這時由於沒有慶平的原因,原來蛇的位置和新蛇的位置差一個單位,所以看起來社會多一節身體,所以將蛇的最後一節用背景色覆蓋。食物的出現和消失也是畫矩形塊和覆蓋矩形塊

2.2.2數據結構設計及用法說明

開始部分:

游戲是運行在圖形模式下的,所以第一步一定是初始化圖形模式,接著要有開始的界面,就像書有封面一樣,我設置了一個游戲的標題畫面,除了游戲標題畫面我還設置了一個歡迎畫面。標題畫面以後,還要為游戲的運行部分作初始化,包括繪制游戲運行時的背景,對游戲某些重 要變數的初始化。

運行部分:

作為游戲的核心部分,這里包括的函數比較多,也就是模塊比較多,首先讓我模擬一下貪吃蛇的游戲模式:某個世界上突然出現一條蛇,它很短,它的運動神經異常,它沒法停止自己的多動症在它的世界裡就只有食物,它很餓,也很貪吃;同樣在不明原因的情況下,食物從天而降,可惜的是沒有落到嘴邊;飢餓的主人公,不管它有沒有毒,也不問食物的來歷,徑直向食物爬去;它吃到食物啦,它超出想像的同化能力讓食物很快的成為自己身體的一部分,它的身子變長啦。當它吃到第一顆食物時,上帝有給它第二顆,於是它吃了第二顆,於是又變長了,於是又有第三顆……它的身子是一直的加長,它不管自己過長身體的麻煩——轉身不便,繼續吃下去,現在它是直接把巴張大,好讓食物有個綠色通道。但是在某天的下午,它咬到了自己,它才想起自己是一條毒蛇,於是暈死過去(不是毒死);又或者它往食物沖鋒的時候,它失去控制,撞到了牆上。

第一輪循環:第一步,出現食物;第二步,蛇不停運動;第三步,檢查蛇是撞到自己或牆壁;由第四步起游戲有兩條支線(A、B):

A :第四步,蛇沒有碰到自己或牆壁,蛇繼續前進,繪制蛇的動作;第五步,判斷蛇是否吃到食物,如果蛇吃到食物,身子變長,原來的食物消失;第六步,讓玩家輸入控制指令,讓蛇在下一輪循環的第二步改變運動方向;第七步,第二輪循環的第一步,重復第一輪的步驟;

B:第四步,蛇碰到自己或牆壁,終止游戲。

結束部分:

游戲結束時,顯示「GAME OVER」,已經是約定俗成的規律了,我的游戲也不例外。除了游戲結束畫面外,我還設置了一個游戲退出畫面,「善始善終」嘛。

有了上述的大致劃分,我把整個程序劃分成(13+2)個模塊(其實就是函數)

2.2.3程序結構(流程圖)

圖2.1流程圖

依據所需要處理的任務要求,規劃輸入數據和輸出結果,決定存放數據的數據結構。

C語言中數據結構集中體現在數據類型上,因此在進行C語言程序設計時,應統籌規劃程序中所使用的變數,數組,指針等,以及它們的類型等。這點是很重要的,如果在此期間選擇不合適的變數或者數組,將來修改就十分困難。

現在分析一下貪吃蛇游戲中的元素,繼而得出與它們對應的在程序中的描述:

蛇:

基本描述:長度,顏色,位置。

對應數據與數據類型:長度—雖然可以用坐標表示,但是這樣的話,運算量將很大,所以換算成較大的單位—節數,以固定長度的每節描述;坐標--整型;顏色--整型; 位置--X,Y坐標。

增加的描述:蛇運動的方向,蛇的生命。

對應數據與數據類型:這些描述是為了與程序的按鍵的輸入部分與判斷游戲結束部分相聯系而設的。方向只有四個方向:上下左右。可以設置與之對應的四個整型數:3、4、2、1。生命就只有兩種情況:死或生,對應0或1。

食物:

基本描述:顏色,位置。

對應數據與數據類型:由於顏色設成固定的,所以不再討論。位置—X、Y坐標。

增加的描述:食物的存在。

對應數據與數據類型:這是為了避免重復出現食物而設置的,與繪制食物的函數有聯系。只有兩個值:0或1(沒有食物或有食物)

其他的元素:牆,由於它在顯示上是作為背景而存在的,所以並沒有什麼說明實際的牆壁就是四條直線組成的邊框,由坐標描述。

還需要的變數:鍵盤鍵入的鍵值(作為全局變數,整型);經常要使用的循環變數;自定義的填充圖案;說明文字的字元數組;游戲的記分;游戲的速度(蛇的速度)。

圖2.2蛇的不停運動的關鍵演算法的流程圖

2.2.4各模塊的功能及程序說明

主要模塊的實現思路和演算法的流程圖說明:

關鍵所在——蛇不停移動的Snakemove():

蛇的不停移動,就是蛇的下一節取代前一節的位置,在計算機中就是蛇下一節的位置坐標變成前一節的位置坐標。在上文中,已定義蛇的位置坐標為數組類型,一組坐標對應一節的位置,假設有i+1節,由0到i節,第i節的坐標取第i-1節的坐標,第i-1節的坐標取第i-2節的坐標……直到第1節取第0節的坐標。而第0節的坐標,即蛇頭的坐標要往某個方向變化,變化量為蛇每節的長度。蛇的這種坐標輪換需要循環語句使其繼續下去。

2.2.5程序結果

運行程序得到如下初始界面圖:

圖2.3程序結果圖

用一個小矩形表示蛇的一節身體,身體每長一節,增加一個矩形塊,蛇頭用兩節表示:

圖2.4程序結果圖

蛇沒有碰到自己或牆壁,蛇繼續前進:

圖2.5程序結果圖

游戲結束時,顯示「GAME OVER」

圖2.6程序結果圖

2.3程序源代碼及注釋

#define N 200

#include <graphics.h>

#include <stdlib.h>

#include <dos.h>

#define LEFT 0x4b00

#define RIGHT 0x4d00

#define DOWN 0x5000

#define UP 0x4800

#define ESC 0x011b

int i,key;

int score=0;/*得分*/

int gamespeed=50000;/*游戲速度自己調整*/

struct Food{

int x;/*食物的橫坐標*/

int y;/*食物的縱坐標*/

int yes;/*判斷是否要出現食物的變數*/

}food;/*食物的結構體*/

struct Snake{

int x[N];

int y[N];

int node;/*蛇的節數*/

int direction;/*蛇移動方向*/

int life;/* 蛇的生命,0活著,1死亡*/

}snake;

void Init(void);/*圖形驅動*/

void Close(void);/*圖形結束*/

void DrawK(void);/*開始畫面*/

void GameOver(void);/*結束游戲*/

void GamePlay(void);/*玩游戲具體過程*/

void PrScore(void);/*輸出成績*/

/*主函數*/

void main(void){

Init();/*圖形驅動*/

DrawK();/*開始畫面*/

GamePlay();/*玩游戲具體過程*/

Close();/*圖形結束*/}

/*圖形驅動*/

void Init(void){

int gd=DETECT,gm;

registerbgidriver(EGAVGA_driver);

initgraph(&gd,&gm,"c:\program files\winyes\tc20h\bgi");

cleardevice();}

/*開始畫面,左上角坐標為(50,40),右下角坐標為(610,460)的圍牆*/

void DrawK(void){

/*setbkcolor(LIGHTGREEN);*/

setcolor(11);

setlinestyle(SOLID_LINE,0,THICK_WIDTH);/*設置線型*/

for(i=50;i<=600;i+=10)/*畫圍牆*/ {

rectangle(i,40,i+10,49); /*上邊*/

rectangle(i,451,i+10,460);/*下邊*/ }

for(i=40;i<=450;i+=10) {

rectangle(50,i,59,i+10); /*左邊*/

rectangle(601,i,610,i+10);/*右邊*/ }}

/*玩游戲具體過程*/

void GamePlay(void){

randomize();/*隨機數發生器*/

food.yes=1;/*1表示需要出現新食物,0表示已經存在食物*/

snake.life=0;/*活著*/

snake.direction=1;/*方嚮往右*/

snake.x[0]=100;snake.y[0]=100;/*蛇頭*/

snake.x[1]=110;snake.y[1]=100;

snake.node=2;/*節數*/

PrScore();/*輸出得分*/

while(1)/*可以重復玩游戲,壓ESC鍵結束*/ {

while(!kbhit())/*在沒有按鍵的情況下,蛇自己移動身體*/ {

if(food.yes==1)/*需要出現新食物*/ {

food.x=rand()%400+60;

food.y=rand()%350+60;

while(food.x%10!=0)/*食物隨機出現後必須讓食物能夠在整格內,這樣才可以讓蛇吃到*/

food.x++;

while(food.y%10!=0)

food.y++;

food.yes=0;/*畫面上有食物了*/ }

if(food.yes==0)/*畫面上有食物了就要顯示*/ {

setcolor(GREEN);

rectangle(food.x,food.y,food.x+10,food.y-10); }

for(i=snake.node-1;i>0;i--)/*蛇的每個環節往前移動,也就是貪吃蛇的關鍵演算法*/ {

snake.x[i]=snake.x[i-1];

snake.y[i]=snake.y[i-1]; }

/*1,2,3,4表示右,左,上,下四個方向,通過這個判斷來移動蛇頭*/

switch(snake.direction) {

case 1:snake.x[0]+=10;break;

case 2: snake.x[0]-=10;break;

case 3: snake.y[0]-=10;break;

case 4: snake.y[0]+=10;break; }

for(i=3;i<snake.node;i++)/*從蛇的第四節開始判斷是否撞到自己了,因為蛇頭為兩節,第三節不可能拐過來*/ {

if(snake.x[i]==snake.x[0]&&snake.y[i]==snake.y[0]) {

GameOver();/*顯示失敗*/

snake.life=1;

break; } }

if(snake.x[0]<55||snake.x[0]>595||snake.y[0]<55||

snake.y[0]>455)/*蛇是否撞到牆壁*/ {

GameOver();/*本次游戲結束*/

snake.life=1; /*蛇死*/ }

if(snake.life==1)/*以上兩種判斷以後,如果蛇死就跳出內循環,重新開始*/

break;

if(snake.x[0]==food.x&&snake.y[0]==food.y)/*吃到食物以後*/ {

setcolor(0);/*把畫面上的食物東西去掉*/

rectangle(food.x,food.y,food.x+10,food.y-10);

snake.x[snake.node]=-20;snake.y[snake.node]=-20;

/*新的一節先放在看不見的位置,下次循環就取前一節的位置*/

snake.node++;/*蛇的身體長一節*/

food.yes=1;/*畫面上需要出現新的食物*/

score+=10;

PrScore();/*輸出新得分*/ }

setcolor(4);/*畫出蛇*/

for(i=0;i<snake.node;i++)

rectangle(snake.x[i],snake.y[i],snake.x[i]+10,

snake.y[i]-10);

delay(gamespeed);

setcolor(0);/*用黑色去除蛇的的最後一節*/

rectangle(snake.x[snake.node-1],snake.y[snake.node-1],

snake.x[snake.node-1]+10,snake.y[snake.node-1]-10); } /*endwhile(!kbhit)*/

if(snake.life==1)/*如果蛇死就跳出循環*/

break;

key=bioskey(0);/*接收按鍵*/

if(key==ESC)/*按ESC鍵退出*/

break;

else

if(key==UP&&snake.direction!=4)

/*判斷是否往相反的方向移動*/

snake.direction=3;

else

if(key==RIGHT&&snake.direction!=2)

snake.direction=1;

else

if(key==LEFT&&snake.direction!=1)

snake.direction=2;

else

if(key==DOWN&&snake.direction!=3)

snake.direction=4;

}/*endwhile(1)*/}

/*游戲結束*/

void GameOver(void){

cleardevice();

PrScore();

setcolor(RED);

settextstyle(0,0,4);

outtextxy(200,200,"GAME OVER");

getch();}

/*輸出成績*/

void PrScore(void){

char str[10];

setfillstyle(SOLID_FILL,YELLOW);

bar(50,15,220,35);

setcolor(6);

settextstyle(0,0,2);

sprintf(str,"score:%d",score);

outtextxy(55,20,str);}

/*圖形結束*/

void Close(void){

getch();

closegraph();

}