1. 程式人生 > >C的陷阱與缺陷 P87-P137 PartIII-學習小結

C的陷阱與缺陷 P87-P137 PartIII-學習小結

緩衝輸出與記憶體分配:

程式輸出有兩種方式,一種是即時處理方式(往往造成較高的系統負擔),另一種是先暫時存起來然後再大塊寫入,因此c語言實現通常都允許程式設計師進行實際的寫操作之前控制產生的輸出資料量。

這種能力一般使用setbuf庫函式實現,如果buf是一個大小適當的字元數粗,那麼setbuf(stdout,buf);語句將會通知I/O庫,所有寫入到stdout的輸出都應該使用buf作為輸出緩衝區,直到buf緩衝區的內容被填滿or程式設計師直接呼叫fflush,buf的內容才會寫入到stdout之中,舉一個例子來看看:

int main()
{
    int c;
    static char buf[BUFSIZ]; //BUFSIZ由stdio.h給出
    setbuf(stdout,buf);
    
    while((c=getchar())!=EOF)
        putchar(c);
}

書上這個例子太垃圾了,於是去網上搜了一下,換一個

#include <stdio.h>
char outbuf[BUFSIZ];
int main(void)
{
    setbuf(stdout, outbuf); // 把緩衝區與流相連
    puts("This is a test of buffered output.\n");
    puts(outbuf);
    fflush(stdout); // 重新整理
    puts(outbuf); // 輸出
    return 0;
}

輸出結果: This is a test of buffered output..         //不在oubuf,但在I/O流,因為緩衝和流已經相連,轉入outbuf中 This is a test of buffered output..        //輸出此時的outbuf,之後outbuf應該儲存了兩個一樣的字串了 This is a test of buffered output..       This is a test of buffered output..         //輸出此時的outbuf 程式先把outbuf與輸出流相連,然後輸出一個字串,這時因為緩衝區已經與流相連,所以outbuf中也儲存著這個字串,緊接著puts函式又輸出一遍,所以現在outbuf中儲存著兩個一樣的字串。重新整理輸出流之後,再次puts,則又輸出兩個字串。

前處理器:

1.不能忽視巨集的空格:

#define f (x) ((x)-1)

這句話中,f (x)就是有毒的。

2.巨集不是函式:

在最開始學c的時候,網上總有些人寫出這樣其實不太好的話

#define abs(x) (((x)>=0)?(x):-(x))
//巨集定義中出現的這些括號只是預防引起與優先順序有關的問題
//所以在你忘記優先順序的時候,括號也是比較好用的

//———————————————————————————————————————不可視的境界線

//如果你去掉括號的話,也就是#define abs(x) x>0?x:-x
//你試一下表達式abs(a-b)還能work well嗎

//同時,這個“-”號也很講究

//巨集,只是用於預處理的替換

函式就是函式,巨集就是巨集,巨集不要搞得太複雜,naive,這一節不看了,反正我也不會寫這種程式碼。

3.可移植性缺陷:

程式碼的可移植性是工程中很重要的因素,在我們小組十天內寫出滿分大作業的時候就意識到了這一點,因為帆帆用的devc++,czb用的xcode(哎,你說有錢該多好),我用的vs2017,有的地方就是我這能跑他那裡GG,還有每個IDE都可能有自己安裝的一些庫檔案,比如我的vs就集成了EGE(#include <graphics.h>);對於一般的萌新同學,在用學校的編譯器和自己電腦上的ide體驗也相當不好。同時,c語言的標準也在變更著。所以有些時候我們寫的程式碼,最好就別和機器、 編譯器關係太密切。現在還想不起很多的採坑點,等我再學深一些再回來補。

4.realloc:

#define newsize 100*sizeof(int)
free(p);
p=realloc(p,newsize);

練習:編寫一個函式對於一個已經排好序的整數表實現二分查詢,函式的輸入是一個指向表頭的指標,表中元素個數以及帶查詢的數值。函式的輸出是一個指向滿足查詢要求的元素指標,當未找到的時候就輸出一個NULL指標。

二分查詢原理很簡單,但是在實踐中人們經常不能寫好,比如我。書上寫了兩個版本,我們這裡意思意思一下。

int *bsearch(int *t,int n,int x)
{
 int lo=0,hi=n;
 while(lo<hi)
{
     int mid=(hi+lo)/2; //可以用int mid=(hi+lo)>>1代替,提高機器速度
     if(x<t[mid])
        hi=mid;
     if(x>t[mid])
        lo=mid+1
     else 
            return t+mid;
}
     return NULL;
}

位運算我還是沒系統理解,改天仔細看看。不過在很多機器上,下標運算都比指標運算慢,我們看看老爺子是怎麼寫的(哎)。

int *bsearch(int *t,int n,int x)
{
    int *lo=t,*hi=t+n;
    while(lo<hi)
    {
       int *mid=lo+((hi-lo)>>1);
        if(x<*mid) hi=mid;
        else if(x>*mid) lo=mid+1;
        else 
            return mid;

    }

return NULL;

}

先到這吧= =,學點別的