-6

コーディングウェブサイトソリューションからコードを理解しようとしましたが、多くのことを理解できませんでした。BITとフェンウィックの部分は理解できましたが、理解できなかったものはすべて以下に書き留めました。
このコードのソースはhttp://www.codechef.com/viewsolution/1816336
です。誰かが説明してくれると本当に助かります。標準の定義された入出力関数を使用する代わりに、なぜこれらを使用する傾向があるのか​​という概念:

char ioSpace[500000 * 17 + 128];
unsigned popcnt(unsigned x)
{
    #ifndef ONLINE_JUDGE
    return __builtin_popcount(x);
    #else
    unsigned ret;
    asm("popcntl %1, %0;":"=r"(ret) :"r"(x));
    return ret;
    #endif
}

unsigned readUInt(char*& readPos)
{
    unsigned num = 0;
    unsigned c;
    while ((c = *readPos++) >= '0')
    num = num * 10 + (c - '0');
    return num;
}

template<unsigned D>
void writeDigit(char*& writePos, unsigned& advance, unsigned& num)
{
    unsigned digit = num / D;
    num %= D;
    if (digit)
    advance = 1;
    *writePos = digit + '0';
    writePos += advance;
}

void writeUInt(char*& writePos, unsigned num)
{
    unsigned advance = 0;
    writeDigit<100000>(writePos, advance, num);
    writeDigit<10000>(writePos, advance, num);
    writeDigit<1000>(writePos, advance, num);
    writeDigit<100>(writePos, advance, num);
    writeDigit<10>(writePos, advance, num);
    advance = 1; // for zero number
    writeDigit<1>(writePos, advance, num);
    *writePos++ = '\n';
}

次に、メイン入力関数で:

    read(STDIN_FILENO, ioSpace, sizeof(ioSpace));

私はC++プログラミングにそのようなスタイルを取り入れようとしていて、理解不足のためにそうすることが避けられなかったので、誰かが私に手順全体を説明できますか?

4

2 に答える 2

1

まず、このコードがあなたの研究に値する良い模範であるという証拠は見当たりません。コメント自体が完全に欠如していると、コードを信用できなくなります。デバッガーでコードをステップスルーすることを本当に理解したい場合は、このコードでどこに行き詰まっているのかはわかりません。始めるために、読むことについてのいくつかの観察。

readUint()メソッドとwriteUint()メソッドがバッファー(おそらくioSpace)に対して機能していることは明らかですが、実際の呼び出しは表示されていないため、確認できませんが、

  read(STDIN_FILENO, ioSpace, sizeof(ioSpace));

STDINからのiospace取得日を示します。ファイルがiospaceよりも大きい場合、何が表示されるかが明確ではありません。また、エラー処理が行われることもありません。

readUint()のコードは次のとおりです。

 while ((c = *readPos++) >= '0')

次の文字を取得し、readPositionをインクリメントします。私たちがいつ止まるのかすぐに疑問に思うべきだとわかったとき。この場合、文字cが

 >= '0'

言い換えると、表示される文字がASCII '0'未満であるため、'&'や'#'などの任意の文字である可能性がありますが、おそらく作成者は改行'\n'を期待しています。 writeUint()で番号を終了します-コメントの欠如について私が何を意味するのかわかりますか?それで

c - '0'

文字「9」の数値を生成します。「0」は、9のASCIIコードから0、57〜48のASCIIコードを差し引いたもので、もちろん9です。

while ((c = *readPos++) >= '0')
    num = num * 10 + (c - '0');

次に、10を乗算し、最後に読み取った値を加算して、10進値を作成します。

現在、このコードは文字を含むファイルに対して脆弱です。次のような行があった場合に何が起こるかを見てください

 23A4\n

したがって、このコードを使用している場合は、入力を信頼する理由が必要です。

書き込みは、writedigit()関数を呼び出すことにより、数値から個々の数字を取得するだけです。

于 2013-02-11T15:38:40.127 に答える
0

うーん...readUInt関数を使用して、文字列の数値を実際の数値に変換することは間違いありません。つまり、atoi()関数と同等です。WriteDigitはその逆だと思いますが、よくわかりません。

于 2013-02-11T14:59:04.053 に答える