【问题标题】:How to use goto across multiple functions如何跨多个函数使用 goto
【发布时间】:2018-05-20 04:05:04
【问题描述】:

我试图在不使用exit() 的情况下退出程序。我想出了一个非常复杂和肮脏的解决方案(我是初学者)。 我想使用if 语句,如果是真的,那么我想使用goto 进入主函数然后return 3; 并结束程序。

这是一段代码:

    FILE *filepointer;

      char * line = NULL;
      size_t len = 0;
      size_t read;
      int linecount = 0;
      filepointer = fopen(filename, "r");
      if (filepointer == NULL)
        {
          printf("[ERR] Could not read file %s.\n",filename );
          goto FILE_ERROR;
        }
    ...
    int main(){
    ...
    FILE_ERROR: return 3;

}

但这不起作用,因为我无法在函数之间跳转,因为我得到 undeclared Label 作为错误。有什么办法可以从我的程序中排除 exit() 并仍然结束它返回某个值。如果有更好的解决方案,请告诉我

【问题讨论】:

  • 建议:重构你的逻辑,然后是代码。 goto 被认为是邪恶的
  • 不要...只是不要
  • 答案很明确,always avoid to use goto and jumps in code,但如果你真的想看看它是如何工作的和可以使用的,请看stackoverflow.com/questions/2891766/…
  • 想退出的时候直接返回main,让main返回即可。如果您无法构建您的程序来执行此操作,那么您可以使用setjmp/longjmp。不过我真的不明白这一点。

标签: c


【解决方案1】:

goto不能用于跳转不同功能;它只能在同一个函数中使用。要在函数之间跳转,您可以查看 setjmp()longjmp() 函数。

话虽如此,既然您声称自己是初学者,我不相信您真的需要使用上述任何一种。您可以简单地修改您的函数以返回“错误”值。并在main() 中检查其值并从main() 返回错误值。

【讨论】:

  • 在您了解如何正确构建代码之前,请不要查看setjmp()longjmp()
  • 我并不完全是 carg-cult 编程的追随者。这就是为什么我提到它可以完成。但这并不是你真正需要的 OP。
  • @cmaster:“从不”是个糟糕的建议。 setjmplongjmp 有合法用途,即使存在许多相关危害。例如,与gets 不同,它远不如longjmp 安全。
  • 通过仔细编程,SIGSEGV 可以从用户空间本身恢复,而不涉及“不可控的方式”。简而言之,即使在用户空间程序中,setjmp/longjmp 也有真正的用例。
  • @cmaster:SIGSEGV 实际上并不是未定义的行为。听起来你对这个主题有非常强烈的意见,但老实说,我对其中一些回复感到有点受伤,比如“如果你这样做,我会把你从我的项目中删除”或“代码严重损坏”。这是一个适当的评论吗?听起来这里也有大量的假设,比如关于半成品的物体。如果您在池中分配这些对象,这并不罕见,您可以在longjmp 之后简单地释放池。编码风格有很多种,你不喜欢的编码风格并没有“错”。
【解决方案2】:

这个问题的唯一好答案是:不要这样做gotos 以这种方式使用会使您的代码很难推理。

重构您的代码,以便您拥有清晰的结构和调用层次结构。使用返回值在整个调用堆栈中传播成功/失败。

【讨论】:

    【解决方案3】:

    按照设计,goto 不能从一个函数跳转到另一个函数。它只能用于在给定函数内跳转。

    有很多方法可以在函数之间跳转,但是这样做不仅设计很差,而且很危险,因为很容易让你的程序处于无效状态。

    处理此问题的正确方法是让您的函数返回一个特定值(或一组值)以指示错误。然后调用函数将检查其中一个错误值并采取相应措施。

    例如:

    int readFile(char *filename)
    {
      FILE *filepointer;
    
      char * line = NULL;
      size_t len = 0;
      size_t read;
      int linecount = 0;
      filepointer = fopen(filename, "r");
      if (filepointer == NULL)
        {
          // add strerror(error) to the error message to know why fopen failed
          printf("[ERR] Could not read file %s: %s.\n",filename, strerror(errno) );
          // error completion
          return 0;
        }
      ...
      // successful completion
      return 1;
    }
    
    int main(){
       ...
       if (readFile("myfile") == 0) {
           return 3;
       }
       ...
    }
    

    【讨论】:

      【解决方案4】:

      如果您想使用 go-to 并坚持这样做,我猜您可以尝试扩展您的第一个功能,使其包含/封装第二个功能,并完全摆脱第二个功能,这样您就可以在这个更大的函数中执行 go tos 和子例程。

      你可以试试这个选项吗? (如果你在使用 Goto's 时已经死了,)?

      我会试一试。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-10-25
        • 1970-01-01
        • 2021-03-22
        • 2019-10-24
        相关资源
        最近更新 更多