2017-08-30 19 views
-1

2つの文字列を文字通り結合するC言語で、ポインタと配列について少しだけ学ぶために、単純なstr_join関数を作りたかったのです。C - 独自のstr_join関数が機能しない

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

int str_size(char *str); 
void str_join(char *str1, char *str2); 

int main(int argc, char **argv) 
{ 
    char *part1 = "Hello "; 
    char *part2 = "World!"; 
    str_join(part1, part2); 
    printf("%s\n", part1); 
    return 0; 
} 

int str_size(char *str) 
{ 
    char c; 
    for(int i = 0;; i++) 
    { 
     c = str[i]; 
     if(c == '\0') 
      return i + 1; 
    } 
} 

void str_join(char *str1, char *str2) 
{ 
    int str_size_1 = str_size(str1) - 1; //Last char is '\0', don't need them 2 times 
    int str_size_2 = str_size(str2); 
    char str3[str_size_1 + str_size_2]; 
    int i; 

    for(i = 0; i < str_size_1; i++) 
     str3[i] = str1[i]; 

    for(i = 0; i < str_size_2; i++) 
     str3[i + str_size_1] = str2[i]; 

    str1 = (char *)str3; 
} 

(単純すぎるかもしれません)単純です。 私がする出力を除外:

Hello World 

が、それは次のようになります。私は、以下のコマンドを使用してプログラムをコンパイル

Hello 

gcc main.c -o main 

そして、それを実行しました:

./main 

私は自分の失敗を見ない、誰かが私のエラーに私を向けることができますか? 私を助けてくれてありがとう!

答えて

1

Cでは、関数の引数は値渡しです。関数内からパラメータを変更しても、呼び出し元には反映されません(実際の引数)。

したがって、あなたのケースでは、str1 = (char *)str3;は、あなたが思う通りのことをしません。

それは、待って、言った! str3はVLAで、ライフタイムはブロックスコープです。おそらく、最初の要素のアドレスを返すことはできませんし、メモリの場所にアクセスするためのスコープ外では有効であることを期待することはできません。それは、その範囲 outlivesようにメモリを割り当てる必要があります。あなたが持っているいずれかの

  • 使用(のVLAと組み合わせることができない)staticストレージ有するアレイ
  • 使用メモリアロケータ関数
+0

私はstr1のアドレスをstr3のアドレスに変更していませんか? – l1677783

+0

@ l1677783 str1は関数内のローカル変数です(関数の引数はローカル変数のように動作します)。 'str1 =(char *)str3'は、そのローカル変数がstr3を指すように変更します。あなたはmain()にあるpart1変数を変更していません。 main()はpart1ポインタのコピーをstr_join()関数に渡します。 (注、ポインタのコピーではなく、ポインタが指すもののコピー) – nos

+0

@ l1677783ええ、あなたですか?もう一度チェック.... –

0

関数から戻ってきたと思われるポインタは返されません。

str1 = (char *)str3; 

は、あなたはそれが(正しく)を指すように、これは文字列str3に入社str1を変更することを想定しているように見えるが、この変更は、関数の可視外ではありません。

あなたは(少なくとも)2通りの方法でこの問題を解決することができます

1)malloc

char *str3 = malloc(str_size_1 + str_size_2); 

に割り振り、その後、(代わりに)ボイドの機能

やからこのポインタを返します2)

このような関数へのポインタへのポインタを渡します。

void str_join(char **str1, char *str2) 

そして

*str1 = str3; 
0

あなたが達成したい目標は、関数呼び出し元のメソッドの参照方法で呼び出しの助けを借りて行われます。しかし、あなたのコードでは、str_joinは値による呼び出しです。 str1の値を変更すると、機能の範囲だけが変更されます。 str_joinスコープから出てくるとすぐに、str1の値は、str1のアドレスではなく、str1という値のコピーであるため、関数に渡すものが以前のものに変更されます。あなたは代わりに、これを試してみてください:

void str_join(char **str1, char **str2) 

// though the str2 need not to be passed by reference you can leave it as it is now

次に、あなたのようにあなたのメイン機能でそれを呼び出すことができます*str1

で関数内str1を交換してください:&符号が意味str_join(&str1, &str2)

あなたはstr1str2

のアドレスを渡しています
0

ここに必要なことを実装する方法はたくさんあると確信しています。 Cで合理的に慣用的なやり方は、元の文字列を保持し、呼び出し元に戻すのに十分な大きさの新しい動的に割り当てられた文字列を作成することです。

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

char *str_join(char *str1, char *str2) 
    { 
    char *result = malloc (strlen (str1) + strlen (str2) + 1); 
    strcpy (result, str1); 
    strcat (result, str2); 
    return result; 
    } 

int main(int argc, char **argv) 
    { 
    char *part1 = "Hello "; 
    char *part2 = "World!"; 
    char *joined = str_join(part1, part2); 
    printf("%s\n", joined); 
    free (joined); 
    return 0; 
    } 

発信者は結果に対してfree()を呼び出す必要があります。 "char *"を返す関数は解放しなければならないものを返すと仮定し、 "const char *"を返す関数は解放する必要のないものを返すと仮定するのが合理的な一般的な方法です。しかし、C標準ライブラリの多くの基本的で長年にわたる機能はこの慣例に従いません。

関連する問題