使用cin和do-while的无限循环,即使使用cin.sync来刷新缓冲区也是如此

时间:2011-11-10 19:17:30

标签: c++ validation cin

我正在尝试以下代码中的输入验证:

typedef unsigned long DATATYPE;
typedef unsigned long ADDRTYPE;
enum {READ_MEMORY, WRITE_MEMORY, PRINT_CACHE, PRINT_MEMORY, EXIT};
typedef bool BOOL;

typedef struct
{
   ADDRTYPE  nRamSize;
   DATATYPE* pMemory;
} MEMORY;

typedef struct
{
   DATATYPE data[CACHELINE_SIZE_BYTES];
   ADDRTYPE tag;
   BOOL     bValid;
} CACHELINE;

typedef struct
{
   CACHELINE CacheLine[SET_ASSOCIATIVITY];
} CACHESET;

typedef struct
{
   ADDRTYPE  nNumSets;   // Stores the number of sets in the cache
   CACHESET* pCacheSet;  // Each set contains SET_ASSOCIATIVITY slots
} SETASSOCCACHE;

int isPowerOfTwo(ADDRTYPE x)
{
   return (x != 0) && ((x & (x - 1)) == 0);
}

int main()
{
    int           nChoice;
    ADDRTYPE      nCacheSize;
    MEMORY        Memory;
    SETASSOCCACHE Cache;

    do
    {
        cout << "Enter size of memory in bytes (has to be a power of 2)" << endl;
        cin >> Memory.nRamSize;
        cin.sync();
    } while (!isPowerOfTwo(Memory.nRamSize)); // Keep taking in values till its a power of 2

    do
    {
        cout << "Enter size of cache in bytes (has to be a power of 2)" << endl;
        cin >> nCacheSize;
        cin.sync();
     } while (!isPowerOfTwo(nCacheSize)); // Keep taking in values till its a power of 2
}

根据this,使用cin.sync()应该删除用户输入中的任何尾随换行符。但是,即便如此,我仍然在第一次输入后获得无限循环。我忽略了一些明显的想法吗?

更多信息:

  • 这是在Mac OSX上,使用gcc版本4.2.1(基于Apple Inc. build 5658)(LLVM build 2335.15.00)
  • 用于输入的终端是apple提供的Terminal.app(也在iTerm2上)。
编辑 - 我开始认为这是在Mac OS X Lion中安装了XCode 4.1的g ++所特有的 - 我在我的办公室linux机器上运行相同的代码,并没有表现出这种奇怪(同样,没有其他人似乎重现了错误)。如果有人拥有Lion XCode会很好,并且可以尝试Brian的例子,看看当第一个输入是2的非幂时它们是否会得到无限循环。

谢谢大家跳进!!

2 个答案:

答案 0 :(得分:3)

如果您将代码缩减为SSCCE,您会发现没有问题:

#include <iostream>

int isPowerOfTwo(unsigned long x)
{
   return (x != 0) && ((x & (x - 1)) == 0);
}

int main()
{
    unsigned long nChoice;

    do
    {
        std::cout << "Enter size of memory in bytes (has to be a power of 2)" << std::endl;
        std::cin >> nChoice;
        std::cin.sync();
    } while (!isPowerOfTwo(nChoice)); // Keep taking in values till its a power of 2

}

这完全符合预期,因此您发布的代码并不是显示问题的实际代码,或者您的类型中存在某些棘手问题。

编辑:要解释为什么输入非数字导致循环失控,请参阅:

http://www.parashift.com/c++-faq-lite/input-output.html#faq-15.2

一旦给出无效输入,它就不会再次尝试阅读。

以下将解决这些问题(来自常见问题解答):

while ((std::cout << "Enter size of memory in bytes (has to be a power of 2)" << std::endl)
       && !(std::cin >> nChoice))
{
   std::cin.clear();
   std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}

当读入nChoice失败时,该字符将保留在流中。您必须重置流状态,然后使用ignore()

从流中删除有问题的字符

答案 1 :(得分:1)

没有sync,代码完全没问题。

我猜sync“打破”代码,因为最后有new line个字符。一旦你输入一个“好”的数字(2的幂),一切都很好。如果它不是2的幂,那么当您尝试读取数字时,您的代码会经历sync,这似乎会混淆cin