8

C++、特にポインター演算の理解を深めようとしています。私はかなり頻繁にatoiを使用していますが、それがどのように機能するかについて考えたことはほとんどありません. やり方を調べてみると大体わかるのですが、一つだけ戸惑っています。

オンラインで見つけた解決策の例を次に示します。

int atoi( char* pStr ) 
{
  int iRetVal = 0; 

  if ( pStr )
  {
    while ( *pStr && *pStr <= '9' && *pStr >= '0' ) 
    {
      iRetVal = (iRetVal * 10) + (*pStr - '0');
      pStr++;
    }
  } 
  return iRetVal; 
} 

過去にどのようにアトイが行われたかを理解するのに苦労した主な理由は、キャラクターの比較方法だと思います. 「while」ステートメントは、文字が存在する間、文字が9以下で、0以上であると言っています。この声明は私に2つのことを言います:

  1. 文字は他の文字と論理的に比較できます (しかし、返される値は何でしょうか?)。

これを調べる前は無意識のうちに知っていたと思いますが、実際に考えたことはありませんでしたが、5 が 6 より小さいのと同じように、「5」の文字は「6」の文字よりも「小さい」ので、比較できます。基本的に、整数としての文字 (この目的のため)。

  1. while (*sPtr) と *SPtr != 0 はなぜか違います。これは私には当然のことのように思えますが、言葉にすることができないことに気づきました。つまり、これが真実であることは知っていますが、その理由はわかりません。

編集: *pStr - '0' の部分が何をするのかわかりません。

これらの観察を理解するための助けは非常に...役に立ちます!ありがとう!

4

8 に答える 8

4

while the character exists

No, not really. It says "while character is not 0 (or '\0'). Basically, ASCII character '\0' indicates an end of a "C" string. Since you don't want to go past the end of a character array (and the exact length is not known), every character is tested for '\0'.

Characters can be compared to other characters logically

That's right. Character is nothing but a number, well, at least in ASCII encoding. In ASCII, for instance, '0' corresponds to a decimal value of 48, '1' is 49, 'Z' is 90 (you can take a look at ASCII Table here). So yeah, you can compare characters just like you compare integers.

Somehow while (*sPtr) and *sPtr != 0 are different.

Not different at all. A decimal 0 is a special ASCII symbol (nul) that is used to indicate the end of "C" string, as I mentioned in the beginning. You cannot see or print (nul), but it's there.

于 2013-01-30T22:40:56.260 に答える
3

* pStr-'0'は、文字を数値' 1'-' 0'= 1に変換します。whileループは、文字列の最後にないかどうか、および有効な数字があるかどうかをチェックします。

于 2013-01-30T22:37:56.523 に答える
2

Cの文字は、単にASCII値として表されます。すべての数字がASCIIで連続しているため(つまり、0x30=='0'と0x39=='9'で、他のすべての数字が間にある)、範囲チェックを実行するだけで、文字が数字であるかどうかを判断できます。を引くことで桁の値を取得できます'0'

于 2013-01-30T22:38:00.537 に答える
0

C スタイルの文字列はnull で終了します

したがって:

while ( *pStr && *pStr <= '9' && *pStr >= '0' ) 

これは以下をテストします。

  • *pStrまだ文字列の終わりに達しておらず、書き込みと同等であることに*pStr != 0注意してください (一重引用符、ASCII 値0、またはがないことに注意してくださいNUL)。
  • *pStr >= '0' && *pStr <= '9'(おそらくもっと論理的に) at の文字が(ASCII 値) から(ASCII 値 )*pStrの範囲内にあること、つまり数字です。'0'48'9'57
于 2013-01-30T22:43:56.743 に答える
0

投稿された atoi の実装は完全ではないことに注意してください。Real atoi は負の値を処理できます。

while (*sPtr) と *sPtr != 0 はどうも違います。

この 2 つの表現は同じです。条件として使用する場合、アドレス sPtr に格納されている値がゼロでない場合に真*sPtrと見なされ、アドレス sPtr に格納されている値がゼロでない場合に真と見なされ*sPtr != 0ます。違いは、他の場所で使用された場合、2 番目の式は true または false に評価されますが、最初の式は保存された値に評価されます。

于 2013-01-30T22:45:13.950 に答える
0

