0

私はC++が初めてです。という関数がありますisValid(const char str[]);

int isValid (const char str[])
{
  int len = strlen (str);

  if (strlen (str) != 10)
     return 0;
  if (!isdigit (str[i]))
     return 0;
  if (str==NULL)
     return 0;
  if (atol(str)==1234567890)
     return 1;
}

サンプル メイン:

int main(void)
{
   char test[10];
   cout<<"Testing NULL"<<endl;
   cout<< isValid(NULL)<<endl;

   cout<<"Testing isValid"<<endl<<"Enter test: ";
   cin>>test;
   cout<<isValid(test)<<endl;
   return 0;
}

私はこれを取得しています:

NULL のテスト

セグメンテーション違反

NULL を実装するにはどうすればよいですか。ありがとう!

4

6 に答える 6

3

のテストの順序isValidが間違っています。NULLを呼び出しstrlenたり逆参照したりする前に、最初にテストする必要がありますstr

他にもいくつかのエラーがありました:

isValidif条件が満たされない場合の戻り値を追加する必要があります。これにより警告が生成されると予想していました。そうでない場合は、警告を有効にしてコンパイルすると ( /W4MSVC の場合-Wall、gcc の場合)、フラグが立てられます。

i定義されていないためisdigit(str[i])、コンパイルされません。str私の更新されたコード(以下)は、各文字が数字であることを確認する方法を示しています

int isValid (const char str[])
{
    if (str==NULL)
        return 0;
    size_t len = strlen(str);
    if (len != 10)
        return 0;
    for (size_t i=0; i<len; i++) {
        if (!isdigit (str[i]))
            return 0;
    }
    if (atol(str)==1234567890)
        return 1;
    return 0;
}
于 2013-06-02T16:27:24.830 に答える
0

使用した構文は、コンパイラがそれを無視し、代わりにポインターを使用するという理解に基づいて、言語によって許可されています。これは、このコンテキストで意味できる唯一のことだからです。

int isValid (const char str[])

http://c-faq.com/aryptr/aryptrparam.htmlを参照してください。

コンパイラはこれを次のように正確に扱います。

int isValid(const char* str)

(理由:あなたの構文は、関数がスタック上の不明な数の文字で始まることを示唆しています)

配列が固定サイズになることが絶対にわかっていて、ポインターではなく配列を持つすべての権限と責任が必要な場合は、次のいずれかを実行できます。

int isValid(const char str[10]) // takes a copy of the array every invocation,
// I bet your next question is "why don't my changes stick"

また

int isValid(char (&str)[10])    // whee, it's an array
于 2013-06-02T17:36:51.673 に答える
0
int isValid (const char str[])
{
    if (str==NULL)
     return 0;

  int len = strlen (str);

  if (strlen (str) != 10)
     return 0;
  if (!isdigit (str[i]))
     return 0;
  //if (str==NULL)   /// this should be the first check
  //  return 0;      ///
  if (atol(str)==1234567890)
     return 1;
}
于 2013-06-02T16:27:44.497 に答える
0

設計から始めましょう。ケースの NULL について決心します。この関数の有効な入力ですか? そうでない場合は、メインでそのように呼び出さないでください。前提条件に違反しています。

NULL をテストしても問題ないと判断し、isValid がそれに基づいて動作する場合、たとえば 0 を返す場合は、そのテストを最初に追加します。ただし、その前に署名を take に変更しますconst char*。はい、内部的にはほぼ同じです。配列を渡すことはできず、実際にはポインターに変換されます。しかし、人間の場合、意図を別の方法で文書化します。私の本では、関数が配列を取る場合、言語が他の魔法を実行しても、それは実際の配列でなければなりません。ポインターを使用している間は、NULL を期待するのが公正なゲームであることを示しています。

その間に、C++ の述語関数のように、戻り値の型を bool に変更します。それに応じて、0 と 1 の代わりに false と true を返します。

3 番目の if は NULL をチェックしますが、最初の if ではすでに strlen を呼び出しています。上に移動すると、アクセス違反がなくなります。

len を const int または const auto に格納します。実際には size_t または unsigned になりますが、残りのコードは関係ありません。次に、strlen を再度呼び出すのではなく、その len 定数を使用します。

i がないため、2番目のテストは取得できません。コンパイルすることさえできません。

于 2013-06-02T16:39:54.253 に答える