这对我来说是一项非常有趣的任务,可以让我更多地了解 C++。
承认,代码非常大并且有很多错误检查,但这仅表明在解析过程中有多少不同的事情会出错。
#include <ctype.h>
#include <limits.h>
#include <stdio.h>
#include <iterator>
#include <vector>
#include <string>
static void
die(const char *reason)
{
fprintf(stderr, "aborted (%s)\n", reason);
exit(EXIT_FAILURE);
}
template <class BytePtr>
static bool
read_uint(BytePtr *begin_ref, BytePtr end, unsigned int *out)
{
const unsigned int MAX_DIV = UINT_MAX / 10;
const unsigned int MAX_MOD = UINT_MAX % 10;
BytePtr begin = *begin_ref;
unsigned int n = 0;
while (begin != end && '0' <= *begin && *begin <= '9') {
unsigned digit = *begin - '0';
if (n > MAX_DIV || (n == MAX_DIV && digit > MAX_MOD))
die("unsigned overflow");
n = 10 * n + digit;
begin++;
}
if (begin == *begin_ref)
return false;
*begin_ref = begin;
*out = n;
return true;
}
template <class BytePtr, class IntConsumer>
void
parse_ints(BytePtr begin, BytePtr end, IntConsumer out)
{
while (true) {
while (begin != end && *begin == (unsigned char) *begin && isspace(*begin))
begin++;
if (begin == end)
return;
bool negative = *begin == '-';
if (negative) {
begin++;
if (begin == end)
die("minus at end of input");
}
unsigned int un;
if (!read_uint(&begin, end, &un))
die("no number found");
if (!negative && un > INT_MAX)
die("too large positive");
if (negative && un > -((unsigned int)INT_MIN))
die("too small negative");
int n = negative ? -un : un;
*out++ = n;
}
}
static void
print(int x)
{
printf("%d\n", x);
}
int
main()
{
std::vector<int> result;
std::string input("2147483647 -2147483648 0 00000 1 2 32767 4 -17 6");
parse_ints(input.begin(), input.end(), back_inserter(result));
std::for_each(result.begin(), result.end(), print);
return 0;
}
我努力不调用任何类型的未定义行为,这在将无符号数转换为有符号数或调用isspace
未知数据类型时会变得非常棘手。