C++ 处理将字符串转换为整数的函数中的错误

C++ 处理将字符串转换为整数的函数中的错误,c++,C++,我只是想实现我自己的函数,用于字符串到int的转换。 我的职能如下: int func(string s) { if error return -1; else do something and return the value } 我只是有一个疑问,如果我的字符串是s=“-1”,那么我将如何区分为错误返回的“-1”和为字符串的正确转换返回的“-1”。谢谢你的帮助。我希望我的问题足够清楚。您的功能设计可以是: int func(string s, int *out) {

我只是想实现我自己的函数,用于字符串到
int
的转换。 我的职能如下:

int func(string s)
{
    if error return -1;
    else do something and return the value 
}

我只是有一个疑问,如果我的字符串是s=“-1”,那么我将如何区分为错误返回的“-1”和为字符串的正确转换返回的“-1”。谢谢你的帮助。我希望我的问题足够清楚。

您的功能设计可以是:

int func(string s, int *out)
{
    if error return -1;
    else {
        do something and set *out to the value;
        return 1;
    }
}

如注释所述,如果返回值要同时表示有效值和错误,则会重载
-1
。由于没有可以同时表示两者的整数值,因此需要额外的返回值。在这种设计中,函数的返回值表示成功或失败,
*out
参数返回结果。当然,您可以交换这两个参数(参数接收成功或失败,返回值为该值)。

您有几个不同的权衡选项

1。异常。在错误情况下引发异常。异常不需要在调用站点直接捕获,但可以在调用层次结构中进一步处理,在调用层次结构中,您有更多的上下文来处理错误。我甚至想说,如果您总是将函数调用包装在try-catch块中,您可能会误解异常的优点

int func(const std::string& s);
2。可选返回值。,在C++17中提供(或之前作为
boost::Optional
或技术规范(TS))提供)。这是为了明确说明在调用函数时必须考虑不返回值的有效情况

std::optional<int> func(const std::string& s);
4。检查和输出参数习惯用法。具有接受输出参数的函数。如果生成值,则将结果写入该参数并返回true,否则返回false

bool func(int& out);
这允许如下调用。缺点是不能直接初始化对象(因此不能使用
const
-限定的、默认构造的或不可分配的对象)

5。断言。这是许多人忽视的一点,尤其是那些来自Java等语言的人,在Java中,大多数错误都是通过异常进行分类处理的。如果返回无效值的唯一情况是函数的错误调用——即程序中的逻辑错误(更不用说bug了)——那么通常更可取的做法是尽快将其识别出来。调试器将立即停止失败的断言,而您的生产性代码将完全优化它们

int func(const std::string& s);

断言对于检查函数的前置或后置条件非常有用。它们对于在运行时无法有效处理的错误发出信号特别有用。如果他们失败了,这意味着你的程序逻辑被破坏了,因为这本来就不应该发生,所以没有好办法从这种情况中恢复过来。由于您的应用程序处于意外状态,进一步执行代码可能会使情况变得更糟。

您可以抛出一个异常

int func (string const & input)
{
  if (error)
    throw std::runtime_error("stuff happenend")
  else
    return value;
}

我将使用
boost::lexical_cast
并让调用方处理
错误的强制转换异常

// will throw bad_lexical_cast  if any issue.
int convert(const std::string& num) {
    return boost::lexical_cast<int>(num);
}


int main()
{
    try {
        std::cout << convert("1") << "\n";
        std::cout << convert("-1") << "\n";
        std::cout << convert("abc") << "\n";
    } catch (const boost::bad_lexical_cast& blc) {
        std::cout << blc.what() << "\n";
    }

 return 0;
}
//如果出现任何问题,将抛出错误的\u词法\u cast。
int转换(const std::string&num){
返回boost::词法转换(num);
}
int main()
{
试一试{

std::您不能。您的函数设计有缺陷。如果字符串不表示数字,为什么不直接抛出异常?这说明了错误处理总是很棘手的原因。在一般情况下,任何函数都有两个输出:(1)成功/失败值,和(2)返回值。尝试将两者结合起来总是很有诱惑力的,因为单独返回这两个东西是一件麻烦事,从来没有那么方便。但是如果你将两者结合起来(就像你在这里尝试的那样),如果正常返回值集与成功/错误之间的区别不明显,则最终会出现无法解决的歧义。下面是一个相关的谜语:“为什么Unix系统不能在1969年12月31日星期三午夜前运行?”回答:“因为在23:59:59,
time()
系统调用将返回-1,这看起来像是一个错误。”选择C或C++,因为这改变了实现。一个非常常见的约定是返回<代码> 0代码/>成功,非零错误。这是与普通的零=假,非零=布尔代数的约定相反,但是在非零失效代码中编码更多信息是有用的。@ Keith Thompson,另一种选择是“沉默失败”。例如
atoi
,如果它不能转换值,也会返回
0
。是的,这是一个替代方案,也被称为坏主意。为什么不使用?@juanchopanza masochim。它是新的黑色。@juanchopanza因为词法转换更灵活。它还为您提供了跨许多不同类型的统一接口s、 转换类型?所需的全部是
string
int
。如果只需要一把螺丝刀,为什么还要有工具箱呢?我会根据我的所有需要使用相同大小的螺丝刀。这包括
string
int
,这是被要求的。你问了为什么?你有答案,包括来自帖子的原件。还有如果你没有C++11编译器,那怎么办?
boost
int func(const std::string& s);
int func (string const & input)
{
  if (error)
    throw std::runtime_error("stuff happenend")
  else
    return value;
}
// will throw bad_lexical_cast  if any issue.
int convert(const std::string& num) {
    return boost::lexical_cast<int>(num);
}


int main()
{
    try {
        std::cout << convert("1") << "\n";
        std::cout << convert("-1") << "\n";
        std::cout << convert("abc") << "\n";
    } catch (const boost::bad_lexical_cast& blc) {
        std::cout << blc.what() << "\n";
    }

 return 0;
}