0
#include <iostream>
using namespace std 
#include <string.h>
int main(){
    char token[] = "some random string";
    char c[23];  
    strcpy( c, token);
    strncpy(c, token, 5); 
    c[strlen(c)] = '\0';
    cout<<c;
    return 0 ;
}

私の出力は次のとおりsome random stringです。しかし、私はそれが次のようになることを期待していますsome。なぜこのように振る舞うのか、誰か説明してもらえますか?

4

4 に答える 4

6

これは問題なく機能しています。strncpy文字列を必ずしもnullで終了するわけではないことに注意してください。これを行うとき:

strncpy(c, token, 5);

の最初の5バイトをにコピーしますがtokenc 結果をnullで終了しません。さらに、この行は役に立ちません。

c[strlen(c)] = '\0';

strlen(c)既存のヌルターミネータを探し、見つけたらすぐに別のヌルターミネータで上書きします。これは無意味です。

新しいコードでは、使用されることstrncpyめったにありません。その使用目的(必ずしもnullで終了するわけではない固定長のバッファー)は長い間廃止されてきました。代わりに次のような関数を優先しますstrlcpy(注:strlcpy標準ではありません。BSDのようなシステムでのみ使用できます)。

または、純粋なCではなくC ++でコーディングしている場合は、std::stringこのようなトリッキーな問題を使用して回避してください。

于 2012-12-25T03:51:28.430 に答える
4

2行のコードは何もしないので、出力は「ランダムな文字列」である必要があると思います。コメントを参照してください。

int main(){
   char token[] = "some random string";
   char c[23];  
   strcpy( c, token);
   strncpy(c, token, 5);  // Does nothing
   c[strlen(c)] = '\0';   // Does nothing
   cout<<c;
   return 0 ;
}

「some」を出力したい場合は、次のように実行できます。

strncpy(c, token, 5);
c[5] = '\0';

strncpy()は、末尾の「\0」をdest文字列に自動的に追加しません。ソース文字列の長さがlen(strncpyの3番目の引数)より大きい場合、len文字は末尾の「\0」なしでdestにコピーされます。したがって、末尾の「\0」をコードで明示的に指定する必要があります。

于 2012-12-25T03:51:32.427 に答える
1

文字列全体の後でnullを終了するのではなく、「some」という単語の後でnullを終了する必要があります。strncpyは「some」をcにコピーしますが、必ずしも文字列をnullで終了するわけではありません(strncpyのマニュアルページを参照) 。

c[4] = '\0'
于 2012-12-25T03:51:18.500 に答える
0

snprintf他の人が述べているように、とは異なりsprintfstrncpyのより安全なバージョンではありませんstrcpy。「正確にN文字が宛先にコピーされる(ソース文字列がNより短い場合はNULを使用する)」ことを保証するだけです。(manページ)

しかし、私はあなたがすでにラインによってそれに気づいたと思います

c[strlen(c)] = '\0';

これは、のnull終了を保証することを意味しましたcstrlenしかし、 NULを使用しての長さを決定するため、実際には無意味ですc。したがって、この行は「NULを見つけてその場所にNULを書き込む」ことをほとんど意味しません。

の重要性はstrncpy、文字列のcertian部分をコピーすることです。これはの修正ではなく、関数strcpyの導入前に存在していました。snprintf

于 2012-12-25T07:26:53.750 に答える