

下記のように、３つの文字列を入力させた上で、その３つの文字列を連結した状態のものを出力させるプログラムを入力したいのですが、自分のプログラムではうまく行きませんでした。

**実行例**

[code]

    文字列1を入力してください：One
    文字列2を入力してください：Two
    文字列3を入力してください：Three
    連結した結果:OneTwoThree
    
[/code]

**ソースコード**

[code]

    int main(void)
    {
        char *s1[128],*s2[128],*s3[128];
        printf("文字列1を入力してください: ");
        scanf("%s",s1[128]);
        printf("文字列2を入力してください: ");
        scanf("%s",s2[128]);
        printf("文字列3を入力してください: ");
        scanf("%s",s3[128]);
    
        printf("%s\n",s1[128]);
        printf("%s\n",s2[128]);
        printf("%s\n",s3[128]);
    
    
        return 0;
    }
    
[/code]

**コンパイル結果**

[code]

    $ ./a.out
    文字列1を入力してください: One
    文字列2を入力してください: 文字列3を入力してください: Two
    Segmentation fault (コアダンプ)
    
[/code]

なぜ「文字列2を入力してください」と「文字列3を入力してください」の部分が識別されていないのかもわかりません。どのようにプログラムすればうまくコンパイルできるようになるのでしょうか。


CC BY-SA 4.0
2019-12-21T13:15:38.813
61651
2019-12-23T03:54:30.807
2019-12-21T13:55:47.293
32986
36412
question
c
３つの文字列を連結するプログラムの書き方。


ほぼすべての行でダメなんですが、なぜダメかを順番に解説していくと：

以下の変数定義は、文字列(128個の文字)を格納する領域では無くて、文字へのポインタを128個格納する領域を定義しています。

[code]

    char *s1[128],*s2[128],*s3[128];
    
[/code]

以下のパラメータは、s1という文字へのポインタの配列の(0番目から始まるので存在しないはずの)128番目のポインタ(さらに初期化していないから不定な値)を指定しています。

[code]

    scanf("%s",s1[128]);
    
[/code]

こちらも上記と同様ですね。実際にはこの行までは実行されずに`Segmentation fault
(コアダンプ)`が発生しているわけですが。それから「連結」せず入力値を1つ1行で表示していますね。連結処理まで手が回らなかったということでしょうか。

[code]

    printf("%s\n",s1[128]);
    
[/code]

本来なら存在しないはずのポインタの(しかも初期化していない)アドレス値を指定しているので、`文字列1を入力してください:
One`の入力が完了した時点で`Segmentation fault (コアダンプ)`が発生しても不思議では無いです。  
それ以上動作して`文字列2を入力してください: 文字列3を入力してください: Two`まで実行されたのは偶然です。

* * *

使う関数は以下の様な安全を考えた新しいものを使ったほうが良いでしょう。(VC++の資料ですが)  
[scanf_s、_scanf_s_l、wscanf_s、_wscanf_s_l](https://docs.microsoft.com/ja-
jp/cpp/c-runtime-library/reference/scanf-s-scanf-s-l-wscanf-s-wscanf-
s-l?view=vs-2019)  
[strcpy_s、wcscpy_s、_mbscpy_s、_mbscpy_s_l](https://docs.microsoft.com/ja-
jp/cpp/c-runtime-library/reference/strcpy-s-wcscpy-s-mbscpy-s?view=vs-2019)  
[strcat_s、wcscat_s、_mbscat_s、_mbscat_s_l](https://docs.microsoft.com/ja-
jp/cpp/c-runtime-library/reference/strcat-s-wcscat-s-mbscat-s?view=vs-2019)

実際にはエラー発生を検出して対処したりする処理があった方が良いのですが、プログラムとしては以下のようになります。概要をコメントで記述しています。

[code]

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <errno.h>
    #define MAX_INPUT_LEN 128  /* 最大入力長 + 1 */
    #define MAX_CONCAT_LEN 384 /* 最大連結長(3倍した値) */
    
    int main(void)
    {
        char s1[MAX_INPUT_LEN] = { 0 }; /* 入力文字の格納用の文字配列領域:初期化する */
        char s2[MAX_INPUT_LEN] = { 0 }; /* 同上 */
        char s3[MAX_INPUT_LEN] = { 0 }; /* 同上 */
        char s4[MAX_CONCAT_LEN] = { 0 }; /* 連結結果格納用の文字配列領域:初期化する */
    
        printf("文字列1を入力してください: ");
        scanf_s("%127s", s1, MAX_INPUT_LEN); /* 各入力処理:scanf_sを使い、かつ最大長を指定する */
        printf("文字列2を入力してください: ");
        scanf_s("%127s", s2, MAX_INPUT_LEN);
        printf("文字列3を入力してください: ");
        scanf_s("%127s", s3, MAX_INPUT_LEN);
    
        strcpy_s(s4, MAX_CONCAT_LEN, s1); /* 連結処理の最初は文字列コピー */
        strcat_s(s4, MAX_CONCAT_LEN, s2); /* 2個目、3個目は連結 */
        strcat_s(s4, MAX_CONCAT_LEN, s3);
        printf("連結した結果:%s\n", s4);
    
        return 0;
    }
    
[/code]


CC BY-SA 4.0
2019-12-21T15:14:41.567
61653
2019-12-21T16:16:42.753
2019-12-21T16:16:42.753
26370
26370
61651
answer


単純に直すならこんな感じです。

[code]

    #include <stdio.h>
    
    int main(void)
    {
        char s1[128],s2[128],s3[128];
        printf("文字列1を入力してください: ");
        scanf("%s",s1);
        printf("文字列2を入力してください: ");
        scanf("%s",s2);
        printf("文字列3を入力してください: ");
        scanf("%s",s3);
    
        printf("%s",s1);
        printf("%s",s2);
        printf("%s\n",s3);
    
    
        return 0;
    }
    
[/code]


CC BY-SA 4.0
2019-12-23T03:54:30.807
61694
2019-12-23T03:54:30.807
28970
61651
answer