c++ - Char* 输入检查它是十六进制还是十进制,并使用适当的错误处理和报告将其解析为无符号短整型

标签 c++

我正在尝试将输入解析为 unsigned short。输入可以是任何东西,但我们只能接受十六进制或十进制。它需要适合 unsigned short 因此没有负值或超过 0xffff (65535)。无效值必须使用 C++ 功能适本地报告错误并提供足够的信息。

我的尝试(但它不检查无效的十六进制值,例如 5xffff):

void parse_input(char *input, unsigned short &output)
{
    std::string soutput(input);

    int myint1;

    try
    {
        myint1 = std::stoi(soutput, 0, 0);
        if (myint1 > std::numeric_limits<unsigned short>::max())
        {
            std::cerr << "Value: " << myint1
                      << " is out of bounds!" << std::endl;
            exit(EXIT_FAILURE);
        }
        output = myint1;
    }
    catch (std::exception &e)
    {
        std::cerr << "exception caught: " << e.what() << std::endl;
        exit(EXIT_FAILURE);
    }
}

另一种尝试也没有做到所有这些(显然使用 errno 是 Not Acceptable ):

auto n = strtoul(argv[2], NULL, 0);
if (errno == ERANGE || n > std::numeric_limits<unsigned short>::max()) {

}
else {

}

因此,基于上述内容的实际问题是,使用 C++ 功能解决此问题的最有效方法是什么?请举例说明。

非常感谢。

最佳答案

So the actual question based on the above is, what is the most efficient and effective way to resolve this using C++ features? Please provide an example.

由于您的输入数字似乎使用 0x 来区分十六进制输入并且没有前缀用于十进制数字,因此这是一个使用自定义 I/O 操纵器的小解决方案:

std::istream& hex_or_decimal(std::istream& is) {

    char peek = is.peek();
    int zero_count = 0;
    while(peek == '0' || std::isspace(peek)) {
        if(peek == '0') {
            ++zero_count;
        }

        // Consume 0 prefixes as they wont affect the result
        char dummy;
        is.get(dummy);
        peek = is.peek();
        if((peek == 'x' || zero_count) && zero_count <= 1) {
            is.get(dummy);
            is >> std::hex;
            return is;
        }
    }

    is >> std::dec;
    return is;
}

然后像这样使用:

int main()
{
    std::istringstream iss { "5 0x42 33 044 00x777 0x55" };

    short input = 0;
    while(iss >> hex_or_decimal >> input) {
        std::cout << std::dec << input 
                  << " 0x" << std::hex << input << std::endl;
    }
    if(iss.fail()) {
       std::cerr << "Invalid input!" << std::endl;
    }
}

输出是

5 0x5
66 0x42
33 0x21
44 0x2c
Invalid input!

查看实例 here请。


注意:
5xfffff 值在 5 被流正确使用后被标记为无效(参见演示 here )


您可以使用 std::istream 标准功能和标志轻松地使其适应您的需求(例如,在无效输入时抛出异常)。

例如:

抛出和捕获异常

int main()
{
    std::istringstream iss { "5 0x42 33 044 00x777 0x55" };
    iss.exceptions(std::ifstream::failbit); // <<<

    try {
        short input = 0;
        while(iss >> hex_or_decimal >> input) {
            std::cout << std::dec << input 
                      << " 0x" << std::hex << input << std::endl;
        }
    }
    catch (const std::ios_base::failure &fail) { <<<
        std::cerr << "Invalid input!" << std::endl;
    }
}

关于c++ - Char* 输入检查它是十六进制还是十进制,并使用适当的错误处理和报告将其解析为无符号短整型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45533444/

相关文章:

c++ - 循环写入文件时遇到问题

c++ - std::bitset <64>是否在uint64_t的32位计算机上工作?

c++ - 如何处理状态转换并将 "if"语句替换为多态类型?

c++ - 什么时候发布 IMFSample 及其数据是安全的?

c++ - 将 strcpy 与 std::vector 一起使用

c++ - 虚函数重定义隐藏了另一个基类的同名重载函数

c++ - int 类型的构造函数

c++ - glDrawElements 已停止工作

c++ - Quicksort 正确实现,但有一些额外的比较

c++ - 让 Friend 成为模板类的构造函数