【心得】strcat函數的實現與應用

實現

金山面試的問題之一,比較簡單。
須要注意兩點:1.字符串空間檢測判斷2.字符串末尾記得加'0'html

第一種寫法:

也是個人答案:c++

char *strcat(char *str1, char *str2)
{
    if((str1==NULL)||(str2==NULL)) throw "Invalide arguments!";

    int len1=strlen(str1),len2=strlen(str2);
    for(int i=strlen(str1);i<len1+len2;i++){
        str1[i]=str2[i-len1];
    }
    str1 [len1+len2]= '\0';
    return str1;
}

當時少寫了 str1 [len1+len2]= '0';面試

第二種寫法:

char *strcat(char *str1, char *str2)
{
    if((str1==NULL)||(str2==NULL)) throw "Invalide arguments!";
    char *pt = str1;
    while(*str1!='\0') str1++;
    while(*str2!='\0') *str1++ = *str2++;
    *str1++ = '\0';
    return pt;
}

切不可寫成return str1;
由於此時函數體內的str1指針已經被移動到字符串結尾,指向'0'。
因此只能返回一開始pt保存的原始str1。返回值錯誤!數組

因爲函數strcat的參數str1是形參,因此主函數的數組a的指針不會變化。
可是最好的寫法仍是不要直接對str1作修改:ide

char *strcat(char *str1, char *str2)
{
    if((str1==NULL)||(str2==NULL)) throw "Invalide arguments!";
    char *pt = str1;
    while(*pt!='\0') pt++;
    while(*str2!='\0') *pt++ = *str2++;
    *pt = '\0';
    return str1;
}

應用

參考:http://www.blog.chinaunix.net...
聲明:使用gcc和vc++(VS2010)編譯函數

函數定義:char *strcat (char *dest,const char *src)
函數說明:strcat()會將參數src字符串拷貝到參數dest所指的字符串尾,第一個參數dest要有足夠的空間來容納要拷貝的字符串;
返回值: 返回dest字符串參數的起始地址;ui

接下來分三種狀況來看strcat()函數:.net

方案一:兩個參數都是數組

#include <string.h>
#include <stdio.h>

int main(void)
{
    char dest[30] = "Hello";
    char src[] = "World";

    strcat(dest, src);
    printf("dest:[%s]\n", dest);

    return 0;
}

GCC/VC++:dest:[HelloWorld]unix

方案二:兩個參數都是指針

  1. dest爲空指針

    #include <stdio.h>
    #include <string.h>
    
    int main(void)
    {
        char *dest = NULL;
        char *src = "World";
    
        strcat(dest, src);
        printf("dest:[%s]", dest);
    
        return 0;
    }

    GCC:Segmentation fault (core dumped)居然是段錯誤,爲何呢?

    dest沒有足夠的空間來存儲src中的內容;

    VC++:

    cmd:空
    彈出:.exe已中止工做。

    修改以後的:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int main(void)
    {
        char *dest = NULL;
        dest = (char *)malloc(1024);
        *dest='\0';//顯式將首地址指向結束符。很是必要。不然1024個字節的字符串會充滿隨機的字符。
        char *src = "World";
    
        strcat(dest, src);
        printf("dest:[%s]", dest);
    
        return 0;
    }

    GCC/VC++:dest:[World]
    若是沒有*dest='\0';,GCC經過,VC++不經過。
    猜想:gcc在malloc後,新分配的空間自動補全了'0'。

  2. dest非空

    但此時的dest是空字符串,若是想要在非空字符串(好比"aaa")後strcat怎麼辦?
    直接把char *dest = NULL;改爲char *dest = "aaa";嗎?

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int main(void)
    {
        char *dest = "aaa";
        dest = (char *)malloc(1024);
        *(dest+3)='\0';
        char *src = "World";
    
        strcat(dest, src);
        printf("dest:[%s]", dest);
    
        return 0;
    }

    VC++:

    cmd: dest:[屯蚖orld]

    gcc:

    dest[World]

    VC++中, "aaa"被新分配的內存地址的值覆蓋。因爲新分配的內存地址的值並未初始化(除了dest+3位置上賦值爲'0'), 因此出現亂碼。"World"的第一個字母W(1字節)被a的第三個字符組合成了漢字「蚖」(2字節)。

    那麼,先分配內存,而後賦值:char *dest = (char *)malloc(1024);dest = "aaa";?
    同樣不能夠!
    VC++:

    cmd:空
    彈出:.exe已中止工做!

    gcc:Segmentation fault (core dumped)
    緣由相同:"aaa"將分配的空間覆蓋,也就是說a指向新的字符串"aaa",它的大小爲4,沒法放下a和b。

    正確的作法是對a先申請內存,而後用strxxx函數對a開始幾位進行修改。好比用strcpy:

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    int main ()
    {
        char *dest=(char *)malloc(1024);
        char *src="World";
        strcpy (dest,"aaa");
        strcat (dest,src);
        printf("dest:[%s]", dest);//puts (dest);
        return 0;
    }

    vc++:

    cmd:dest:[aaaWorld]

    gcc:

    dest:[aaaWorld]

    OK!

方案三:第一個是數組,第二個是指針

#include <stdio.h>
#include <string.h>

int main(void)
{
    char dest[6] = "Hello";
    char *src = "World";

    strcat(dest, src);
    printf("dest:[%s]\n", dest);

    return 0;
}

gcc:

dest:[HelloWorld]
*** stack smashing detected ***: ./1 terminated
Aborted (core dumped)

爲何會這樣呢?不是說要空間足夠的時候才能夠拷貝成功的麼?
很明顯,這屬於數組越界的問題,在C語言中,c不檢查也不提示,因此這裏的拷貝用到了dest[6]後面緊挨着的幾個存儲單元;

VC++:

cmd:dest:[HelloWorld]
彈出:stack around the variable 「XX」 was corrupted!

方案四:第一個指針,第二個數組

#include <stdio.h>
#include <string.h>

int main(void)
{
    char *dest;
    char src[] = "World";

    strcat(dest, src);
    printf("dest:[%s]\n", dest);

    return 0;
}

看到這裏,都會知道確定是dest的空間不足,沒法拷貝src中的內容;
因此輸出結果是:
gcc:

dest:[�Ax�World]
//原文說他的結果是Segmentation fault (core dumped)

vc++:

cmd:空。
彈出:dest未初始化就被使用。

更改以後:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void)
{
    char *dest;
    dest = (char *)malloc(1024);
    *dest='\0';
    char src[] = "World";
    
    strcat(dest, src);
    printf("dest:[%s]\n", dest);

    return 0;
}

OK輸出結果是
GCC/vc++:dest:[World]
若是沒有*dest='\0';,GCC經過,VC++不經過。

相關文章
相關標籤/搜索