質問

ANSI C のみを使用して、C スタイルの文字列が整数であるか実数 (つまり、float/double) であるかをかなり確実に判断する最善の方法は何でしょうか?

役に立ちましたか?

解決

atoi と atof は失敗すると 0 を返すため、これらの関数は使用しないでください。前回チェックしたとき、0 は有効な整数および浮動小数点であるため、型を決定するのには役に立ちません。

strto{l,ul,ull,ll,d} 関数を使用します。これらの関数は失敗時に errno を設定し、変換されたデータが終了した場所も報告します。

ストラツール: http://www.opengroup.org/onlinepubs/007908799/xsh/strtoul.html

この例では、文字列に変換対象の値が 1 つ含まれていることを前提としています。

#include <errno.h>

char* to_convert = "some string";
char* p = to_convert;
errno = 0;
unsigned long val = strtoul(to_convert, &p, 10);
if (errno != 0)
    // conversion failed (EINVAL, ERANGE)
if (to_convert == p)
    // conversion failed (no characters consumed)
if (*p != 0)
    // conversion failed (trailing data)

最初に errno を 0 に設定するのを忘れたことを指摘してくれた Jonathan Leffler に感謝します。

他のヒント

使用する sscanf, を使用すると、atoi や atof ソリューションの場合のように 0 を特別に扱う必要がなく、文字列が float か int かその他のものであるかを確認できます。

コード例を次に示します。

int i;
float f;
if(sscanf(str, "%d", &i) != 0) //It's an int.
  ...
if(sscanf(str "%f", &f) != 0)  //It's a float.
  ...

atoi と atof は変換するか、変換できない場合は 0 を返します。

strto{l,ul,ull,ll,d} 関数が最善の方法だという Patrick_O さんの意見に私も同意します。ただし、注意すべき点がいくつかあります。

  1. 関数を呼び出す前に、errno をゼロに設定します。それを行う機能はありません。
  2. リンクされている Open Group ページ (Patrick もリンクしていることに気づく前にアクセスしました) では、errno が設定されていない可能性があることが指摘されています。値が範囲外の場合は ERANGE に設定されます。それ 5月 設定されます(ただし同様に、 5月 ない 引数が無効な場合は EINVAL に設定されます。

現在の仕事に応じて、返された変換ポインターの末尾から末尾の空白をスキップし、最後の文字が終端の null '\0' でない場合に文句を言う (拒否する) ように調整することもあります。あるいは、いい加減になって最後にゴミが表示されるようにすることもできますし、キロバイト、メガバイト、ギガバイト、テラバイトなどを表す 'K'、'M'、'G'、'T' などのオプションの乗数を受け入れることもできます。またはコンテキストに基づくその他の要件。

文字列をステップスルーして、何かがあるかどうかを確認できると思います . その中の文字。ただし、それは私の頭に最初に浮かんだことなので、より確実にするための他の(より良い)方法があると確信しています。

整数をチェックするには、strtol/strtoll (atoi ではありません) を使用します。double をチェックするには、strtof/strtod (atof ではない) を使用します。

atoi と atof は文字列の最初の部分を変換しますが、文字列全体が使用されたかどうかはわかりません。strtol/strtod は、文字が変換された後に余分なジャンクがあったかどうかを示します。

したがって、どちらの場合も、必ず null 以外の TAIL パラメータを渡し、それが文字列の末尾 (つまり **TAIL == 0) を指していることを確認してください。また、アンダーフローとオーバーフローの戻り値も確認してください (詳細については、マニュアル ページまたは ANSI 規格を参照してください)。

strod/strtol は最初の空白をスキップするため、最初の空白を含む文字列を不正な形式として扱いたい場合は、最初の文字もチェックする必要があることにも注意してください。

それは、そもそもなぜ質問するのかによって異なります。

数値を解析したいだけで、それが浮動小数点か整数かわからない場合は、浮動小数点数を解析するだけで、整数も正しく解析されます。

トリアージなどのために実際にタイプを知りたい場合は、最も関連性が高いと思われる順序でタイプをテストすることを検討する必要があります。たとえば、整数を解析してみて、それができない場合は浮動小数点数を解析してみます。(逆の場合は、float がもう少し多く生成されるだけです...)

atoi と atof は、末尾に数値以外の文字がある場合でも数値を変換します。ただし、strtol と strtod を使用すると、先頭の空白とオプションの記号がスキップされるだけでなく、数値に含まれていない最初の文字へのポインターが残ります。その後、残りが空白であることを確認できます。

strtoul のような新しい関数を使用したくない場合は、別の strcmp ステートメントを追加して、文字列が 0 かどうかを確認することもできます。

つまり

if(atof(token) != NULL || strcmp(token, "0") == 0)
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top