6

の仕様でstrtolは、入力文字列を「最初の空白」、「サブジェクト シーケンス」、および「最終文字列」に概念的に分割し、「サブジェクト シーケンス」を次のように定義しています。

入力文字列の最長の最初のサブシーケンスで、予期される形式の最初の非空白文字で始まります。入力文字列が空であるか、完全に空白文字で構成されている場合、または最初の非空白文字が記号または許容される文字または数字以外である場合、サブジェクト シーケンスには文字が含まれません。

かつて、「最長の最初のサブシーケンス」ビジネスは、失敗した一致としてスキャンし、次の未読文字としてスキャンする方法に似てscanfいると考えていました。ただし、いくつかの議論の後、予想される形式の可能な文字列の最初の部分シーケンスである最長の初期文字列ではなく、予想される形式である最長の最初の部分シーケンスを処理することがほぼ確信しています。"0x@""0x""@"strtol

まだ私を混乱させているのは、仕様の次の言語です。

サブジェクト シーケンスが空であるか、期待される形式を持たない場合、変換は実行されません。endptr が NULL ポインターでない場合、str の値は endptr が指すオブジェクトに格納されます。

「サブジェクト シーケンス」の正しい定義であると思われるものを受け入れる場合、期待される形式を持たない空でないサブジェクト シーケンスなどは存在せず、代わりに (冗長性と混乱を避けるために) テキストは単に読む必要があります。 :

サブジェクト シーケンスが空の場合、変換は実行されません。endptr が NULL ポインターでない場合、str の値は endptr が指すオブジェクトに格納されます。

誰かが私のためにこれらの問題を明確にすることができますか? おそらく、過去の議論や関連する欠陥レポートへのリンクが役立つでしょう。

4

4 に答える 4

3

C99 言語は非常に明確だと思います。

サブジェクト シーケンスは、最初の非空白文字から始まる、入力文字列の最長の初期サブシーケンスとして定義されます。これは、期待される形式です。

与えられた は、期待される形式ではありません"0x@"。予期された形式ではありません。したがって、期待される形式の最長の初期サブシーケンスです。"0x@""0x""0"

これは、次のように解釈しない限り、期待される形式ではない空でないサブジェクト シーケンスを持つことはできないことを意味することに同意します。

ロケール以外では"C"、追加のロケール固有のサブジェクト シーケンス フォームが受け入れられる場合があります。

...ロケールが、サブジェクトシーケンスが持つ可能性のある他の可能なフォームを定義できるようにするため、それにもかかわらず、「期待されるフォーム」ではありません。

最後の段落の文言は、単なる「ベルトとブレース」のようです。

于 2011-07-15T01:37:10.583 に答える
2

¶4 ではなく、C99 標準の §7.20.1.4 (strtol、strtoll、strtoul、および strtoull 関数) ¶2 から始めた方が理解しやすいかもしれません。

¶2 strtol、strtoll、strtoul、および strtoull 関数は、nptr が指す文字列の最初の部分を、それぞれ long int、long long int、unsigned long int、および unsigned long long int 表現に変換します。最初に、入力文字列を 3 つの部分に分解します。空白文字の最初の、場合によっては空のシーケンス (isspace 関数で指定)、base の値によって決定される基数で表される整数に似たサブジェクト シーケンス、および入力文字列の終端のヌル文字を含む、1 つ以上の認識されない文字の最終文字列。次に、サブジェクト シーケンスを整数に変換しようとし、結果を返します。

¶3 base の値がゼロの場合、サブジェクト シーケンスの期待される形式は、6.4.4.1 で説明されている整数定数の形式であり、オプションでプラス記号またはマイナス記号が先行しますが、整数の接尾辞は含まれません。base の値が 2 ~ 36 (両端を含む) の場合、サブジェクト シーケンスの期待される形式は、base で指定された基数を持つ整数を表す文字と数字のシーケンスであり、オプションでプラス記号またはマイナス記号が前に付いていますが、整数サフィックス。a (または A) から z (または Z) までの文字は、10 から 35 の値に割り当てられます。base の値より小さい値の文字と数字のみが許可されます。base の値が 16 の場合、オプションで文字 0x または 0X を一連の文字と数字の前に置くことができます。記号がある場合はその後に続きます。

¶4 サブジェクト シーケンスは、入力文字列の最長の最初のサブシーケンスとして定義されます。

特に、¶3 では、サブジェクト シーケンスとは何かを明確にしています。

于 2011-07-15T05:08:35.027 に答える
1

私はあなたの評価に完全に同意します。定義上、空でないすべてのサブジェクト シーケンスは期待される形式であるため、標準の文言は疑わしいものです。

浮動小数点変換関数の場合、別の失敗があります (C99:TC3 セクション 7.20.1.3、§3):

[...] サブジェクト シーケンスは、最初の非空白文字から始まる、入力文字列の最長の初期サブシーケンスとして定義されます。これは、期待される形式です。入力文字列が予期された形式でない場合、サブジェクト シーケンスには文字が含まれません。

これは、入力文字列全体が期待される形式でなければならないことを意味し、endptrパラメーターの目的を無効にします。入力文字列の予想される形式は、サブジェクト シーケンスの予想される形式とは異なると主張する人もいるかもしれませんが、それでもかなり紛らわしいです。

strto*()と関数ファミリのセマンティクスが異なることも正しいです*scanf(): 両方が一致する場合、それらは常に値に同意し、同じ数の文字を消費します (そして、newlib と glibc を含む、それらが一致しない libc 実装はすべて壊れています)。前回チェックしたとき)、*scanf()さらに、例のように、複数の文字をバックトラックする必要があるケースと一致しませ"0x@""1.0e+"

于 2011-07-15T08:18:58.847 に答える
1

strtolのPOSIX 仕様はより明確なようです。

これらの関数は、str が指す文字列の最初の部分をそれぞれ long 型と long long 型の表現に変換します。まず、入力文字列を 3 つの部分に分解します。

  1. 最初の、場合によっては空の空白文字のシーケンス (isspace() で指定)

  2. base の値によって決定される基数で表される整数として解釈されるサブジェクト シーケンス

  3. 入力文字列の終端の NUL 文字を含む、1 つ以上の認識されない文字の最終文字列。

次に、サブジェクト シーケンスを整数に変換しようとし、結果を返します。

しかしもちろん、それは規範的ではなく、「ISO C 標準に従う」ものです。

于 2011-07-14T23:24:39.540 に答える