2013-02-14 2 views
5

strcmp()(no 'n')は、どちらの引数にもヌル文字が表示されるとすぐに処理を停止し、結果を返します。
したがって、引数の1つがヌルで終了することが100%確実であることがわかっている場合(たとえば、文字列リテラルの場合)、strncmp()( 'n')を使用した場合のセキュリティ上のメリットはありません。strlen()strcmp()は既知の終端文字列より多くの文字を読み取ることは決してないため、第3引数の一部を使用して、既知の文字列長との比較を制限します。それが知られている、終端の大きさに時間を浪費線形ことにstrncmp()式のstrlen()は、strcmp()をstrncmp()を使用する目的を無効にしますか?

実際には、長さ引数strncmp()への呼び出しがstrcmp()ケースからのみ異なる最初の二つの引数の1にstrlen()されているように私には思えます文字列をstrlen()と評価してください。

は考えてみましょう:

サンプルコードA:

if (strcmp(user_input, "status") == 0) 
    reply_with_status(); 

サンプルコードB:

if (strncmp(user_input, "status", strlen("status")+1) == 0) 
    reply_with_status(); 

を、後者を超える前者どんな利点がありますか?私は他人のコードでそれを見ているので、小物

これらの機能の仕組みに間違いがありますか?

答えて

5

、私はそれが理由のstrncmpを使用するために有害だと言うでしょう:strlenを使用して

  • ことを確認する1の文字列リテラル"status"
  • 添加のスキャンとにかく
  • 繰り返しを行いますその文字列は実際には等しいです

これらはすべて混乱につながりますが、いずれの場合も保護されませんdが実際に6文字より短く、テスト文字列と同じ文字が含まれていた場合、オーバーフローすることはありません。user_input

これは例外的です。入力文字列がテスト文字列の文字数より常に多くのメモリを持っていることがわかっている場合は、心配しないでください。そうでなければ、あなたはかもしれません。は心配する必要があります。 strncmpは、大きなバッファー内のものをテストするのに便利です。

私の好みは、コードの可読性です。

+0

私はあなたをupvoteしたが、私は十分な評判を持っていない。 :pあなたの詳細な答えをありがとう! – cvp

+0

ほとんどのコンパイラは 'strlen(" status ")'を定数として計算できます。それ以外の場合は同意します。 –

4

はい、あります。 strncmpでstrlenを使用すると、文字列にヌルが入るまでポインタをトラバースします。これはstrcmpと機能的に同等です。あなたの特定の例では

+0

iは、その後1を同じ状態でしょう。私がstrncmpを使用するとき、第2引数はuser_inputの最大サイズです(user_inputがuser_inputの場合はしばしばsizeof(user_input)、char [])。これはガーディアンです。 –

0

今、私はこれがstrncmp()の特に有用な使用ではないことに同意し、strcmp()よりもこれで何のメリットも見られません。

strlenの後に+1を削除してコードを変更すると、有効になります。

strncmp(user_input, "status", strlen("status")) 

すなわち `「ステータス」とuser_inputの最初の6つの文字を比較するため - 少なくとも時々意味があります。

だから、もし+1があれば、それは普通のstrcmpになります。それはちょうど時間を計算する時間の無駄です。しかし、+1がなければ、それは(適切な状況下で)非常に便利な比較です。

+0

非常に良い点。これは、入力システムが実装されているかどうかを区別するためのコマンドワードのタイプです。あなたが "st"で始まる他のコマンドを持っていないと仮定して 'if(!strncmp(command、" st "、2))/ * ... * /'お返事をありがとうございます! – cvp

+0

はい、この疑似コードのようになる傾向がありますが、 'count = 0; for(i:all_commands){if(match_cmd(command、i)){一致= i;カウント++; }} if(count == 1)execute_command(i);それ以外はprint( "もっとタイプする必要があります...");'; –

4

あなたが与えた特別なケースでは、実際には役に立たないです。しかし、わずかな変更は、より一般的です:

if (strncmp(user_input, "status", strlen("status")) == 0) 
    reply_with_status(); 

それは異なる意味を持っているので、user_inputは、"status"を開始した場合、このバージョンはちょうどチェックします。

+0

あなたの返事をお寄せいただきありがとうございました! – cvp

+0

ああ、あなたは早かった!彼らは素晴らしい心について何を言う... – wildplasser

0

strncmp()は使用が制限されています。通常のstrcmp()は、2つの文字列のいずれかでNULを検出すると停止します。 ( "その文字列が最初のN文字で等しい")

stncmp()の1つの可能な使用法は、解析オプションであり、 signifacant一部、例えば "-string" または "-sadistic" のための " - 状態" または "-st0" が、ないゼロを返します

if (!strncmp("-st", argv[xx], 3)) {} 

、。

2

文字列の先頭が入力と一致するかどうかを確認する以外に、strncmpは、文字列が割り当てられた領域の終わりより前にNULL終了することを100%確信していない場合にのみ役立ちます。だから、

、あなたはあなたが使用できるとして、ユーザーの入力をした固定サイズのバッファを持っていた場合:

strncmp(user_input, "status", sizeof(user_input)) 

は、したがって、あなたの比較がオーバーフローしないことを確実にすること。

しかし、この場合は、user_inputがnullで終了していない場合、user_inputがステータスの先頭に一致するかどうかを実際に確認するので、注意する必要があります。

良い方法は言うことかもしれません:

if (user_input[sizeof(user_input) - 1] != '\0') { 
    // handle it, since it is _not_ equal to your string 
    // unless filling the buffer is valid 
} 
else if (strcmp(user_input, "status")) { ... } 
+0

user_input [sizeof(user_input)-1]!= '\ 0 '、そうでなければあなたはuser_input配列の外にいます。 –

+0

おっとり。ありがとう。 – jmh

関連する問題