如何在else-if中使用(或不使用?)goto

How to use (or not to use?) goto in a else - if

本文关键字:goto else-if      更新时间:2023-10-16

每次我将ifgoto一起使用以绕过进程并直接转到退出时,它都不会通过命令绕过某些内容,而是一直到最后。这里有一个例子:

#include <iostream>
#include <string>
using namespace std;
int main()
{
  string k;
  cout <<"What would you like to do ?n"<<"Continue or Exitn";
  cin >> k;
  if (k = "exit","Exit") goto s;
  else (k = "Continue","continue");
  cout << "You continued...";
  s:
  return 0
}

问题是,即使您键入"退出"或"继续",它也只是简单地关闭。有人能看到问题吗?另外,我该如何避免使用goto?

第一个if总是true,因为在赋值之后,逗号运算符的RHS上的测试将是true

您的简单程序不能保证使用goto。不过,我更喜欢处理这样的任务:函数表。

我完成了一个例子。我们从一个简单的回调类开始。回调接口附带了一个默认实现,该实现抱怨输入。

struct Callback {
    virtual ~Callback () {}
    virtual void operator () (std::string k) const {
        std::cout << "Unrecognized input: " << k << 'n';
    }
};

这部分定义了函数表数据结构,声明了一个API来初始化一个,以及调用回调的驱动程序代码:

typedef std::map<std::string, const Callback *> CallbackMap;
static void init_table (CallbackMap &cbmap);
static void invoke_table (const CallbackMap &cbmap, std::string k)
{
    CallbackMap::const_iterator i = cbmap.find(k);
    if (i != cbmap.end()) (*i->second)(k);
    else Callback()(k);
}
int main ()
{
    CallbackMap cbmap;
    std::string k;
    init_table(cbmap);
    std::cout << "What would you like to do?nContinue or Exitn";
    std::cin >> k;
    invoke_table(cbmap, k);
    return 0;
}

单独的回调实现是通过以下帮助宏实现的:

#define CONST_SINGLETON(Name) 
    public: 
        static const Name & instance () { 
            static const Name one; 
            return one; 
        } 
    private: 
        Name () {} 
        Name (const Name &); 
        void operator = (const Name &)

每个回调实现都执行示例程序中介绍的简单操作:

class ExitCallback : public Callback {
    void operator () (std::string) const { std::exit(0); }
    CONST_SINGLETON(ExitCallback);
};
class ContinueCallback : public Callback {
    void operator () (std::string) const {
        std::cout << "You continued...n";
    }
    CONST_SINGLETON(ContinueCallback);
};

初始化例程用对应于适当回调的字符串填充函数表:

static void init_table (CallbackMap &cbmap)
{
    static struct { const char *s; const Callback *cb; } init[] = {
        { "exit", &ExitCallback::instance() },
        { "Exit", &ExitCallback::instance() },
        { "continue", &ContinueCallback::instance() },
        { "Continue", &ContinueCallback::instance() },
        { 0, 0 }
    };
    for (int i = 0; init[i].s; ++i) {
        cbmap[init[i].s] = init[i].cb;
    }
};

1(这里不要使用goto:在现代C++代码中使用它几乎从来都不合适。

2(使用==比较字符串(=用于string分配(

 if (k == "exit","Exit") 
      ^^^^
    //Here
 else (k == "Continue","continue")
      ^^^^
   // And here

3(,不是"and"运算符,请使用:

if (k == "exit" || k == "Exit")

4(如果有无用的大括号,请缩进代码以正确查看真正需要的块。

您需要学习如何使用调试器,还需要了解有关C++的更多信息

if (k = "exit","Exit") goto s;   //VERY WRONG

并不意味着你想要什么:

  • CCD_ 13的CCD_
  • 逗号被理解为逗号运算符

至少编码if (k == "exit" || k == "Exit"),尽可能避免使用goto

此外,启用所有警告(和调试信息(。也许你的编译器可以警告你。

我建议您阅读一些来自自由软件的源代码(例如,在sourceforge或其他地方(。这将教会你很多。

适当的缩进和样式将帮助您看到您的一些努力。

首先,我强烈建议将字符串转换为小写或大写。这就不需要检查字符串中大写字母和小写字母的所有排列:

  cout << "What would you like to do ?n"
       << "Continue or Exitn";
  cin >> k;
  std::transform(k.begin(), k.end(), k.begin(), tolower);

要退出main函数,return需要一个值,例如exit_SUCCESS或exit_FAILURE。

  if (k == "exit")
  {
    return EXIT_SUCCESS;
  } // No goto's necessary
  // The code continues here.

记住"="是赋值,"=="是比较。

没有必要比较"continue",因为如果响应不是"exit",它会"自动"进行比较。

使用goto
不建议在此实例中使用goto
如果你真的必须使用goto,你将需要不止一个标签。

int main(void)
{
  string k;
top_of_loop:  // Label for your goto
  cout << "What would you like to do ?n"
       <<"Continue or Exitn";
  cin >> k;
  std::transform(k.begin(), k.end(), k.begin(), tolower);
  if (k == "exit")
  {
    goto end_of_program;
  }
  // Execution continues here automatically.
  else
  {
    if (k == "continue")
    {
       goto program_continuation;
    }
    else
    {
       cout << "Unknown response, try again.n";
       goto top_of_loop;
    }
  }
program_continuation:
  cout << "You continued...";
  goto top_of_loop;
end_of_program:
  return 0
}

作为while循环

  cout << "What would you like to do ?n"
       <<"Continue or Exitn";
  cin >> k;
  std::transform(k.begin(), k.end(), k.begin(), tolower);
  while (k != "exit")
  {
    // Your program stuff here.
    cout << "Program continued.n";
    // Prompt the User again.
    cout << "n"
         << "What would you like to do ?n"
         << "Continue or Exitn";
    cin >> k;
    std::transform(k.begin(), k.end(), k.begin(), tolower);
  }
  return 0; // Exit main().

您的代码反映了您的意图,但这些意图不是用C++编写的。它们是一个有效的C++程序——当然是编译的——但你的意思并不是你所写的。

它在这里,固定做你想做的事。

int main()
{
  string k;
  cout << "What would you like to do ?nContinue or Exit" << endl;
  cin >> k;
  if (! (k == "exit" || k == "Exit")) {
    if (k == "Continue" || k == "continue") {
      cout << "You continued...";
    }
  }
  return 0
}

你也可以做:

int main()
{
  string k;
  cout << "What would you like to do ?nContinue or Exit" << endl;
  cin >> k;
  if (k == "exit" or k == "Exit") return 0;
  if (k == "Continue" or k == "continue") {
    cout << "You continued...";
  }
  return 0
}

变化如下:

  1. 要检查多个条件中的一个是否为真,请使用逻辑运算符加入测试。运算符被写成||,或者简单地说,写成or

  2. 比较运算符为==。您使用的运算符=是一个赋值运算符。它执行赋值,其结果值就是赋值。

  3. 逗号运算符用于分隔要计算的多个表达式。其结果值是最后一个表达式,即使所有表达式都已求值。例如,(1, 2, 3)的值为3