21天C語言代碼訓(xùn)練營(第十七天)

在后面的五篇中,我們開始重點介紹一些C語言編程中的技巧和常見的錯誤。這些會對大家今后的面試和工作起到一些積極的作用。

1. 特殊比較

在程序設(shè)計中,很常見的一個問題是變量與零值的比較問題。很多資深程序員還經(jīng)常在這個問題上犯錯。

1.1 float類型與零值比較

也許大家不假思索就會寫出這樣的代碼:

float x;
...
if (x == 0.0) 
if (x != 0.0) 

如果你面試的時候?qū)懗鲞@樣的代碼,很遺憾你沒被錄取。一段簡單的代碼就能說明這種寫法有什么問題:

#include <stdio.h>

int main()
{
    float b = 0.01;
    float x = b - 0.01;

    if (x == 0.0)
    {
        printf("Yes");
    }
    else
    {
        printf("No");
    }

    return 0;
}

我們看一下這段代碼的執(zhí)行結(jié)果:

代碼執(zhí)行結(jié)果

看了執(zhí)行結(jié)果,也許你會很奇怪。為什么打印的結(jié)果不是Yes呢?其實,在內(nèi)存中保存0.01這樣一個數(shù)字時,計算機其實保存的數(shù)字是0.00999999978。因此,在執(zhí)行b - 0.01這句代碼時結(jié)果并不是0而是2.23517413e-10。具體原因我們就不在這里討論了。那正確的寫法究竟是什么呢?正確的寫法如下:

#include <stdio.h>

#define EPSINON 0.00001

int main()
{
    float b = 0.01;
    float x = b - 0.01;

    if ((x >= -EPSINON) && (x <= EPSINON))
    {
        printf("Yes");
    }
    else
    {
        printf("No");
    }

    printf("\n");
    return 0;
}

這樣寫通過一個精確范圍來界定x變量是否為0。

1.2 空字符串判斷

前些天組里還有位資深程序員寫出了類似下面的代碼,大家覺得有什么問題。

int main()
{
    char* pch = (char*)malloc(5 * sizeof(char));
    pch[0] = 0;

    if (pch == "")
    {
        printf("Yes");
    }
    else
    {
        printf("No");
    }

    return 0;
}

寫這段代碼的人認為通過pch[0] = 0這句話把pch變成了一個空字符串,之后在pch == ""這句判斷語句執(zhí)行時結(jié)果應(yīng)該為真。因此,應(yīng)該打印"Yes",結(jié)果打印的卻是"No"。

原因其實很簡單,pch == ""這句話其實比較的是pch指針和“”這個空字串地址。兩個不同的地址比較結(jié)果跟保存內(nèi)容其實沒有任何關(guān)系。正確的寫法應(yīng)該是這樣:

int main()
{
    char* pch = (char*)malloc(5 * sizeof(char));
    pch[0] = 0;

    if (strcmp(pch, "") == 0)
    {
        printf("Yes");
    }
    else
    {
        printf("No");
    }

    return 0;
}

C語言庫函數(shù)中為大家提供了strcmp這么一個無比好用的函數(shù),那么一定要學(xué)會正確使用它。

2. 變量的內(nèi)存空間

在C語言程序設(shè)計中,經(jīng)常需要關(guān)注變量在內(nèi)存中的狀態(tài)。其中,非常重要的是占用內(nèi)存的大小。常用sizeof()這個函數(shù)來得到占用內(nèi)存的大小。先看一段代碼:

#include <stdio.h>

int main()
{
    char str[] = "Hello";
    char *p = str;
    int n = 10;

    int a = sizeof(str);
    int b = sizeof(p);
    int c = sizeof(n);

    printf("%d\n", a);
    printf("%d\n", b);
    printf("%d\n", c);

    return 0;
}

你能正確說出這段代碼的執(zhí)行結(jié)果嗎?如下圖:

執(zhí)行結(jié)果

讓很多人比較疑惑的是變量b的值為什么是4。如果你仔細看了之前的文章,那么肯定知道它表示的是指針變量在內(nèi)存中的大小。

3. strcpy函數(shù)實現(xiàn)

接下來,我們通過這個函數(shù)的實現(xiàn)來介紹幾個筆試中常見的問題。

char* strcpy(char* strDest, const char* strSrc);

3.1. 不調(diào)用C語言庫函數(shù),編寫strcpy函數(shù)

在我的印象中,遇到過很多次這樣的題目。難度稍高一些的嵌入式開發(fā)題目要求用效率最高的方式實現(xiàn)。正確代碼如下:

char* strcpy(char* strDest, const char* strSrc)
{
    assert((strDest != NULL) && (strSrc != NULL));
    char* address = strDest;
    while ((*strDest++ = *strSrc++) != '\0')
        NULL;
    return address;
}

這種寫法應(yīng)該已經(jīng)非常接近庫函數(shù)的實現(xiàn)方法了,它的效率非常高。

3.2. strcpy能夠把strSrc的內(nèi)容復(fù)制給strDest,為什么需要char*類型的返回值?

這個問題其實沒有唯一答案,你可以談自己對程序設(shè)計的理解,并給出一個你覺得合適的答案。這里給出一個大多數(shù)面試官比較喜歡的答案:

這樣設(shè)計能夠?qū)崿F(xiàn)鏈?zhǔn)奖磉_式,如:
int len = strlen(strcpy(strDest, "ABCDE"));

3.3. const char* strSrc中const的意義?

其實const這個關(guān)鍵字嚴格意義上說是C++中的,但越來越多的C語言代碼開始使用這個關(guān)鍵字。它的意義是保證strSrc這個字符串的內(nèi)容不會被strcpy修改。

今天就先到這里,有什么問題歡迎郵件溝通。

我是天花板,讓我們一起在軟件開發(fā)中自我迭代。
如有任何問題,歡迎與我聯(lián)系。


上一篇:21天C語言代碼訓(xùn)練營(第十六天)
下一篇:21天C語言代碼訓(xùn)練營(第十八天)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 史上最全的iOS面試題及答案 迷途的羔羊--專為路癡量身打造的品牌。史上最精準(zhǔn)的定位。想迷路都難!閃電更新中......
    南虞閱讀 1,526評論 0 8
  • iOS面試小貼士 ———————————————回答好下面的足夠了------------------------...
    不言不愛閱讀 2,002評論 0 7
  • ———————————————回答好下面的足夠了---------------------------------...
    恒愛DE問候閱讀 1,753評論 0 4
  • __block和__weak修飾符的區(qū)別其實是挺明顯的:1.__block不管是ARC還是MRC模式下都可以使用,...
    LZM輪回閱讀 3,358評論 0 6
  • 凌晨一點 外面雨聲滴滴滴滴地響 大概是雨水與雨水在碰撞 夜很黑 手機屏調(diào)到最暗 仍然閃著稍刺眼的光 還有本該刺耳的...
    甘野閱讀 381評論 0 3