函數(shù)之間的通信方式

函數(shù)之間的通信方式

程序無外乎由變量和函數(shù)組成,前者負責(zé)保存和組織數(shù)據(jù),后者負責(zé)業(yè)務(wù)邏輯,即操作這些數(shù)據(jù)以獲得期望的結(jié)果。函數(shù)彼此獨立,但又不孤立,而是需要同其他函數(shù)進行交流,以便協(xié)同工作。因此,理解函數(shù)之間的通信方式顯得尤為重要。

通信方式的種類

所謂函數(shù)的通信方式,就是一個函數(shù)將值傳遞給另一個函數(shù)的渠道。有三種:

  • 函數(shù)的返回值:調(diào)用函數(shù)可以直接獲得被調(diào)用函數(shù)的返回值。
  • 函數(shù)的參數(shù):以引用傳遞的方式將一個指針傳遞給被調(diào)用函數(shù),后者將需要返回給調(diào)用函數(shù)的值放入其中。
  • 全局變量:任意函數(shù)都可以訪問,多用在兩個函數(shù)之間需要進行通信,但又不直接調(diào)用對方的情況下。

本文重點講解前兩項。

getint函數(shù)

K&R中有一個很好的例子,說明了返回值和參數(shù)這兩個通信方式(以下簡稱通道)之間的的區(qū)別和聯(lián)系。(K&R Section5.2 P95)

需要設(shè)計一個名為getint()的函數(shù),作用是從標準輸入流中讀取一個數(shù)字字符串(整數(shù)),然后將其轉(zhuǎn)化為相應(yīng)整數(shù)數(shù)值。
從程序設(shè)計的角度來講,很明顯這個函數(shù)在工作期間會遇到若干種情況,而且需要向它的調(diào)用方說明這些情況,這些情況有:
1. 成功轉(zhuǎn)換字符串,得到一個需要被返回的數(shù)值。
2. 轉(zhuǎn)換失敗,因為讀取到的字符不是數(shù)字。
3. 轉(zhuǎn)換失敗,因為讀取到了EOF。

問題是,以上情況并不互相排斥,而是有可能同時出現(xiàn)。
例如,對于"12345qwer"這樣一個字符串,"12345"的部分可以被成功讀?。欢?qwer"部分會因為不是數(shù)字而轉(zhuǎn)換失敗。這是函數(shù)應(yīng)該返回"12345"表示的數(shù)值,并且告訴調(diào)用方猶豫后續(xù)字符不是數(shù)字,無法繼續(xù)。

又例如,對于"-1"這樣一個字符串來說,它后面如果緊跟著EOF,那么函數(shù)就需要在返回-1的同時,還需要告訴調(diào)用方它遇到了EOF而終止。EOF是-1,恰好同字符串所代表的數(shù)值相同,如果利用返回值進行傳遞,肯定會造成誤解。
很明顯,如果所有的可能情況都通過返回值進行傳遞,是不可能的。這是就要同時利用返回值和參數(shù)進行傳遞: 
返回值:負責(zé)說明轉(zhuǎn)換是否成功,以及錯誤的原因(錯誤原因互相排斥)。
參數(shù):在轉(zhuǎn)換成功的情況下,負責(zé)將轉(zhuǎn)換后的數(shù)值傳遞出去。

上面的分析可以概括為:

  • 轉(zhuǎn)換成功(返回一個正數(shù)):
    • 轉(zhuǎn)換結(jié)果(利用參數(shù)傳遞出去)
  • 由于讀取到EOF而失?。ǚ祷?1):
  • 由于讀取到非數(shù)字字符失?。ǚ祷?):

詳細代碼如下

#include <stdio.h>
#include <ctype.h>

/**
 *  從標準輸入流中讀取一個整數(shù)數(shù)字字符串,并將其轉(zhuǎn)換為對應(yīng)的整數(shù)數(shù)值
 *
 *  @param pn int型指針,用于將轉(zhuǎn)換所得的整數(shù)數(shù)值傳遞出去
 *
 *  @return 如果輸入的字符串含有整數(shù),返回一個正整數(shù)(取決于數(shù)字后面的第一個字符,如有);如果不含有合法數(shù)字,返回0;如果遇到EOF,返回-1
 */
int getint(int *pn);


int bgetchcar(void); // 等同于getc
void bungetchar(int n); // 等同于ungetc

int main(int argc, const char * argv[]) {
    
    int x = 0;
    int r = getint(&x);
    
    printf("r:%d----x:%d\n", r, x);
    
    
    return 0;
}

int getint(int *pn)
{
    int c, sign;
    
    while (isspace(c = bgetchcar())) { // 跳過空格
        ;
    }
    if (!isdigit(c) && c != EOF && c != '+' && c != '-') {
        bungetchar(c); // 不是數(shù)字,退回最近讀到的字符到輸入流中
        return 0;
    }
    
    sign = (c == '-') ? -1 : 1; // 嘗試記錄符號
    if (c == '+' || c == '-') { // 如果當(dāng)前讀到的是符號,則繼續(xù)讀取下一個字符
        c = bgetchcar();
    }
    for (*pn = 0; isdigit(c); c = bgetchcar()) { // 開始逐個讀取數(shù)字,直到讀取到一個不是數(shù)字的字符為止
        *pn = (*pn) * 10 + (c - '0'); // *10負責(zé)提升位數(shù),c - '0'得出每一位的數(shù)字
    }
    
    *pn *= sign; // 糾正數(shù)值的正負
    
    if (c != EOF) { // 如果最后讀取到的字符不是EOF
        bungetchar(c); // 則將這個字符退回到輸入流中
    }
    return c;
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容