2017-10-06 42 views
-1

比方說,我有:如何防止C中複製函數期間「str 0ing」溢出?

char a[] = "str\0ing" 

,我想這個字符串複製到另一個字符數組,

char b[]. 

然而,我的功能似乎被擊中終止序列(或至少向前斜槓)並停止,這樣複製到b []中的唯一東西就是「str」。到底發生了什麼,我該如何解決這個問題?

我正在運行一個格式爲b [i] == a [i]的簡單For循環。謝謝。

編輯:我很抱歉,因爲很不清楚,這是我的第一篇文章。 這是我當前的代碼:

int copyStringN(char * in, char * out, int n) { 
    int i; 
    if (!in || !out) return -1; 
    for (i = 0; i < n; i++) { 
    *out++ = *in++; 
    } 
    *out= '\0'; 
    return 0; 
} 

int main() { 
#define N 8 
    char a[] = "th\0ing"; 
    char b[N]; 
    int err; 
    err = copyStringN(a, b, N); 
    assert (!err); 
    printf("%s\n", b); 
    return 0; 
} 

的限制是,它必須能夠打印「\ 0」,如果它存在,所以在字符串中我不能簡單地添加一個反斜槓。我必須以某種方式編碼我的函數來將此字符序列解釋爲顯式字符而不是終止符。

+5

請顯示一些代碼。 – babon

+0

然後告訴你的函數不要把'\ 0'當作終結符。 –

+1

你必須知道數組的長度。字符數組不是字符串(通常,就像您的示例所示)。 –

回答

0

爲了得到輸出看起來像 「海峽\ 0ing」,逃避一個額外的\ NULL字符:

int main(void) 
{ 
    char a[] = "str\\0ing"; 
    int len = strlen(a); 
    char b[len+1]; 
    for(int i=0;i<len+1;i++) 
    { 
     b[i] = a[i]; 
    } 
    printf("%s\n", b); 

    return 0; 
} 

輸出:
enter image description here

+1

好吧,那假設OP希望數組包含兩個字符的序列''\\'',''0'而不是空字符。他可能確實需要這樣做,但他是否確實不清楚。 –

+0

@JohnBollinger--這裏也不完全清楚,做出最好的猜測,並試圖解決這個問題。至少,我希望OP讓我知道我是否錯過了這個意圖。謝謝。 – ryyker

+0

我上面已經編輯過。我對缺乏信息表示歉意,並感謝你。 – admbmb

0

這是你如何做到這一點一個簡單的for循環:

#include <assert.h> 
#include <stdio.h> 

int main() { 
    char a[] = "str\0ing"; 
    int length = sizeof a/sizeof(char); 
    char b[length]; 
    for (int i = 0; i < length; i++) { 
     b[i] = a[i]; 
    } 
    assert(b[0] == 's'); 
    assert(b[1] == 't'); 
    assert(b[2] == 'r'); 
    assert(b[3] == '\0'); 
    assert(b[4] == 'i'); 
    assert(b[5] == 'n'); 
    assert(b[6] == 'g'); 
    printf("It works\n"); 
} 

還有其他方法,co但是你說你正在使用for循環,所以這可能與你已經嘗試過的最接近。

這裏的想法是,a不是一個字符串。它是一個字符數組。 C中的字符串是以零字節結尾的字節序列。如果你想在你的字符串中有一個零字節,它不是一個字符串。它是一個字符數組。所以上面的代碼將數組a中的字符複製到數組b

請注意分配b足夠空間的重要性。

編輯現在已添加到您的問題

好了,我們可以看到,你知道如何複製。但是你的問題是,你期望printf顯示一個零字節的字符串。它不會。如果你只是給它指向字符串開頭的指針,那麼不是。

如果要打印一個零字節的「字符串」,唯一的方法是將字符數據及其長度包裝到一個對象中,並用特殊的打印功能打印。

或者,如果可以的話,就移動到C++,它沒有麻煩可言:

#include <iostream> 
int main() { 
    std::string s("str\0ing", 7); 
    std::cout << s << '\n'; 
} 

它運行這麼好:

$ g++ t.cpp && ./a.out 
string 

田田!

+0

我上面編輯得更清晰。謝謝 – admbmb

+0

更新了答案。如果你不能移動到C++,那麼把字符數據與它的長度綁定到一個結構中的想法應該是一種方法。儘管給C++一個嘗試,如果可以的話。 –

2

如果你想要的\0被視爲NUL字符(\0)本身,而不是作爲\0,你可以使用memcpy()

char b[sizeof(a)]; 
memcpy(b, a, sizeof(a)); 

sizeof(a)字節a複製到b

閱讀關於memcpy()here

由於John指出的那樣,如果你有a作爲參數傳遞給函數像

void fn(char b[], char a[]); 
... 
... 
fn(b, a); 

sizeof(a)會給指針變量的大小,這是不行的只能是所有相同指針並且不管大小爲a。這是因爲將數組傳遞給函數時,數組的地址是傳遞的,函數中的a實際上是一個指針。

這是這樣即使功能就像

int fn(char b[], char *a); 

甚至

int fn(char b[], char a[10]); 

所以,如果你路過a的功能,一定要通過它的大小,以及像

void fn(char b[], char a[], size_t len) 
{ 
    memcpy(b, a, len); 
} 
... 
... 
... 
size_t l=sizeof(a); 
fn(a, l); 
+2

需要注意的一點是:這隻適用於原始的'a'數組聲明可見的範圍。如果移動到以'a'作爲參數傳遞的函數,它將會中斷。 –

+0

@JohnBollinger謝謝指出。我編輯它。 –

+1

我編輯了我的文章,包括我無恥地被遺漏的東西,我很抱歉。謝謝。 – admbmb