2014-07-15 57 views
3

好的,所以我是一個通常編寫Java/C++的人,而且我剛剛開始寫作C.我目前正在編寫一個詞法分析器,而我無法忍受C中字符串的工作方式,因爲我無法執行字符串算術。所以這是我的問題:將數組中的字符附加到char指針

char* buffer = ""; 
char* line = "hello, world"; 

int i; 
for (i = 0; i < strlen(line); i++) { 
    buffer += line[i]; 
} 

我該怎麼做在C?由於上面的代碼無效C,我該如何做這樣的事情? 基本上我循環雖然一個字符串line,我試圖追加每個字符buffer字符串。

+0

好吧,如果我通過循環線路,我如何通過一個單一的字符通過的strcpy這需要(字符*,爲const char *)? –

+1

@ user3839220:你要做的是將字符串複製到'buffer'。所以,只需用'strcpy()'調用你的整個'for'循環即可。 – Krumia

+0

[在C++中創建可修改的字符串文字]的可能的重複(http://stackoverflow.com/questions/3055240/create-a-modifiable-string-literal-in-c) – Sadique

回答

0
#include <string.h> 

//... 

char *line = "hello, world"; 
char *buffer = (char *) malloc(strlen(line) + 1); 

strcpy(buffer, line); 

儘管在C字符串文字具有類型非const陣列最好是聲明由字符串文字與限定符const的初始化指針:

const char *line = "hello, world"; 

在C/C字符串文字++是不可變的。

如果要追加的字符,則代碼可以看看下面的方式(行的每一個字符被附加在一個循環緩衝)

#include <string.h> 

//... 

char *line = "hello, world"; 
char *buffer = (char *) malloc(strlen(line) + 1); 

buffer[0] = '\0'; 
char *p = Buffer; 

for (size_t i = 0; i < strlen(line); i++) 
{ 
    *p++ = line[i]; 
    *p = '\0'; 
} 

一般的做法是,你會發現指針終止零將其替換爲目標字符前進指針並且輸出新的終止零。源緩衝區應足夠大以容納一個字符。

2

首先緩衝區需要有或超過正在複製到它的數據的長度。

char a[length], b[] = "string"; 

然後將字符複製到緩衝區。

int i = 0; 
while (i < length && b[i] != '\0') { a[i] = b[i]; i++; } 
a[i] = '\0'; 

,如果你需要,只是在兩個字符串中的最小長度值開始i,並且遞減值,而不是增量可以顛倒順序。正如其他人所建議的那樣,您也可以使用該堆,以便對任意值或變化值進行座標變換,即length。此外,你可以用指針更改了代碼段(並給你發生了什麼更好的主意):

int i = 0; 
char *j = a, *k = b; 
while (j - a < length && *k) { *(j++) = *(k++); } 
*j = '\0'; 

確保查找memcpy;並且不要忘記null結束符(oops)。

+0

'B [我]!= '\ 0''和'a [i] ='\ 0';' – chouaib

+0

謝謝,@chouaib – motoku

1

字符串文字在C中是不可變的。修改一個會導致未定義的行爲。如果你想添加一個字符分配一個字符串

#include <stdio.h> 

int main(void) { 


    char * line = "hello, world"; 
    char buffer[32]; // ok, this array is big enough for our operation 

    int i; 
    for (i = 0; i < strlen(line) + 1; i++) 
    { 
     buffer[i] = line[i]; 
    } 

    printf("buffer : %s", buffer); 

    return 0; 
} 
0

如果使用char陣列(你的緩衝區)大到足以容納你的角色,你仍然可以修改其內容堆,這裏的做到這一點的一種方法:

size_t length = strlen(buffer); 
char *newbuffer = realloc(buffer, length + 2); 
if (newbuffer) { // realloc succeeded 
    buffer = newbuffer; 
    buffer[length] = newcharacter; 
    buffer[length + 1] = '\0'; 
} 
else { // realloc failed 
    // TODO handle error... 
    free(buffer); // for example 
} 

然而,這是低效的循環反覆這樣做,因爲你要反覆呼籲strlen()(基本)相同的字符串,並重新分配緩衝區,以便每次再適合一個字符。

如果您希望更明智地進行重新分配,請將緩衝區的當前分配容量與其中字符串的長度分開跟蹤 - 如果您瞭解C++,請考慮std::string對象的「大小」與其之間的差異「容量」 - 當需要重新分配時,將緩衝區的大小乘以一個縮放因子(例如加倍)而不是加1,這樣重新分配的數量是O(log n)而不是O(n)。

這是一個很好的字符串類在C++中會做的事情。在C中,你可能會想將這個緩衝區管理的東西放到它自己的模塊中。

+0

這是我試過的,但是當我運行可執行文件時,它似乎總是掛起來? –

+0

我還沒有看到你的代碼,所以我不能告訴你爲什麼它掛起。使用調試器和/或詢問關於該問題的更多細節的其他問題。 – Wyzard

+0

不知道如何把代碼放在這裏,所以我會編輯我的文章。 –

0

最簡單的解決方案,缺乏任何情況下,是要做到:

char buffer[ strlen(line) + 1 ]; 
strcpy(buffer, line); 

您可以用來使用指針在Java中的一切(因爲非原始類型的Java是比什麼其實更像共享指針其他)。然而,你不一定非得在C中這樣做,如果你這樣做可能會很痛苦。

給你的背景可能是一個好主意,在C中使用一個計數的字符串對象,其中字符串對象擁有其數據。寫struct my_string { char *data; size_t length; }。編寫用於創建,銷燬,複製以及任何其他需要的操作(如附加字符或檢查長度)。 (與實現分開的接口!)另外一個有用的補充是使其分配比length多一個字節,以便您可以有一個函數,該函數可以空終止並允許它傳遞給一個函數,該函數需要只讀C風格的字符串。

這裏唯一真正的缺陷是要記住在進行復制操作時調用函數,而不是允許結構分配發生。 (當然,您可以使用結構分配進行移動操作!)

0

asprintf函數對於構建字符串非常有用,可用於基於GNU的系統(Linux)或大多數基於BSD的系統。你可以做這樣的事情:

char *buffer; 
if (asprintf(&buffer, "%s: adding some stuff %d - %s", str1, number, str2) < 0) { 
    fprintf(stderr, "Oops -- out of memory\n"); 
    exit(1); } 
printf("created the string \"%s\"\n", buffer); 
free(buffer); /* done with it */