亚洲免费av电影一区二区三区,日韩爱爱视频,51精品视频一区二区三区,91视频爱爱,日韩欧美在线播放视频,中文字幕少妇AV,亚洲电影中文字幕,久久久久亚洲av成人网址,久久综合视频网站,国产在线不卡免费播放

        ?

        C語言教學(xué)中的幾個(gè)常見問題

        2009-06-20 08:45:46
        計(jì)算機(jī)教育 2009年10期
        關(guān)鍵詞:程序設(shè)計(jì)教學(xué)

        黃 宇

        文章編號:1672-5913(2009)10-0096-03

        摘要:作者在多年的C語言教學(xué)過程中,對學(xué)生中經(jīng)常遇到的問題進(jìn)行了一些總結(jié)。本文就學(xué)生中經(jīng)常遇到的5個(gè)帶有普遍性的問題,通過C程序示例進(jìn)行了分析,指出了出現(xiàn)錯(cuò)誤的原因,給出了改正的方法。

        關(guān)鍵詞:C語言;程序設(shè)計(jì);教學(xué)

        中圖分類號:G642

        文獻(xiàn)標(biāo)識碼:B

        1引言

        隨著計(jì)算機(jī)應(yīng)用技術(shù)的普及,大學(xué)中很多專業(yè)都開設(shè)了計(jì)算機(jī)編程課程。在非計(jì)算機(jī)專業(yè)中,大多以教授C語言編程為主。本人長期從事對非計(jì)算機(jī)專業(yè)學(xué)生的C語言編程課的教學(xué)工作,在長期的教學(xué)實(shí)踐中,發(fā)現(xiàn)了一些學(xué)生在編程中經(jīng)常會遇到的問題。在此,就幾個(gè)典型的常見問題,展開一些探討。這些問題的解決,對于更深入的理解C語言,將起到一定的幫助作用。

        2幾個(gè)常見問題

        2.1無符號數(shù)運(yùn)算問題

        大家知道,在C語言中,不同類型的數(shù)據(jù)一起運(yùn)算時(shí)是按照隱式類型轉(zhuǎn)換的規(guī)則進(jìn)行的,也就是將兩個(gè)類型不一致的數(shù)據(jù)首先轉(zhuǎn)換成一致的,然后再進(jìn)行運(yùn)算。其轉(zhuǎn)換的基本原則有兩點(diǎn),一是小數(shù)據(jù)類型向大數(shù)據(jù)類型轉(zhuǎn)換,二是有符號類型向無符號類型轉(zhuǎn)換。比如,當(dāng)一個(gè)float類型數(shù)據(jù)和一個(gè)double類型的數(shù)據(jù)進(jìn)行運(yùn)算時(shí),就是首先將float類型的數(shù)據(jù)轉(zhuǎn)換成double類型的數(shù)據(jù),然后再進(jìn)行運(yùn)算;而當(dāng)一個(gè)int類型的數(shù)據(jù)和一個(gè)unsigned int類型的數(shù)據(jù)進(jìn)行運(yùn)算時(shí),則首先把int類型的數(shù)據(jù)轉(zhuǎn)換為unsigned int類型的數(shù)據(jù),然后再進(jìn)行運(yùn)算。對于第一種情況,一般不會遇到問題,但是對于第二種情況,初學(xué)者往往注意不到這種轉(zhuǎn)換中可能會隱含的問題,導(dǎo)致程序運(yùn)行結(jié)果出現(xiàn)與自己設(shè)想不一致的情況。

        下面給一個(gè)具體的例子:

        #include

        int main()

        {

        unsigned int n = 1;

        int m = -1;

        if (m < n)printf("m < n");

        else printf("m >= n");

        return 1;

        }

        在這段程序中,n = 1,m = -1,顯然應(yīng)該是m= n。初學(xué)者遇到這種情況,往往百思不得其解,最終往往會歸咎于是不是系統(tǒng)出現(xiàn)了問題。

        為什么會出現(xiàn)這種情況呢?這是因?yàn)閚是unsigned int類型的,而m是int類型的,在m和n進(jìn)行比較運(yùn)算時(shí),由于二者的類型不一致,首先要進(jìn)行類型轉(zhuǎn)換。按照C語言隱式類型轉(zhuǎn)換規(guī)則,有符號類型的int轉(zhuǎn)換為無符號類型的unsigned int。這樣,m(=-1)中的符號位被當(dāng)成了“數(shù)字”進(jìn)行轉(zhuǎn)換,有符號的-1成為了無符號的4294967295(四字節(jié)的情況下。如果是二字節(jié)的則是65535)。而4294967295當(dāng)然要大于1了,所以就有了以上的運(yùn)行結(jié)果。

        不單單是在比較運(yùn)算中會出現(xiàn)這種情況,在其他運(yùn)算中,比如加減乘除等,也一樣會有類似的情況出現(xiàn)。所以,當(dāng)有符號和無符號的數(shù)據(jù)混合運(yùn)算時(shí),一定要注意這個(gè)問題,除非特殊情況,應(yīng)盡量避免有符號和無符號的混合運(yùn)算。

        2.2計(jì)算數(shù)組的長度

        在C語言中,操作符sizeof( )可以計(jì)算一個(gè)類型或者一個(gè)變量所占用的字節(jié)數(shù)。比如:sizeof(int)或者sizeof(x)(假定x是int類型的),當(dāng)一個(gè)整數(shù)占用4個(gè)字節(jié)時(shí),就可以得到4的結(jié)果。

        再比如,一個(gè)整數(shù)數(shù)組:int a[8];

        可以通過sizeof(a)/sizeof(int)得到數(shù)組a的元素個(gè)數(shù)。因?yàn)閟izeof(a)得到的是a數(shù)組占用的總字節(jié)數(shù),除以每個(gè)int所占用的字節(jié)數(shù)sizeof(int),就是該數(shù)組的長度。

        由于很多情況下需要知道一個(gè)數(shù)組的長度,比如在對一個(gè)數(shù)組排序時(shí),因此,有些初學(xué)者就利用sizeof在函數(shù)中計(jì)算數(shù)組的長度。舉例如下:

        mysort(int a[])

        {

        int len;

        len = sizeof(a)/sizeof(int); //得到數(shù)組a的長度

        //以下對a進(jìn)行排序

        }

        但是往往會發(fā)現(xiàn),這樣的結(jié)果并不正確,len經(jīng)常得到的是1(假定是32位系統(tǒng),一個(gè)整數(shù)占4個(gè)字節(jié))。這又是為什么呢?

        這個(gè)問題,與C語言中數(shù)組參數(shù)的傳遞方式有關(guān)。在C語言中,當(dāng)一個(gè)數(shù)組當(dāng)作參數(shù)傳遞時(shí),數(shù)組被轉(zhuǎn)換為指針。在上面的例子中,無論你在函數(shù)定義是mysort(int a[])還是mysort(int a[100]),在函數(shù)內(nèi)部,a均被轉(zhuǎn)換成int *a類型,與定義mysort(int *a)是一致的。因此,在函數(shù)內(nèi)部,當(dāng)計(jì)算sizeof(a)時(shí),實(shí)際上計(jì)算的是sizeof(int *)。因此,當(dāng)作為形參時(shí),無論你的mysort(int a[N])定義中,有無N,或者N是多大,sizeof(a)得到的都是4(假定在32位系統(tǒng)中)。

        因此,在一個(gè)函數(shù)內(nèi)部,是無法得到一個(gè)數(shù)組參數(shù)的長度的,其長度只能通過參數(shù)進(jìn)行傳遞。所以,上述的排序函數(shù)應(yīng)該定義成如下的形式:

        mysort(int a[], int len)

        {

        //以下對a進(jìn)行排序

        }

        2.3常量字符串問題

        在學(xué)習(xí)完字符串的操作之后,同學(xué)們往往會編寫一些簡單的練習(xí)程序,這時(shí)經(jīng)常會遇到一些“莫名其妙”的情況,使得程序不能正確運(yùn)行。

        比如下面這個(gè)程序,非常簡單,就是把字符串"abcde"中的'a'換成'A':

        int main()

        {

        char *p = "abcde";

        p[0] = 'A';

        return 1;

        }

        程序編譯沒有問題,一運(yùn)行就出現(xiàn)錯(cuò)誤。這是為什么呢?

        在這個(gè)程序中,字符串"abcde"是一個(gè)常量,指針p指向了這個(gè)常量。而“常量”顧名思義是不能修改的,而該程序試圖通過指針p修改一個(gè)常量字符串,導(dǎo)致運(yùn)行錯(cuò)誤。

        把程序修改如下,就沒有問題了:

        int main()

        {

        char p[] = "abcde";

        p[0] = 'A';

        return 1;

        }

        這是因?yàn)閜是一個(gè)字符數(shù)組,并通過初始化的方法對該數(shù)組進(jìn)行了賦值。雖然字符數(shù)組p也是一個(gè)字符串,但是p不是常量,可以修改,因此就不會出現(xiàn)運(yùn)行錯(cuò)誤了。

        同樣,如果是這樣,也不會出現(xiàn)錯(cuò)誤:

        int main()

        {

        char p[] = "abcde";

        char *q = p;

        q[0] = 'A';

        return 1;

        }

        因?yàn)樵谶@里q指向是字符數(shù)組p,而不是字符串常量"abcde"。

        2.4文件結(jié)束判斷問題

        在C語言中,函數(shù)feof( )可以判斷文件結(jié)束,但是初學(xué)者在使用feof( )時(shí),經(jīng)常會犯錯(cuò)誤。請看下面這個(gè)例子,該程序?qū)崿F(xiàn)將文件a.txt拷貝到b.txt的功能,通過feof判斷a.txt是否結(jié)束,在結(jié)束之前,每次讀一個(gè)字符,并寫到b.txt中。程序如下:

        int main()

        {

        FILE *pi, *po;

        char c;

        pi = fopen("a.txt", "rb");

        po = fopen("b.txt", "wb");

        while (!feof(pi))

        {

        c = fgetc(pi);

        fputc(c, po);

        }

        fclose(pi);

        fclose(po);

        return 1;

        }

        程序很簡單,看似沒有什么錯(cuò)誤。但是這里卻隱含了一個(gè)初學(xué)者經(jīng)常會犯的錯(cuò)誤。運(yùn)行一下該程序,就會發(fā)現(xiàn)在b.txt的最后,會“奇怪”地多出了一個(gè)字符。

        問題出現(xiàn)在什么地方呢?主要是對feof的認(rèn)識有誤造成的。

        仔細(xì)看一下feof的功能,會發(fā)現(xiàn)當(dāng)讀完了最后一個(gè)字符后,feof還是保持“假”,只有當(dāng)讀完了最后一個(gè)字符再試圖讀文件時(shí),feof才為真。也就是說,feof判斷是否到達(dá)文件尾比實(shí)際情況要“晚”一步。按照上面的程序,當(dāng)fgetc從a.txt中讀完了最后一個(gè)字符后,feof并不馬上為真,還要循環(huán)再讀一次a.txt,并通過fputc函數(shù)將這次得到的結(jié)果(在字符c中)寫入到b.txt中,造成了b.txt中多了一個(gè)字符。而這時(shí),feof才變成了真,程序退出循環(huán)結(jié)束。

        明白了這一點(diǎn),程序按照如下方式增加一個(gè)if語句就可以了:

        int main()

        {

        FILE *pi, *po;

        char c;

        pi = fopen("a.txt", "rb");

        po = fopen("b.txt", "wb");

        while (!feof(pi))

        {

        c = fgetc(pi);

        if (feof(pi)) break;//新增加的一個(gè)判斷

        fputc(c, po);

        }

        fclose(pi);

        fclose(po);

        return 1;

        }

        2.5結(jié)構(gòu)體的大小問題

        通過sizeof可以計(jì)算一個(gè)結(jié)構(gòu)體占用的字節(jié)數(shù),比如下面一段程序是計(jì)算結(jié)構(gòu)體S所占的字節(jié)數(shù)。程序的輸出應(yīng)該是多少呢?

        int main()

        {

        struct S

        {

        char a;

        int n;

        };

        int n;

        n = sizeof(struct S);

        printf("%d", n);

        return 1;

        }

        char占1個(gè)字節(jié),int占4個(gè)字節(jié),初學(xué)者往往會回答S長度是5。但是一運(yùn)行程序,發(fā)現(xiàn)輸出的結(jié)果卻是8。見到這樣的結(jié)果,初學(xué)者往往又不得其解,不知為什么會這樣。

        這里涉及的就是所謂的地址對齊的問題,編譯程序,在默認(rèn)的情況下,會按照一定的原則,比如讓寬度為2的基本數(shù)據(jù)類型(short等)都位于能被2整除的地址上,讓寬度為4的基本數(shù)據(jù)類型(int等)都位于能被4整除的地址上等等,這樣做的原因是為了加快程序的運(yùn)行速度。也就是說,對結(jié)構(gòu)體進(jìn)行了一定的填充,使得它的成員的地址滿足一定的要求。關(guān)于如何對齊問題涉及的內(nèi)容比較多,這里就不詳細(xì)解釋了,有興趣的讀者可以參考有關(guān)計(jì)算機(jī)組成原理方面的書。

        3結(jié)束語

        我們在C語言教學(xué)過程中,經(jīng)常會遇到學(xué)生提出的各種問題,有些問題是個(gè)別性的,有些問題則是普遍性的,從學(xué)生遇到的最多的問題中,整理出了這5個(gè)具有普遍性的問題,希望對有關(guān)C語言的教與學(xué)能起到一定的幫助。

        參考文獻(xiàn):

        [1] 薛勝軍. 計(jì)算機(jī)組成原理[M]. 武漢:華中科技大學(xué)出版社,2000.

        [2] 王誠, 劉衛(wèi)東,宋佳興. 計(jì)算機(jī)組成與設(shè)計(jì)[M]. 3版. 北京:清華大學(xué)出版社,2008.

        [3] 嚴(yán)蔚敏,吳偉民.數(shù)據(jù)結(jié)構(gòu)(C語言版)[M].北京:清華大學(xué)出版社,2006.

        [4] 譚浩強(qiáng). C程序設(shè)計(jì)[M]. 北京:清華大學(xué)出版社,2006.

        [5] David J. Kruglinski. Visual. C++技術(shù)內(nèi)幕[M]. 4版. 北京:清華大學(xué)出版社,2001.

        [6] H.M.Deitel,P.J.Deitel. C程序設(shè)計(jì)教程[M]. 北京:機(jī)械工業(yè)出版社,2001.

        猜你喜歡
        程序設(shè)計(jì)教學(xué)
        微課讓高中數(shù)學(xué)教學(xué)更高效
        甘肅教育(2020年14期)2020-09-11 07:57:50
        基于Visual Studio Code的C語言程序設(shè)計(jì)實(shí)踐教學(xué)探索
        如何讓高中生物教學(xué)變得生動(dòng)有趣
        甘肅教育(2020年12期)2020-04-13 06:25:34
        從細(xì)節(jié)入手,談PLC程序設(shè)計(jì)技巧
        電子制作(2019年9期)2019-05-30 09:42:04
        “自我診斷表”在高中數(shù)學(xué)教學(xué)中的應(yīng)用
        東方教育(2017年19期)2017-12-05 15:14:48
        對外漢語教學(xué)中“想”和“要”的比較
        高職高專院校C語言程序設(shè)計(jì)教學(xué)改革探索
        OBE理念下基于Greenfoot的Java程序設(shè)計(jì)課程教學(xué)改革
        PLC梯形圖程序設(shè)計(jì)技巧及應(yīng)用
        三級甲等公立醫(yī)院績效考核程序設(shè)計(jì)
        国产九色AV刺激露脸对白| 久久96国产精品久久久| 人妻少妇边接电话边娇喘| 高潮抽搐潮喷毛片在线播放| 亚洲欧美一区二区三区 | 国产精品后入内射日本在线观看| 91中文人妻丝袜乱一区三区 | 亚洲午夜无码视频在线播放| 视频一区二区三区中文字幕狠狠 | 成人激情五月天| 欧美丰满熟妇bbbbbb百度| 久久久久久一本大道无码| 精品综合久久88少妇激情| 国产强被迫伦姧在线观看无码| 久久久久国产精品免费免费搜索| 久久99精品这里精品动漫6| 国产精品高湖呻呤久久av| 中文字幕av永久免费在线| 国产精品无码无在线观看| 天躁夜夜躁狼狠躁| 色系免费一区二区三区| av在线一区二区三区不卡| 成人试看120秒体验区| 国产精品麻豆aⅴ人妻| 国产精品一区二区资源| 国产成人高清亚洲一区二区| 性色av一二三天美传媒| 中文字幕有码无码av| 日韩av中出在线免费播放网站| 国产熟女白浆精品视频二| 国产精品久久久久久久久电影网| 男人扒开女人下面狂躁小视频 | 97精品一区二区视频在线观看| 免费毛片视频网站| 精品国产麻豆免费人成网站| 风韵丰满熟妇啪啪区老熟熟女| 欧美亚洲日韩国产人成在线播放| 久久aⅴ无码av高潮AV喷| 蜜桃码一区二区三区在线观看| 午夜精品久久久久久久| 天天天天躁天天爱天天碰|