0

私は C が初めてで、最近 strcat 関数に問題があります。次のように定義された引数の配列があります。

#define MAXARGS 10;

char *argvalues[MAXARGS];

私が望むのは、配列の最後の非null要素をnullターミネータと連結することだけです。そのための私のコードの一部は次のとおりです。

while (argvalues[i] != NULL) {
  if (argvalues[i] == NULL){
    strcat(argvalues[i-1], '/0');
    printf("i is: %d\n", i);
    break;
  }
  i++;
}

なぜセグメンテーション違反が発生するのか、それは実際に正しい使用方法strcatですか?

4

8 に答える 8

11

ループが配列の最後を通り過ぎています。それがセグメンテーション違反の原因です。C では、初期化されていない変数が NULL になるという保証はありません。したがって、存在しないargvalues [11]にアクセスしようとするまで、ループはループし続けます。したがって、セグメンテーション違反です。

while (argvalues[i] != NULL) {
  if (argvalues[i] == NULL){

この二つは互いに矛盾しています。argvalues[i] == NULL であることを発見すると while ループが最初に終了するため、if ステートメントに到達することさえありません。そして、10 個すべての引数が設定されている場合、argvalues[11] にアクセスしようとすると、前述のように segfault が発生します。

strcat を適切に使用するには、連結する文字列を末尾に受け入れるのに十分な大きさの文字列バッファが必要です。たとえば、既に "hello" を含むバッファーに " world" を追加する場合、hello バッファーは、少なくとも "hello"+" world" にさらに 1 文字 ('\0'最後に)。

// Here's an example.
char buffer[12];
strcpy(buffer, "hello");
strcat(buffer, " world");

これを行おうとすると、失敗します。

// Buffer isn't big enough to copy into.
char buffer[] = "hello";
strcat(buffer, " world");

何をしているのかを正確に把握するには、もう少し説明とコードが必要です。引数に null ターミネータを追加するのに最適な場所は、引数が最初に設定されるときです。引数の設定方法によっては、すでに発生している可能性があります。

于 2009-11-03T19:28:45.197 に答える
2

Alcon が指摘したように、このコードでは strcat() に到達することはありません。ループを次のように変更する必要があります。

while (i < MAXARGS) {
   ...
}

また、null ポインターを strcat() に渡します。文字ではなく文字列を取ります。'\0' はヌル文字で、ヌル ポインターに「昇格」されます。"" または "\0" は空の文字列になりますが、null も追加されません。strcat(0) は、連結する前にヌル ターミネータを検索するため、ここで使用するのは適切ではありません。したがって、それを使用してヌル ターミネータを追加することはできません。

配列内の各文字列に null ターミネータがまだない場合、またはその長さがわかっている場合、null ターミネータを追加するための末尾を見つける方法がわかりません。「電話してください、電話番号を教えます」みたいな感じです。

于 2009-11-03T19:28:00.377 に答える
0

これは良い方法ではありません。

char* に「\0」がないことが確実な場合は、次のようにすることができます。

char* oldargvalues = argvalues;
while(*argvalues++);
argvalues = 0;

(oldargvalues は、char* の先頭を追跡するためのものです)。とはいえ、既に「\0」文字があるとループが終了してしまうので不思議です。

于 2009-11-03T19:29:45.047 に答える
0

Alcon と Fred が言ったことは真実です。さらに、あなたargvaluesはすでに null で終了しているように見えるため、実際に何をしようとしているのかは明確ではありません。最初の引数文字列が、割り当てたバッファ内にない限り、使用しstrcatないでください。十分な大きさがあることがわかっています。あなたが持っているのと同じように、ノーオペレーションであっても、void main(char* argv[], int argc)決して言わないでしょう。strcat(argv[i], ...)strcat(..., "")

于 2009-11-03T19:33:56.270 に答える
0

みなさん回答ありがとうございます!!!!!

私は問題を解決したと思います。主に私が行ったことは、新しいchar [size]変数を作成し、その変数に最後の引数をコピーし、その変数にnullターミネータを入れてから最後の引数にコピーすることです。正常に動作しますが、コードが乱雑です。後でうまくいくかもしれません。strcat は文字列用ではなく、文字列用です。私のコードのすべての不足を指摘してくれてありがとう!

みんな、ありがとう!!!!とても有難い!

于 2009-11-04T15:55:13.873 に答える
0

strcat は、2 つの char ポインターを次のように連結します。

char *p1[12];
char *p2 = "world";
strcpy(p1,"hello ");
strcat(p1,p2);

円周率が保持されるようになりました - Hello world 宛先に、連結された結果のための十分なスペースがあることを確認する必要があります。

于 2009-11-03T19:39:03.497 に答える
0

いくつかの問題:

argvalues 配列はすべて NULL になるように自動的に初期化されるわけではありません。手動で行う必要があるため、すぐに、while() ループで NULL を検出できません。他の人が示しているように。

argvalues はどのように設定されていますか?

于 2009-11-03T19:40:27.687 に答える
0

私はあなたが持っているループを理解していません。それは決して何もしないように見えます。while ループでは、argvalues[i] != NULL かどうかをチェックします。次のステートメントで、NULL かどうかを確認します。そのうちの 1 つは常に false になるため (NULL と非 NULL の両方にすることはできません)、このループは何もしません。次のようなものが欲しいと思います:

#define MAXARGS 10;
char *argvalues[MAXARGS];
int i = 1;
while (i < MAXARGS) 
{
   if (argvalues[i] == NULL)
   {
      //Notice here:  as mentioned by other posters, you need to pass 
      //a string to strcat, not a char
      strcat(argvalues[i-1], "");
      printf("i is: %d\n", i);
      break;
    }

    i++;
}
于 2009-11-03T19:34:51.573 に答える