• <li id="iii0i"></li>
    <li id="iii0i"></li>
  • 首頁(yè) > 職業(yè)資格  > 

    C語(yǔ)言函數的定義 全球熱頭條

    2023-09-09   來(lái)源:萬(wàn)能知識網(wǎng)

    C語(yǔ)言函數的定義

    引導語(yǔ):函數表示每個(gè)輸入值對應唯一輸出值的一種對應關(guān)系。這種關(guān)系使一個(gè)集合里的每一個(gè)元素對應到另一個(gè)(可能相同的)集合里的唯一元素。以下是小編分享給大家的C語(yǔ)言函數的定義,歡迎參考學(xué)習!

    一、函數的定義


    【資料圖】

    一個(gè)函數包括函數頭和語(yǔ)句體兩部分。

    函數頭由下列三不分組成:

    函數返回值類(lèi)型

    函數名

    參數表

    一個(gè)完整的函數應該是這樣的:

    函數返回值類(lèi)型 函數名(參數表)

    {

    語(yǔ)句體;

    }

    函數返回值類(lèi)型可以是前面說(shuō)到的某個(gè)數據類(lèi)型、或者是某個(gè)數據類(lèi)型的指針、指向結構的指針、指向數組的指針。指針概念到以后再介紹。

    函數名在程序中必須是唯一的,它也遵循標識符命名規則。

    參數表可以沒(méi)有也可以有多個(gè),在函數調用的時(shí)候,實(shí)際參數將被拷貝到這些變量中。語(yǔ)句體包括局部變量的聲明和可執行代碼。

    我們在前面其實(shí)已經(jīng)接觸過(guò)函數了,如abs(),sqrt(),我們并不知道它的內部是什么,我們只要會(huì )使用它即可。

    這一節主要講解無(wú)參數無(wú)返回值的函數調用。

    二、函數的聲明和調用

    為了調用一個(gè)函數,必須事先聲明該函數的返回值類(lèi)型和參數類(lèi)型,這和使用變量的道理是一樣的(有一種可以例外,就是函數的定義在調用之前,下面再講述)。

    看一個(gè)簡(jiǎn)單的例子:

    void a(); /*函數聲明*/

    main()

    {

    a(); /*函數調用*/

    }

    void a() /*函數定義*/

    {

    int num;

    scanf(%d,&num);

    printf(%d ,num);

    }

    在main()的前面聲明了一個(gè)函數,函數類(lèi)型是void型,函數名為a,無(wú)參數。然后在main()函數里面調用這個(gè)函數,該函數的作用很簡(jiǎn)單,就是輸入一個(gè)整數然后再顯示它。在調用函數之前聲明了該函數其實(shí)它和下面這個(gè)程序的功能是一樣的:

    main()

    {

    int num;

    scanf(%d,&num);

    printf(%d ,num);

    }

    可以看出,實(shí)際上就是把a()函數里面的所有內容直接搬到main()函數里面(注意,這句話(huà)不是絕對的。)

    我們前面已經(jīng)說(shuō)了,當定義在調用之前時(shí),可以不聲明函數。所以上面的程序和下面這個(gè)也是等價(jià)的:

    void a()

    {

    int num;

    scanf(%d,&num);

    printf(%d ,num);

    }

    main()

    {

    a();

    }

    因為定義在調用之前,所以可以不聲明函數,這是因為編譯器在編譯的時(shí)候,已經(jīng)發(fā)現a是一個(gè)函數名,是無(wú)返回值類(lèi)型無(wú)參數的函數了。

    那么很多人也許就會(huì )想,那我們何必還要聲明這一步呢?我們只要把所有的函數的定義都放在前面不就可以了嗎?這種想法是不可取的,一個(gè)好的程序員總是在程序的開(kāi)頭聲明所有用到的函數和變量,這是為了以后好檢查。

    前面說(shuō)了,在調用之前,必須先聲明函數,所以下面的做法也是正確的(但在這里我個(gè)人并不提倡)。

    main()

    {

    void a();

    a();

    }

    v  oid a()

    {

    int num;

    scanf(%d,&num);

    printf(%d ,num);

    }

    一般來(lái)說(shuō),比較好的程序書(shū)寫(xiě)順序是,先聲明函數,然后寫(xiě)主函數,然后再寫(xiě)那些自定義的函數。

    既然main()函數可以調用別的函數,那么我們自己定義的函數能不能再調用其他函數呢?答案是可以的??聪旅娴睦樱?/p>

    void a();

    void b();

    main()

    {

    a();

    }

    void a()

    {

    b();

    }

    void b()

    {

    int num;

    scanf(%d,&num);

    printf(%d ,num);

    }

    、C語(yǔ)言讀書(shū)筆記--函數

    先來(lái)看看函數的一般形式,嘗試寫(xiě)一個(gè)加法的函數:

    思路是這樣的:首先得有頭文件,頭文件之后就得寫(xiě)主函數,主函數的內部應該就是加法的過(guò)程,我們將所有加法的語(yǔ)句都拿出來(lái)組成一個(gè)函數。代碼如下:

    #include

    int add(int a, int b);

    int main()

    {

    int result = add(3,5);

    printf("sum is %d ", result);

    return 0;

    }

    int add(int a, int b)

    {

    int sum;

    sum = a+b;

    return sum;

    }

    這是一個(gè)最簡(jiǎn)單的函數,描述了一個(gè)加法函數的定義和調用的過(guò)程。

    int add(int a, int b) 成為函數的首部。

    有了首部之后,就得考慮一件事情,將首部復制之后,加上一個(gè)分號,粘貼在主函數之前,作為函數的原型聲明。試想,我們在主函數里邊是不是要先定義變量result才能使用result?那么函數的道理也是一樣的,當程序運行到主函數中語(yǔ)句“int result = add(3,5);”的時(shí)候,如果向上沒(méi)有尋找到add()的定義,那么編譯器一定就會(huì )報錯。所以要不然添加函數的原型聲明,要不然就將函數的定義直接寫(xiě)在主函數之前。

    函數首部int add(int a, int b)中的第一個(gè)int,即add之前的這個(gè)int稱(chēng)為函數的類(lèi)型。表明這個(gè)函數將要返回一個(gè)整數類(lèi)型的值。這個(gè)類(lèi)型可以是C語(yǔ)言中任何被允許的數據類(lèi)型,包括void,意為無(wú)返回值類(lèi)型,即這個(gè)函數不需要返回任何的值。

    函數首部int add(int a, int b)中的add稱(chēng)為函數的名字,簡(jiǎn)稱(chēng)函數名。

    函數首部int add(int a, int b)中int a和int b稱(chēng)為函數的形式參數。這里形式參數理論上可以有無(wú)窮多個(gè),當然,現實(shí)情況下3-5個(gè)就已經(jīng)算是很多了;形式參數中,即使a和b都是int類(lèi)型的,也要分別定義才行;形式參數可以在函數中直接使用,無(wú)須再次定義;形式參數是用來(lái)告訴調用者,你應該給我傳遞來(lái)什么樣子的數據,我好利用你給我的數據在函數中進(jìn)行計算。

    int add(int a, int b){}中的{}就是函數體的內容了。函數需要進(jìn)行的所有的操作都要放在這對大括號中。想必大家也看到了函數體中最后有一條語(yǔ)句是return,這條語(yǔ)句起到的作用就是返回函數計算的結果,在這個(gè)程序中就是將加法的結果返回給主函數。需要注意的是,函數的類(lèi)型和返回值的類(lèi)型必須嚴格一致!

    函數的定義到此為止,接下來(lái)講講函數的調用方式。只要定義好函數,通過(guò)函數名(實(shí)際參數1,實(shí)際參數2,實(shí)際參數n)這種方式就可以調用函數了。例如主函數中的“int result = add(3,5);”,就是調用了add函數。這里,3和5稱(chēng)為實(shí)際參數,即你究竟想讓函數幫你計算哪兩個(gè)數的加法結果,你就在這個(gè)括號里邊寫(xiě)哪幾個(gè)數字。必須要嚴格遵守的`規定:實(shí)際參數和形式參數必須一一對應,數量應該相同,類(lèi)型也保持一致。

    理解了這幾點(diǎn)之后,一個(gè)基本的函數就已經(jīng)可以寫(xiě)出來(lái)了。接下來(lái)來(lái)個(gè)題目嘗試一下:

    輸入精度e,使用公式求π的近似值,精確到最后一項的絕對值小于e。公式:π=1-1/3+1/5-1/7+...

    代碼:

    //首先得有頭文件

    #include

    #include//后邊要使用到fabs絕對值函數

    //然后就是主函數了

    int main(void)

    {

    double pi, e; //定義所需變量

    double f_pi(double e); //原型聲明。函數名只要符合命名規則即可 //因為要求小于e,所以也將這個(gè)e傳遞過(guò)去

    printf("enter e: "); //輸入的提示

    scanf("%lf", &e); // double類(lèi)型的e對應%lf,記住不要缺少&

    printf("pi=%lf ", f_pi(e) ); // 函數返回的是個(gè)double類(lèi)型的值,直接輸出

    return 0;

    }

    double f_pi(double e) //函數首部,形參和實(shí)參一定要對應,可以重名

    {

    int denominator, flag;

    double item, sum;

    //請注意“先定義,然后賦初值再使用”的好習慣!!!

    flag = 1; //負責變換正負符號的變量

    denominator = 1; //分母初值為1,第一項的1為1/1

    item=1.0; //存放每一項的值

    sum=0;

    while(fabs(item)>=e) //滿(mǎn)足條件就循環(huán)

    {

    item=flag*1.0/denominator; //計算每一項的值。flag控制符號

    //1.0必須寫(xiě)出小數位,否則整項就變成一個(gè)整型值

    sum+=item; //累加

    flag = -flag; //符號正負切換

    denominator = denominator + 2;//分母遞增

    }

    return sum; //sum的類(lèi)型和函數的類(lèi)型必須一致

    }

    函數的定義和調用其實(shí)并不難理解,相信很多人困擾在參數的傳遞上,接下來(lái)總結一下函數參數傳遞的幾種方式:

    正常的參數調用,例如int、float、double等一一對應的傳遞。

    無(wú)參數,也無(wú)返回值。例如下列代碼就只是為了輸出一些語(yǔ)句。這種做法在語(yǔ)法上是被允許的,但是并不推薦這么寫(xiě)。

    void printf()

    {

    printf("hello world!");

    }

    3. 參數是數組的名字。我們知道數組的名字是個(gè)地址,那么如果實(shí)參是數組名的話(huà),我們可以將形參設置成指針,指向實(shí)參傳遞過(guò)來(lái)的數組的首地址。

    4. 參數是指針。如果實(shí)參是指針,那么形參肯定也得是指針。保持類(lèi)型一致即可,然后在函數內部再對指針進(jìn)行操作。

    5. 參數是結構體。如果實(shí)參是結構體,一般來(lái)說(shuō)我們使用結構體指針來(lái)做形參比較合適。

    還是在此分割一下吧,說(shuō)了這么多,可能很多人在問(wèn)問(wèn)什么函數定義這么麻煩,還要定義函數,直接都寫(xiě)在main函數中多方便?

    非也!

    C語(yǔ)言是一個(gè)過(guò)程化的語(yǔ)言,C語(yǔ)言中的主函數其實(shí)是用來(lái)主導程序的進(jìn)程和數據的流動(dòng)方向的。如果將主函數寫(xiě)的過(guò)于復雜,我們閱讀程序的結構就會(huì )非常的費力。

    四、C語(yǔ)言中函數回調

    什么是回調函數?

    簡(jiǎn)而言之,回調函數就是一個(gè)通過(guò)函數指針調用的函數。如果你把函數的指針(地址)作為參數傳遞給另一個(gè)函數,當這個(gè)指針被用為調用它所指向的函數時(shí),我們就說(shuō)這是回調函數。

    為什么要使用回調函數?

    因為可以把調用者與被調用者分開(kāi)。調用者不關(guān)心誰(shuí)是被調用者,所有它需知道的,只是存在一個(gè)具有某種特定原型、某些限制條件(如返回值為int)的被調用函數。

    如果想知道回調函數在實(shí)際中有什么作用,先假設有這樣一種情況,我們要編寫(xiě)一個(gè)庫,它提供了某些排序算法的實(shí)現,如冒泡排序、快速排序、shell排序、shake排序等等,但為使庫更加通用,不想在函數中嵌入排序邏輯,而讓使用者來(lái)實(shí)現相應的邏輯;或者,想讓庫可用于多種數據類(lèi)型(int、float、string),此時(shí),該怎么辦呢?可以使用函數指針,并進(jìn)行回調。

    回調可用于通知機制,例如,有時(shí)要在程序中設置一個(gè)計時(shí)器,每到一定時(shí)間,程序會(huì )得到相應的通知,但通知機制的實(shí)現者對我們的程序一無(wú)所知。而此時(shí),就需有一個(gè)特定原型的函數指針,用這個(gè)指針來(lái)進(jìn)行回調,來(lái)通知我們的程序事件已經(jīng)發(fā)生。

    下面是自己寫(xiě)的一個(gè)簡(jiǎn)單的回調函數,相比其他的那些復雜的代碼,這個(gè)更容易理解:

    #include

    #include

    void perfect(int n)

    {

    int i=1;

    int count=0;

    for(i=1;i

    {

    if(0==n%i)

    {

    count+=i;

    }

    }

    if(count==n)

    printf("%d是完數 ",n);

    else printf("%d不是完數 ",n);

    }

    void myCallback(void (*perfect)(int ),int n)

    {

    perfect(n);

    }

    int main()

    {

    int n;

    printf("請輸入一個(gè)正整數 ");

    scanf("%d",&n);

    myCallback(perfect,n);

    return 0;

    }

    五、C語(yǔ)言中的刷新和定位函數

    一.fflush

    1.fflush的原型如下:

    intfflush(FILE *stream);

    2.當需要立即把輸出緩沖區的數據進(jìn)行物理寫(xiě)入時(shí),應該使用這個(gè)函數。例如調用fflush函數保證調試信息實(shí)際打印出來(lái),而不是保存在緩沖區中直到以后才打印。

    二.定位函數

    1.在正常情況下,數據以線(xiàn)性的方式寫(xiě)入,這意味著(zhù)后面寫(xiě)入的數據在文件中的位置是在以前所有寫(xiě)入數據的后面。C同時(shí)支持隨機訪(fǎng)問(wèn)I/O,也就是以任意順序訪(fǎng)問(wèn)文件的不同位置。隨機訪(fǎng)問(wèn)是通過(guò)在讀取或寫(xiě)入前,先定位到文件中需要的位置來(lái)實(shí)現的。

    2.定位函數原型:

    1>long ftell(FILE*stream);

    2>intfseek(FILE *steam,long offset,intfrom);

    3.ftell函數返回流的當前位置。即:下一個(gè)讀取或寫(xiě)入將要開(kāi)始的位置距離文件起始位置的偏移量。該函數允許保存一個(gè)文件的當前位置。

    1>在二進(jìn)制流中,這個(gè)值就是當前位置距離文件起始位置之間的字節數。

    2>在文本流中,這個(gè)值表示一個(gè)位置,但它并不一定準確地表示當前位置和文件起始位置之間的字符數,因為有些系統將對行末字符進(jìn)行翻譯轉換。但是,ftell函數返回的值總是可以用于fseek函數中,作為一個(gè)距離文件起始位置的偏移量。

    4.fseek函數允許你一個(gè)流中定位。這個(gè)函數將改變下一個(gè)讀取或寫(xiě)入操作的位置。它的第 1個(gè)參數是需要改變的流。它的第2和第3個(gè)參數標識文件中需要定位的位置。

    1>試圖定位到一個(gè)文件的起始位置之前是一個(gè)錯誤。定位到文件尾并進(jìn)行寫(xiě)入將擴展這個(gè)文件。定位到文件尾之后并進(jìn)行讀取將導致返回一條“到達文件尾”的信息。

    2>在二進(jìn)制流中,從SEEK_END進(jìn)行定位可能不被支持,所以應該避免。

    3>在文本流中,如果from是SEEK_CUR或SEEK_END,offset必須是零。如果from是SEEK_SET,offset必須是一個(gè)從同一個(gè)流中以前調用ftell所返回的值。

    5.用fseek改變一個(gè)流的位置會(huì )帶來(lái)三個(gè)副作用。

    1>首先,行末指示字符被清除。

    2>其次,如果在fseek之前使用ungetc把一個(gè)字符返回到流中,那么這個(gè)被退回的字符會(huì )被丟棄,因為在定位操作以后,它不再是“下一個(gè)字符”。

    3>最后,定位允許你從寫(xiě)入模式切換到讀取模式,或者回到打開(kāi)的流以便更新。

    詞條內容僅供參考,如果您需要解決具體問(wèn)題
    (尤其在法律、醫學(xué)等領(lǐng)域),建議您咨詢(xún)相關(guān)領(lǐng)域專(zhuān)業(yè)人士。

    推薦詞條

    影音先锋AⅤ天堂资源站,13小箩利洗澡无码视频APP,午夜理论片日本中文在线,最近新免费韩国日本电影 国产精品免费大片,无码成人AA片一区二区,琪琪午夜福利免费院,中国午夜伦理片 国产AV一区二区三区天堂综合网,又肉又污的黄文,国产免费内射又粗又爽密桃视频,女人脱精光让人桶爽了 特级做A爰片毛片免费69,亚洲乱妇老熟女爽到高潮的片,女干部光着屁股让领导玩,伊人久在线观看视频 国产精品久久久久久亚洲影视,国产深夜男女无套内射,亚洲VA欧美VA天堂V国产综合,欧美阿v高清资源在钱 A级毛片无码久久精品免费,黑人射精在线播放美利坚,青青草国产97免费观看,妇女性内射冈站HDWWW000