0

こんにちは、私はプログラミングにとても慣れていないので、あなたからいくつか学びたいと思っています:) 最大サイズが 5 文字の 3 つ以上の入力を取得したい。(例: HELLO、HI、GOOD、BYE) そして、それらの 4 つの文字列から同じ文字を 1 回だけ保持する新しい文字列にそれらを積み重ねたい (例: H、E、L、L、O、I、G、D 、に)

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

int main(void) {
char first[5], second[5], third[5], fourth[5];
printf("Enter 1st word: \n");   scanf(" %5s", &first);
printf("Enter 2nd word: \n");   scanf(" %5s", &second);
printf("Enter 3rd word: \n");   scanf(" %5s", &third);
printf("Enter 4th word: \n");   scanf(" %5s", &fourth);

char stack[21];  // i want a new string like this and then combine first 4 strings
                 // in this string...

return 0;
}

どの方法でできるか教えていただければ幸いです。(私もこのサイトの初心者です。これを検索しましたが、見つかりませんでした。存在する場合は申し訳ありません。)

4

3 に答える 3

1

最初にコードに関するいくつかのコメント:

  • 他の誰かがコメントで既に述べているように、 n文字列を保持するにはサイズn + 1のバッファーが必要です。これは、C では文字列の長さがどこにも格納されないためです。代わりに、文字列の終わりを示す特別な NUL バイトが文字列に追加されます。したがって、、 …、配列の長さは少なくとも 6 にする必要があります。firstfourth
  • 最悪のケースが発生し、ユーザーがそれぞれ 5 文字に相当する 4 つのバラバラな単語を入力した場合はどうなるでしょうか? 結合された文字列は 20 文字になります。したがって、stack配列は 21 文字 (終端 NUL バイトの場合は 1) に対応できる必要があります。( user3121023のコメントでも言及されています。)
  • を使用して文字列を読み取るには、 ではなくscanf型の引数を渡します。 はすでに に減衰しているため、追加でそのアドレスを使用しないでください ( のように)。そのようなバグについて通知を受けるには、コンパイラの警告を有効にしてください (少なくとも を使用してください)。(この回答を入力しているときに、 Dere0405によっても言及されました。)char *char (*)[6]firstchar *&first-Wall
  • の使用scanfは安全ではありません。ユーザーが 5 文字を超える文字列を入力すると、配列の末尾を超えて読み取ることになります。フォーマット指定子を read に変更して、5 文字目以降の読み取りを停止%5sするように指示することができます。scanfただし、これにより余分な文字が行末に残ります。より良いオプションは、入力行全体を使用fgetsまたは読み取ることです。getlineまたは、文字列をコマンドライン引数として渡すだけです (私の推奨ソリューション)。

実際の問題に移ります:

これは宿題に非常によく似ているため、完全な解決策は提供しませんが、いくつかのヒントのみを提供します。(残念ながら、他の誰かがすでに完全なコードを提供しているため、私の回答は無視される可能性があります。)

5 つの文字列すべてをループし、各文字が既にstack. ある場合は続行し、そうでない場合は に追加しますstack。文字列をループするには、次のイディオムを使用できます。

int i;
for (i = 0; first[i]; ++i)
  printf("The character at position %d is '%c'\n", i, first[i]);

または、現在のインデックスを参照する必要がない場合は、次のイディオムがよりコンパクトになります。

char * pos;
for (pos = first; *pos; ++pos)
  printf("The current character is '%c'\n", *pos);

firstC 文字列であるため、false と評価される NUL バイトで終了するという事実をどのように使用するかに注意してください。そうでなければ、反復をどこで止めればよいかわかりません。

文字列の文字をループする方法がわかったので、文字が既に追加されているかどうかを確認するにはどうすればよいでしょうか? 次の 2 つの解決策が考えられます。

  1. ループしてstack、各要素を問題の現在の文字と比較します。短い文字列ではこれが最適な方法かもしれませんが、長い文字列では効率が低下します。

  2. 文字ごとにカウンターを作成し、 に追加するたびにインクリメントしますstackchars は単なる数字であるという事実を利用できます。charしたがって、最初はすべて 0 に設定された256 要素 (256 の異なる があります) を持つ配列を作成し、現在追加されている文字の位置をインクリメントすることができます。例えば:

    int counters[256];
    memset(counters, 0, sizeof(counters));  /* fill with 0s */
    

    そして、コードの後半で:

    if (counters[(unsigned char) (*pos)]++)
      {
        /* Character was already added.  Do nothing. */
      }
    else
      {
        /* Character was not added yet.  Add it to stack. */
      }
    

    if (counters[(unsigned char) (*pos)]++)少しトリッキーです。まず、*posポインターを参照して現在の文字を生成し、配列は負のインデックスを持つことができないためpos、現在の文字として解釈されます。unsigned char次に、その位置がcounters配列で検索され、ifステートメントで評価されます。最後に、ポストインクリメント演算子を介して値がインクリメントされます (ただし、比較後のみ)。

stack最後に NUL バイトで終了することを忘れないでください。

于 2014-12-06T19:14:07.963 に答える
0

次のようにコードを更新してください。

printf("Enter 1st word: \n");   scanf(" %s", &first);

printf("Enter 1st word: \n");   scanf(" %s", first);

他の行に更新してください。

于 2014-12-06T18:24:32.383 に答える