【问题标题】:Why does this case statement need an "if else" and not just an "if"?为什么这个case语句需要一个“if else”而不仅仅是一个“if”?
【发布时间】:2020-07-05 07:55:53
【问题描述】:

所以我是 C++ 新手,我正在学习一个 pdf 教程,该教程让我开始学习基本知识。我正在编写一个简单的案例程序,我遇到了一些奇怪的事情。

#include "pch.h"
#include <iostream>
#include <string>

using namespace std;

enum string_feeling {
    eGood,
    eBad,
    eOk,
};

string_feeling hashit(string const& feeling) {
    if (feeling == "Good" || feeling == "good" || feeling == "GOOD") {
    return eGood;
    }
    if (feeling == "Bad" || feeling == "bad" || feeling == "BAD") {
        return eBad;
    }
    if (feeling == "Ok" || feeling == "ok" || feeling == "OK") {
        return eOk;
    } 
    else cout << "";
}

int main() {
    string username;
    cout << "Hello! Please enter your first name here: \n";
    cin >> username;
    cout << "Hello, " << username << "!\n";
    cout << "How are you today? ";
    string feeling;
    cin >> feeling;
    cout << endl;

    switch (hashit(feeling)) {
    case eGood:
        cout << "That's great!";
        break;
    case eBad:
        cout << "I hope you are happy soon!";
        break;
    case eOk:
        cout << "That's good.";
        break;
    default:
        cout << "Ok.";
    }
}

每当我在“if (feeling == ok)”之后没有“else”时,将永远不会调用默认案例,如果我输入随机的内容,它会给我 eGood 案例中的文本。我想知道为什么会发生这种情况,因为我正在学习 C++,所以我不想在我把 else 语句放在那里之后不知道为什么它会起作用。所以,如果有人可以向我解释这一点,那就太好了!抱歉我的语法不好。

【问题讨论】:

  • 发布有问题的代码,而不是一些您似乎说有效但如果我们根据单独给出的说明编辑它会出现问题的代码。并删除不需要演示问题的代码。
  • 无论有没有else,你的程序都有未定义的行为。您需要在每个可达路径中使用returnthrow
  • 如果您不想在string_feeling 中添加新案例,您可以将hashit 更改为例如bool hashit(const string &amp; feeling, string_feeling &amp; v) 以在不设置v 时返回false feeling 有效,否则设置 v 并返回 true
  • 注意此代码样式的效率。在这种情况下,这可能并不重要,但有时应该考虑一下。您在每个 if() 语句中进行三个比较,复杂度为 O(length),最坏的情况下,您的函数为 O(9*length)。首先将字符串大写(可以是“gOOd”吗?),最坏的情况是 O(4*length),或者对整个函数进行最坏情况下的 O(length) 模式比较。

标签: c++ switch-statement


【解决方案1】:

在启用警告的情况下编译您的程序,例如g++ -Wall -Wextra -Werror,它甚至无法编译,因为string_feeling hashit(string const&amp; feeling) 并非在所有情况下都返回值。

在不启用警告的情况下编译代码无疑是浪费时间的方式。

【讨论】:

    【解决方案2】:

    hashit函数中的三个if语句中没有一个条件为真时,函数中不执行return语句并调用未定义的行为

    (引用自N33376.6.3 的return语句)

    从函数的末尾流出相当于没有值的返回;这会导致返回值的函数出现未定义的行为。

    为避免这种情况,您应该在enum 中再添加一种

    enum string_feeling {
        eGood,
        eBad,
        eOk,
        eOther // add this
    };
    

    不满足条件时返回。

    string_feeling hashit(string const& feeling) {
        if (feeling == "Good" || feeling == "good" || feeling == "GOOD") {
        return eGood;
        }
        if (feeling == "Bad" || feeling == "bad" || feeling == "BAD") {
            return eBad;
        }
        if (feeling == "Ok" || feeling == "ok" || feeling == "OK") {
            return eOk;
        } 
        else cout << "";
        return eOther; // add this
    }
    

    【讨论】:

      【解决方案3】:

      你总是必须返回一个值,否则行为是不确定的

      如果您无法修改枚举以添加未知感觉的案例,您可以修改 hashit 以在 feeling 有效且在这种情况下设置输出的情况下返回 true参数与相应的枚举值,否则返回false而不设置输出参数:

      #include <iostream>
      #include <string>
      
      using namespace std;
      
      enum string_feeling {
          eGood,
          eBad,
          eOk,
      };
      
      bool hashit(string const& feeling, string_feeling & r) {
        if (feeling == "Good" || feeling == "good" || feeling == "GOOD") {
          r = eGood;
        }
        else if (feeling == "Bad" || feeling == "bad" || feeling == "BAD") {
          r = eBad;
        }
        else if (feeling == "Ok" || feeling == "ok" || feeling == "OK") {
          r = eOk;
        } 
        else
          return false;
        
        return true;
      }
      
      int main() {
          string username;
          cout << "Hello! Please enter your first name here: \n";
          cin >> username;
          cout << "Hello, " << username << "!\n";
          cout << "How are you today? ";
          string feeling;
          cin >> feeling;
          cout << endl;
          
          string_feeling f;
          
          if (! hashit(feeling, f))
            cout << "I do not understand how you are" << endl;
          else {
            switch (f) {
            case eGood:
              cout << "That's great!" << endl;
              break;
            case eBad:
              cout << "I hope you are happy soon!" << endl;
              break;
            case eOk:
              cout << "That's good." << endl;
              break;
            }
          }
      }
      

      编译和执行:

      pi@raspberrypi:/tmp $ g++ -Wall c.cc
      pi@raspberrypi:/tmp $ ./a.out
      Hello! Please enter your first name here: 
      bruno
      Hello, bruno!
      How are you today? good
      
      That's great!
      pi@raspberrypi:/tmp $ ./a.out
      Hello! Please enter your first name here: 
      bruno
      Hello, bruno!
      How are you today? aze
      
      I do not understand how you are
      pi@raspberrypi:/tmp $ 
      

      除此之外:

      • 给你的枚举命名string_feeling不是很清楚,无论输入的感觉是一个字符串,最好只是命名它Feeling

      • hashit 中通过值获取字符串以将其更改为小写然后将其与 "good"、"bad" 和 "ok" 进行比较或使用 strcasecmp在其.c_str() 上,还允许管理“gOoD”等

      【讨论】:

        【解决方案4】:

        如果没有if条件满足,hashit

        else cout << "";
        

        由于您没有显式编写return 语句,因此该函数返回默认值0,等于eGood

        但是,默认返回值并不总是0。这是undefined behaviour

        如果您使用不同的编译器运行此代码,may 会得到不同的结果。

        【讨论】:

        • "函数返回默认值0" ... "但是,默认返回值并不总是0"这有点矛盾。
        猜你喜欢
        • 2012-09-10
        • 1970-01-01
        • 1970-01-01
        • 2017-08-12
        • 1970-01-01
        • 2022-01-06
        • 1970-01-01
        • 2018-10-01
        • 1970-01-01
        相关资源
        最近更新 更多