C和指針——簡介篇

程序示例
/*
** 這個(gè)程序從標(biāo)準(zhǔn)輸入中讀取輸入行并在標(biāo)準(zhǔn)輸出中打印這些輸入行
** 每個(gè)輸入行的后面一行是該行內(nèi)容的一部分
**
** 輸入的第一行是一串列表號(hào),串的是最后以一個(gè)負(fù)數(shù)結(jié)尾
** 這些列標(biāo)號(hào)成對(duì)出現(xiàn),說明需要打印的輸入行的列的范圍
** 例如,0 3 10 12 -1 表示第0列到第3列,第10列到第12列的內(nèi)容將被打印 
*/ 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_COLS 20     /* 所能處理的最大列號(hào) */ 
#define MAX_INPUT 1000  /* 每個(gè)輸入行的最大長度 */ 

int read_column_numbers(int columns[], int max);
void rearrange(char *output, char const *input,
    int n_columns, int const columns[]);
    
int main(void){
    int n_columns;          /* 進(jìn)行處理的列標(biāo)號(hào) */ 
    int columns[MAX_COLS];  /* 需要處理的列數(shù) */ 
    char input[MAX_INPUT];  /* 容納輸入行的數(shù)組 */ 
    char output[MAX_INPUT]; /* 容納輸出行的數(shù)組 */ 
    
    /*
    ** 讀取該串列標(biāo)號(hào) 
    */ 
    n_columns = read_column_numbers(columns, MAX_COLS);
    
    /*
    **  讀取 處理 和 打印剩余的輸入行 
    */ 
    while(gets(input) != NULL){
        printf("Original input: %s\n",input);
        rearrange(output, input, n_columns, columns);
        printf("Rearranged line: %s\n", output);
    }
} 

//讀取序列號(hào),如果超出范圍則不給予理會(huì) 
int read_column_numbers(int columns[],int max){
    int num = 0;
    int ch;
    //取得序列號(hào),如果讀取的序列號(hào)小于0則停止讀取 
    while (num < max && scanf("%d",&columns[num]) == 1 && columns[num] >= 0)
        num ++;
    
    //確認(rèn)已經(jīng)讀取的序列號(hào)為偶數(shù)個(gè),因?yàn)樗鼈兪浅蓪?duì)出現(xiàn)的 
    if (num%2 != 0){
        puts("Last column number is not paired.");
        exit(EXIT_FAILURE);
    }
    
    //丟棄該行中包含最后一個(gè)數(shù)字的那部分內(nèi)容
    //比如當(dāng)出現(xiàn)-1后,如果后面還有內(nèi)容的話,后面的內(nèi)容應(yīng)該處理,否則會(huì)變?yōu)檩斎胱址畠?nèi)容 
    while ((ch = getchar())!= EOF && ch != '\n' );
    
    return num;
}

//處理輸入行,將指定列的字符連在一起,輸出行以NUL結(jié)尾 
void rearrange(char *output, char const *input, int n_columns, int const columns[]){
    int col;        /* columns數(shù)組的下標(biāo) */ 
    int output_col; /* 輸出列計(jì)數(shù)器 */
    int len;        /* 輸入行的長度 */
    
    len = strlen(input);
    output_col = 0;
    
    //處理每對(duì)列標(biāo)號(hào) 
    for (col = 0; col < n_columns; col += 2){
        int nchars = columns[col+1] - columns[col] + 1;
        //如果輸入行結(jié)束或輸出行數(shù)組已滿,就結(jié)束任務(wù) 
        if (columns[col] >= len || output_col == MAX_INPUT-1)
            break;
            
        //如果輸出行數(shù)據(jù)空間不夠,只復(fù)制可以容納的數(shù)據(jù) 
        if (output_col + nchars > MAX_INPUT-1)
            nchars = MAX_INPUT - output_col -1;
        //復(fù)制相關(guān)數(shù)據(jù) 
        strncpy(output+output_col,input+columns[col],nchars);
        output_col += nchars; 
    } 
    output[output_col] = '\0';
    
}
預(yù)處理指令
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_COLS 20     /* 所能處理的最大列號(hào) */ 
#define MAX_INPUT 1000  /* 每個(gè)輸入行的最大長度 */ 

以上5行都為預(yù)處理指令。因?yàn)樗鼈兪怯?strong>預(yù)處理器解釋的。預(yù)處理器讀入源代碼,根據(jù)預(yù)處理指令對(duì)其進(jìn)行修改,然后將把修改后的源代碼遞交給編譯器。

函數(shù)原型
int read_column_numbers(int columns[], int max);
void rearrange(char *output, char const *input,
    int n_columns, int const columns[]);

這些聲明被稱為函數(shù)原型。它們告訴編譯器這些以后將在源文件中定義的函數(shù)的特征。這樣,當(dāng)這些函數(shù)被調(diào)用時(shí),編譯器就能對(duì)它們進(jìn)行準(zhǔn)確性檢查。

參數(shù)傳遞

在C語言中,數(shù)組參數(shù)是以引用形式進(jìn)行傳遞的,也就是傳遞調(diào)用,而標(biāo)量和常量則是按傳遞的。

  • 注意
    在函數(shù)中對(duì)標(biāo)量參數(shù)的任何修改都會(huì)在函數(shù)返回時(shí)丟失,因此,被調(diào)用函數(shù)無法修改調(diào)用函數(shù)以傳值形式傳遞給它的參數(shù)。然而,當(dāng)被調(diào)用函數(shù)修改數(shù)組參數(shù)的其中一個(gè)參數(shù)時(shí),調(diào)用函數(shù)所傳遞的數(shù)組會(huì)被實(shí)際地修改。
