最近C語言已經學完,佈置的大做業:學生管理系統5個版本也完成了。可是又買了一本《C和指針》,主要是感受本身的指針仍是沒有徹底熟悉。因此仍是要好好研究一下。閒話很少說,直接第一章。一看是快速入門,覺得很簡單,但那個程序就把我卡了半天才看懂,按照做者說的的確運用了C語言中的大部分技巧。數組
程序1.1:首先讀取一串列標號,這些列標號成對出現,即是輸入行的列範圍。這串列標號以一個負值結尾,做爲結束標誌。剩餘的輸入行被程序讀入並打印,而後輸入行中被選中範圍的字符串被提取出來打印。函數
書中代碼以下:學習
#include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_CLOS 20 /*所能處理的最大列號*/ #define MAX_INPUT 1000 /*每一個數入行的最大長度*/ int read_column_numbers(int columns[],int max); void rearrange(char *output,char const*input,int n_columns,int const columns[MAX_CLOS]); int main(void) { int n_columns; /*進行處理的列標號*/ int columns[MAX_CLOS]; /*須要處理的列數*/ char input[MAX_INPUT]; /*須要容納的輸入的數組*/ char output[MAX_INPUT]; /*容納輸出行的數組*/ n_columns=read_column_numbers(columns,MAX_CLOS); while(gets(input)!=NULL) /*若是讀入不存在輸入行則程序結束*/ { printf("Original input :%s\n",input); rearrange(output,input,n_columns,columns); printf("Rearranged line :%s\n",output); } return EXIT_SUCCESS; } /*讀取須要處理的列標號,若是超出規定範圍不予理會*/ int read_column_numbers(int columns[],int max) { int num=0; int ch; while(num<max&&scanf("%d",&columns[num])==1&&columns[num]>0) { /*這個循環條件保證了讀取的行號不會超過最大值,並且利用&&的短路特性, 也不會即便超過最大行號也不會被scanf讀入,同時scanf保證了讀入整型數據, 同時後面的條件輸入的爲正數*/ num+=1; } /*判斷是否讀入的數據是成對的*/ if(num%2) { puts("Last column number is not paired."); exit(EXIT_FAILURE); } while((ch=getchar())!=EOF&&ch!='\n'); /*用來處理包含最後那個負值的全部字符*/ return num; } /*處理輸入行*/ void rearrange(char *output,char const*input,int n_columns,int const columns[MAX_CLOS]) { int col; /*columns數組的下標*/ int output_col; /*輸出行的列計數器*/ int len; /*輸入行的長度*/ int nchars; /*成對處理的列之間的長度*/ len=strlen(input); output_col=0; for(col=0;col<n_columns;col+=2) { if(columns[col]>=len||output_col==MAX_INPUT-1) /*若是輸入行的標號小於須要處理的列標號或者 輸出數組已滿結束任務*/ break; nchars=columns[col+1]-columns[col]+1; if(output_col+nchars>MAX_INPUT-1); nchars=MAX_INPUT-output_col-1; /*若是輸出行數據空間不夠則只處理到能容納到的數據*/ strncpy(output+output_col,input+columns[col],nchars); output_col+=nchars; } output[output_col]='\0'; }
一點點思考:不得不說,Kenneth這種大師思惟的確很完善,要是我寫的確不少地方都想不到(我怎麼敢和大師比2333!),好比while(ch=getchar())那個語句,一開始我百思不得其解,後來才明白爲的是清除負值以後的字符(包括負值自己)由於這些字符雖然沒有被讀走,同時也仍然在stdin中存在。因此在主函數調用gets這個函數進行讀取的時候這些未被讀走的字符就會被解釋爲第一行數據進而使咱們得不到本身想要的結果。 而他對於可能形成數組越界訪問的狀況也進行了處理。想一想本身在寫的時候歷來沒有在意過這些,都是越界了纔會debug找出來。另一個細節就是他傳入rearrange這個函數的input數組,加了前綴const,防止函數內可能形成的改動。這點也是我須要學習的。spa
不過我也對於他的主函數設置的while條件有一些異議,gets函數在讀到文件尾(EOF)纔會獲得NULL,這種的確適合咱們打開一個文件進行讀取的操做,由於這個文件的末尾必定會有EOF。可是若是咱們在鍵盤輸入的時候,咱們只有CtrlZ才能夠獲得EOF,這點總讓我感受很不爽,其實主要是我懶不想摁CtrlZ,另外是我在書上並非很理解它的輸入樣例(你們能夠去看一下),裏面沒有CtrlZ,因此,我並非很懂做者的意思。但貌似沒有其餘更好的方法了。就暫且認爲是須要輸入CtrlZ。在這個問題上糾結這麼久,我也是醉了。debug
這個程序的確很經典,包含的東西多但不難,其實你們能夠按照示例試一下輸出,而後就會獲得很好玩的結果了。感受本身學了一學期C,仍是什麼都不會,本身打的時候打不下去,而後看了書的程序也是看了半天。。。多是由於最近在看Java致使的吧。不能一天放鬆啊。。。指針