'0'in memory osの表現0x30と is の表現'9'0x39. これはコンピューターが認識するものであり、それらを論理演算子と比較するときに、これらの値を使用します。NUL 終了文字は0x00, (別名ゼロ) として表されます。ここで重要なのは、マシンにとってchars他のものと同じであるということです。int

したがって、whileステートメントは次のように言っています。

調べている char が有効であり (ゼロではないため、ヌル ターミネータではありません)、その値 (マシンが認識する) が 0x39 未満であり、その値が 0x30 より大きい場合は、続行します。

ループの本体はwhile、文字列内の整数の位置に基づいて、アキュムレータに追加する適切な値を計算します。次に、ポインターをインクリメントして、再び実行します。完了すると、累積値が返されます。

于 2013-01-30T22:51:51.860 に答える
0

それを分解しましょう:

if ( pStr )

atoi に null ポインターを渡すpStrと、0x00- になり、これは false になります。それ以外の場合は、解析するものがあります。

while ( *pStr && *pStr <= '9' && *pStr >= '0' )

わかりました、ここでたくさんのことが起こっています。*pStrpStr が指している値が is かどうかをチェックすることを意味します0x00。ASCII テーブルを見ると、ASCII0x00は 'null' であり、C/C++ では文字列は null で終了するという慣習があります (Pascal や Java スタイルの文字列とは対照的に、長さを示してからその数の文字が含まれます)。したがって、*pStrが false と評価された場合、文字列は終わりに達したので停止する必要があります。

*pStr <= '9' && *pStr >= '0'ASCII 文字 '0' '1' '2' '3' '4' '5' '6' '7' '8' '9' の値はすべて連続しているため0x30、'0' は '9'です。です0x39。したがって、 がpStr指す値がこの範囲外である場合、整数を解析していないため停止する必要があります。

iRetVal = (iRetVal * 10) + (*pStr - '0');

メモリ内で連続している ASCII 数字のプロパティのため、数字があることがわかっている場合、*pStr - '0'がその数値に評価されることがあります。「0」の場合は 0 ( 0x30 - 0x30)、「1」の場合は 1 ( 0x31 - 0x30)... 9 です。 「9」。そこで、番号を上にシフトして、新しい場所にスライドします。

pStr++;

ポインターに 1 を追加すると、ポインターはメモリ内の次のアドレス (整数に変換する文字列内の次の文字) を指します。

この関数は、文字列がヌルで終了していない場合、非数字 ('-' など) が含まれている場合、または非 ASCII である場合に失敗することに注意してください。それは魔法ではなく、これらが真実であることに依存しているだけです。

于 2013-01-30T23:27:11.913 に答える
0

このコードのチャンクは、ASCII 値を使用して、それに相当するアルファの整数集計を蓄積しています。

最初の番号付きの箇条書きに関しては、何かを比較すると結果がブール値になることは非常に些細なことのようです。コンパイラが実際に「文字」を理解しているかどうかを尋ねようとしていたように感じますが。私の理解では、この比較は文字の ascii 値を使用して行われます。つまり、a < b は ( 97 < 98) と解釈されます。('a' は 'a' よりも小さいため、'a' と 'A' を比較すると、ASCII 値が使用されていることも簡単にわかることに注意してください)

2 番目の箇条書きについては、while ループが実際に NULL ではない値 (ASCII 値 0) が割り当てられていることを確認しているようです。and 演算子は、false ステートメントが検出されるとすぐに FALSE を生成するため、NULL 文字で比較を行うことはありません。while ループの残りの部分については、箇条書き 1 で述べたように、ASCII 比較を行っています。これは、指定された文字が、数値に関連する ASCII 値に対応しているかどうかを確認しているだけです。つまり、「0」から「9」の間 (または ascii: 48 から 57 の間)

最後に (*ptr-'0') は、私の意見では最も興味深い部分です。このステートメントは、0 から 9 までの整数を返します。アスキー チャートを見ると、0 から 9 までの数字が並んでいることがわかります。'3'-'0' は 51 - 48 で 3 になります! :D したがって、簡単に言えば、ASCII減算を行い、対応する整数値を返します。:D

乾杯、これで少し説明がつくことを願っています

于 2013-01-30T23:04:27.787 に答える