0

プログラムをコンパイルして実行すると、「ランタイムチェックの失敗#2」エラーが発生することを除いて、手元のタスクですべてが正常に機能しているように見えます。ちなみに、これは私のhw割り当てであり、cstring関数のいずれかを使用するのは初めてなので、それが間違っていたと確信しています。基本的に、2つの文字列を一緒に追加していますが、結果パラメーターがオーバーランすることと関係があるとほぼ100%確信しています。修正方法がわからないだけです。

#include <iostream>
#include <cstring>
using namespace std;

void concat(const char a[ ], const char b[ ], char result[ ], int result_maxlength);
int main()
{
  char a[] = "Woozle";
  char b[] = "Heffalump";
  char c[5];
  char d[10];
  char e[20];
  concat(a, b, c, 5);
  concat(a, b, d, 10);
  concat(a, b, e, 20);
  cout << c << "\n";
  cout << d << "\n";
  cout << e << "\n";
  return 0;
}
void concat(const char a[ ], const char b[ ], char result[ ], int result_maxlength)
{
strncpy (result,a, result_maxlength);
strncat (result, b, result_maxlength);
result[result_maxlength-1] = '\0';
}
4

2 に答える 2

1

strncatnum引数は宛先の合計サイズではないため、コピーするバイト数であるため、これはかなり役に立ちません。

于 2012-09-01T04:20:27.913 に答える
1

このコードには、これまでにいくつか指摘されているいくつかの問題があります。非常に微妙なことについてはほとんど話されていないようです。POSIX仕様によると、strncpy移動されたnull以外の文字の数が指定された制限(「n」)に達した場合、の動作は文字列にnullターミネータを設定しません。 。ただし、「n」に到達するためにヌルをテールフィルします。したがって:

char ar[3];
strncpy(ar, "food", sizeof(ar)/sizeof(ar[0]));

これは、最終的にa(0)='f'、a(1)='o'、およびar(2)='o'になります。ヌルターミネータは追加されません。最後の文字は無視されます。このため、このランタイムライブラリ関数の呼び出しについてはマイナス1の注意が必要です。これを説明することは重要です。したがって、代わりにこのようなコードがよく表示されます。

char ar[3];
strncpy(ar, "food", sizeof(ar)/sizeof(ar[0])-1);
ar[sizeof(ar)/sizeof(ar[0])-1] = 0;

これにより、実際に探していたもの、つまりar="fo"が得られる可能性があります。十分なスペースの状況はこれを逆転させます。十分なスペースのあるバッファがある場合、コピーのソース文字列が「n」に到達する前に独自のターミネータに到達すると、「n」に到達するまで「n」はnullでテールフィルされます。したがって:

char ar[30];
strncpy(ar, "food", sizeof(ar)/sizeof(ar[0])-1);
ar[sizeof(ar)/sizeof(ar[0])-1] = 0;

'd'の後に26個のゼロ文字が続くar="food"になります。人々をつま先で動かし続けると、それほど明白ではないmemset-to-zeroが呼び出されます。

char ar[30];
strncpy(ar, "", sizeof(ar)/sizeof(ar[0]));

ええ、それはちょうど間違っています、私は知っています。

とはいえ、strncat()の動作が、現在信じているコードを反映しているように見えるのとは明らかに異なるのは当然のことです。たとえば、最後のパラメータは、宛先で制限する文字数を指定しません。むしろ、ソースからのコピーを制限する文字数を記述します。言い換えれば、あなたが新しい弦に​​取り組み続けるにつれて、そのテールスペースリミッターは継続的に短くなるはずです。もちろん、文字を追跡する必要があるかどうかを知るには(各ステップでコピーされます)、誰かが指摘したように、これによりstrncatの境界線が役に立たなくなり、多くの場合、実用性よりも混乱が生じます。

参考までに、動作が定義された正確な定義は、strncpystrncatで確認できます。宿題を続ける前に、両方をよく読んでおくことを強くお勧めします。

于 2012-09-01T08:06:03.750 に答える