-6

我试图从编码网站解决方案中理解代码,但无法弄清楚很多事情。我可以理解 BIT 和 fenwick 部分,但无论我不明白,我都写在下面:
此代码的来源是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 并添加我们最近读取的值来构建十进制值。

现在此代码易受包含字母的文件的攻击。看看如果你有一条线会发生什么

 23A4\n

因此,如果您使用此代码,您需要有一些理由相信您的输入。

写入只是通过调用 writedigit() 函数从数字中获取单个数字。

于 2013-02-11T15:38:40.127 回答
0

嗯...我很确定 readUInt 函数用于将字符串数字转换为实际数字,即等效于 atoi() 函数。我认为 WriteDigit 是相反的,但我不确定。

于 2013-02-11T14:59:04.053 回答