get函數(shù)
while(gets(input) != NULL){
    printf("Original input: %s\n",input);
    rearrange(output, input, n_columns, columns);
    printf("Rearranged line: %s\n", output);
}

get函數(shù)從標(biāo)準(zhǔn)輸入讀取一行文本并把它存儲(chǔ)于作為參數(shù)傳遞給它的數(shù)組中。一行輸入由一串字符組成,以一個(gè)換行符結(jié)尾。gets函數(shù)丟棄換行符,并在該行的末尾存儲(chǔ)一個(gè)NUL字節(jié)。

字符串常量

字符串常量就是源程序中被雙引號(hào)括起來的一串字符。例如,“Hello”,在內(nèi)存中占據(jù)6個(gè)字節(jié)的空間,按順序分別是H、e、l、l、o和NUL。

printf函數(shù)
printf("Original input: %s\n",input);

常用printf格式代碼

scanf函數(shù)
while (num < max && scanf("%d",&columns[num]) == 1 && columns[num] >= 0)

scanf函數(shù)從標(biāo)準(zhǔn)輸入讀取字符并根據(jù)格式字符串對(duì)它們進(jìn)行轉(zhuǎn)換。scanf函數(shù)的返回值是函數(shù)轉(zhuǎn)換成功并存儲(chǔ)于參數(shù)中的值的個(gè)數(shù)。

  • 注意
    所有的標(biāo)量參數(shù)的前面必須加上一個(gè)“&”符號(hào),而對(duì)于數(shù)組參數(shù),可加可不加。但如果是數(shù)組中的一個(gè)參數(shù),則必須加。

常用scanf函數(shù)格式碼

puts("Last column number is not paired.");

put函數(shù)是gets函數(shù)的輸出版本,它把指定的字符串寫到標(biāo)準(zhǔn)輸出并在末尾添上一個(gè)換行符。

int ch;
while ((ch = getchar())!= EOF && ch != '\n' );

getchar函數(shù)從標(biāo)準(zhǔn)輸入流讀取一個(gè)字符并返回它的值。如果輸入中不再存在任何字符,函數(shù)就會(huì)返回常量EOF(在stdio.h中定義),用于提示文件的結(jié)尾。

  • 為什么這里ch被聲明為整型?

EOF是一個(gè)整型值,它的位數(shù)比字符類型要多,把ch聲明為整型可以防止從輸入讀取的字符意外被解釋為EOF。但同時(shí),這也意味著接收字符的ch必須足夠大,足以容納EOF,這就是ch使用整型值的原因。實(shí)際上,字符只是小整型數(shù),所以用一個(gè)整型變量容納字符值不會(huì)引起任何變化。

const類型
void rearrange(char *output, char const *input, int n_columns, int const columns[]){
    int col;        /* columns數(shù)組的下標(biāo) */ 
    int output_col; /* 輸出列計(jì)數(shù)器 */
    int len;        /* 輸入行的長度 */

當(dāng)數(shù)組名作為實(shí)參時(shí),傳給函數(shù)的實(shí)際上是一個(gè)指向數(shù)組起始位置的指針,也就是數(shù)組在內(nèi)存中的地址。將columns聲明為const有兩方面的作用:首先,它聲明該函數(shù)的作者的意圖是這個(gè)參數(shù)不能被修改。其次,它導(dǎo)致編譯器去驗(yàn)證是否違背該意圖。

strncpy函數(shù)
strncpy(output+output_col,input+columns[col],nchars);

strncpy函數(shù)的前兩個(gè)參數(shù)分別是目標(biāo)字符串和源字符串的地址,最后一個(gè)參數(shù)指定需要復(fù)制的字符數(shù)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

  • 版權(quán)聲明:本文為 gfson 原創(chuàng)文章,轉(zhuǎn)載請(qǐng)注明出處。注:作者水平有限,文中如有不恰當(dāng)之處,請(qǐng)予以指正,萬分感謝...
    gfson閱讀 3,495評(píng)論 0 6
  • C/C++輸入輸出流總結(jié) 前兩天寫C++實(shí)習(xí)作業(yè),突然發(fā)現(xiàn)I/O是那么的陌生,打了好長時(shí)間的文件都沒有打開,今天終...
    LuckTime閱讀 1,808評(píng)論 0 6
  • 指針是C語言中廣泛使用的一種數(shù)據(jù)類型。 運(yùn)用指針編程是C語言最主要的風(fēng)格之一。利用指針變量可以表示各種數(shù)據(jù)結(jié)構(gòu); ...
    朱森閱讀 3,615評(píng)論 3 44
  • 前言 把《C++ Primer》[https://book.douban.com/subject/25708312...
    尤汐Yogy閱讀 9,683評(píng)論 1 51
  • 家譜乃我國古代宗法社會(huì)中記載宗族人物世系及事跡的家族檔案和歷史百科全書,具有“尊祖敬宗”,“敦族睦親”之倫...
    禪師祖閱讀 5,173評(píng)論 0 0

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