2010-12-03 17 views
0

スペースがない場合は、 "/" Cの前に空白を入れることができるこの関数を得ました。そして、文字列をうまくカットしますが、文字列を連結するときにエラーが発生し、メモリ違反が発生する可能性があります。私に手を差し伸べてください。Cでの文字列連結

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

char* substr(const char *pstr, int start, int numchars) { 
    char* pnew = malloc(numchars + 1); 
    strncpy(pnew, pstr + start, numchars); 
    pnew[numchars] = '\0'; 
    return pnew; 
} 

char* fixString(char str[]) { 
    char* position; 
    char* newString = ""; 
    char* finalString; 

    int oldPosition = 0; 
    printf("Original str: %s\n", str); 
    printf("Original length: %d\n\n", strlen(str)); 

    position = strchr(str, '/'); 
    while (position != NULL) { 
     int charPosition = position - str; 

     printf("String position: %d->%d\n", oldPosition, charPosition); 
     newString = substr(str, oldPosition, charPosition - oldPosition); 
     oldPosition = charPosition; 
     if (charPosition > 0 && str[charPosition - 1] != ' ') { 
      printf("Previous char: %c\n", str[charPosition - 1]); 
      newString = strcat(newString, " "); 
     } 

     printf("String: |%s|\n", newString); 
     if (strlen(newString) > 0) { 
      finalString[0] = strcat(finalString, newString); 
     } 
     printf("------------\n"); 
     position = strchr(position + 1, '/'); 
    } 
    char* lastString = substr(str, oldPosition, strlen(str)); 
    finalString = strcat(finalString, lastString); 
    printf("lastString: %s\n\n", lastString); 
    return finalString; 
} 

int main() { 
    char* testString = "/Filter /FlateDecode/Length 7108/Subtype /Type1C"; 
    printf("%s", fixString(testString)); 

    return 0; 
} 
+0

質問の形で言い換えてください。ありがとう。 –

+1

あなたの 'newString'と' finalString'には 'malloc'メモリがありません。 – birryree

+0

質問:私は間違って何をしていますか? –

答えて

2

ターゲットバッファを割り当てないでください。 finalString変数は何も初期化されていません。

あなたのコードでは、それだけで問題はありません。 char *をある種のスマートな文字列型として扱っているようですが、メモリ位置へのポインタ以上のものではありません。たとえば、次のようになります。

newString = strcat(newString, " "); 

2つの文字列を連結し、連結した結果を返しません。 charバッファnewStringにスペースを追加し、同じバッファを返します。 newStringへの代入は無害ですが、誤解を招きます。

// It is the callers responsibility to free the returned string. 
char *fixString(char *str) { 
    int len; 
    char *s; 
    char *dest; 
    int after_space; 

    // First pass, figure out the size of the output. 
    len = 0; 
    after_space = 0; 
    for (s = str; *s; s++) { 
     len += 1 + (!after_space && *s == '/'); 
     after_space = *s == ' '; 
    } 
    dest = malloc(len + 1); 

    s = dest; 
    after_space = 0; 
    while(*str) { 
     if (!after_space && *str == '/') *s++ = ' '; 
     after_space = (*s++ = *str++) == ' '; 
    } 
    return dest; 
} 
+0

私に見せてくれますか? –

+0

私はあなたが誤解していると思います。私は "/"で "/"を既に変更したいと思っています。 –

+0

@トーマス:私が言ったように、私はあなたのコードを深く分析しませんでした。重要なことは、まずバッファを割り当て、必要なロジックに応じてソース文字列からコピーすることでバッファを設定する必要があることです。この場合、ソース内のすべての文字が '/'である場合、または2回のパスがある場合にのみスペースを2倍に割り当てるか、結果バッファの大きさを求めるために1回、実際の転写を行います。 –

0

finalStringのメモリを割り当てる必要があります。

はこのようにそれをやって試してみてください。

#define BUFFER_SIZE 1024 
char* finalString = malloc(BUFFER_SIZE); 
// ... 
strncat(finalString, "something", 1024); 

はあなたがいないあなたの関数で(もうそれを必要としないとき、ポインタにfree()を呼び出すことを忘れないでください - いつでも、関数が戻った後、どこかのクライアントコードで結果は必要ありません)。

0

newStringfinalStringポインターのメモリは決してmallocではありません。 strcatは、それに与えたデスティネーションポインタに文字列を格納するのに十分なスペースがあることを想定しています。

+0

さて、私はこの点でnewStringに問題はありませんでした。 newStringはsubstrによってmallocされています。 –

+0

@Thomas - それは本当です、 'substr'は' newString'のポインタを 'malloc'しますが、それは潜在的に問題である可能性があります:a)決してポインタをフリーにしません。b) strcat'を 'newString'に変換し、' newString'には結果として連結された文字列を格納するのに十分なスペースが割り当てられません。 – birryree

+0

私は見るので、whileループでは、各実行の間にnewStringを解放する必要があります。 –

0

また、必要に応じてmalloc()とrealloc()の後にサイズをチェックする必要があります。 Cでメモリ管理の美しい世界へようこそ。