C/C++/Java goto语句的使用

44 篇文章 2 订阅
20 篇文章 6 订阅

goto语句:http://baike.baidu.com/link?url=2SPNcNbC4S-CP08jQV5ei2b9zqpXdfHrFRqstF5TCsVTnZeUcrpQ3THe0uvWkF95eyej52gBijSAwwXR_6ZeIq#6

《C Primer Plus》(第6版)中文版 7.8章 goto语句

《JAVA核心技术 卷I:基础知识》3.8.6章 中断控制流程语句


##############################################################


最近一段时间,经常需要在同一个函数中编写多个重复代码,出现问题后就需要一个个找出来进行修改,没有效率。在一个例子里发现一段goto语句的使用,发现能够高效的处理重复代码,之前对于goto语句并没有在意,觉得应该不用任何goto语句,但是现在看来,goto语句还是很有效的


知乎上有一个关于goto语句使用的讨论:
既然建议尽量避免使用goto语句为何C++还要支持goto呢?:https://www.zhihu.com/question/21981058


################################################################


首先介绍C/C++版本的goto语句


goto语句也称为无条件转移语句,最早应该出现在BASIC和FORTRAN中,C/C++也能够使用goto语句,但C/C++与前面两种语言不同的是,goto语句并不是必需的,没有goto语句程序也能运行良好。


goto语句的一般格式:

goto 标签名;

其中标签名遵循变量命名规则


介绍一下变量命名规则

1).变量名只能是字母(A-Z,a-z)和数字(0-9)或者下划线(_)组成;

2).第一个字母必须是字母或者下划线开头;

3).不能使用C/C++关键字来命名变量,以免冲突;

4).变量名区分大小写。

参考:C/C++变量命名规则,个人习惯总结 - http://blog.sina.com.cn/s/blog_8a7012cf01017h9p.html


同时程序必须包含另一条语句,格式为:

标签名:
即标签名后紧跟一个冒号


一个简单的C程序:

#include <stdio.h>

int main(int argc, char* argv[]) {

    if (getchar() == 'a') {
        goto Hi;
    } else {
        goto Hello;
    }

Hi: printf("Hi World\n");
    return 0;

Hello: printf("Hello World\n");
    return 0;
}

当你输入字符a时,输出Hi World;否则,输出Hello World






原则上,根本不用在C/C++程序中使用goto语句。但在以下场景中,使用goto语句可以高效的处理代码


1.从多重循环中直接跳出

当需要结束嵌套循环时,break语句只能跳出当前循环,使用goto语句可以直接跳出所有循环,这样就不需要在嵌套循环中再进行if判断了

例子:从一个二重循环中退出

使用break

#include <stdio.h>

int main(int argc, char* argv[]) {
    bool flag  = false; //设置标志位,用于判断是否退出
    int sum = 0;

    // 累加i*j的值,大于10就结束
    for (int i=0; i<10; i++) {
        for (int j=0; j<10; j++) {
            sum += i*j;
            if (sum > 10) {
                flag = true;
                break;
            }
        }

        if (flag) {
            break;
        }
    }
    printf("sum = %d\n", sum);

    return 0;
}

使用goto

#include <stdio.h>

int main(int argc, char* argv[]) {
    int sum = 0;

    // 累加i*j的值,大于10就结束
    for (int i=0; i<10; i++) {
        for (int j=0; j<10; j++) {
            sum += i*j;
            if (sum > 10) {
                goto exit;
            }
        }
    }
    exit:
    printf("sum = %d\n", sum);

    return 0;
}

很明显,goto语句能够方便的完成退出


2.为函数统一设置出口

这个就是我遇到的问题,不论退出函数时是好的结果还是坏的结果,都有可能会有一些必须执行的操作,比如释放资源,重设置标识符等。可能一个函数中会有多个出口,这样对于程序的可读性以及后续维护很不方便,使用goto可以很好的解决这个问题

不用goto

#include <iostream>
#include <string.h>
using namespace std;

string func(const char* arg1, const char* arg2);

int main(int argc, char* argv[]) {
    string res;
    res = func("arg1", "arg2");

    cout <<"res = " <<res <<endl;

    return 0;
}

string func(const char* arg1, const char* arg2) {
    char* p1 = NULL;
    p1 = (char*)malloc(sizeof(char) * strlen(arg1));
    memset(p1, 0, strlen(arg1));
    memcpy(p1, arg1, strlen(arg1));

    char* p2 = NULL;
    p2 =(char*)malloc(sizeof(char) * strlen(arg2));
    memset(p2, 0, strlen(arg2));
    memcpy(p2, arg2, strlen(arg2));

    if (strcmp("arg1", p1) == 0) {
        cout <<"arg1 ok" <<endl;

        delete[] p1;
        delete[] p2;
        return arg1;
    }

    if (strcmp("arg2", p2) == 0) {
        cout <<"arg2 ok" <<endl;

        delete[] p1;
        delete[] p2;
        return arg2;
    }

    delete[] p1;
    delete[] p2;
    return "error";
}


使用goto

#include <iostream>
#include <string.h>
using namespace std;

string func(const char* arg1, const char* arg2);

int main(int argc, char* argv[]) {
    string res;
    res = func("arg1", "arg2");

    cout <<"res = " <<res <<endl;

    return 0;
}

string func(const char* arg1, const char* arg2) {
    char* p1 = NULL;
    p1 = (char*)malloc(sizeof(char) * strlen(arg1));
    memset(p1, 0, strlen(arg1));
    memcpy(p1, arg1, strlen(arg1));

    char* p2 = NULL;
    p2 =(char*)malloc(sizeof(char) * strlen(arg2));
    memset(p2, 0, strlen(arg2));
    memcpy(p2, arg2, strlen(arg2));

    string res = "error";

    if (strcmp("arg1", p1) == 0) {
        cout <<"arg1 ok" <<endl;

        res = arg1;
        goto exit;
    }

    if (strcmp("arg2", p2) == 0) {
        cout <<"arg2 ok" <<endl;

        res = arg2;
        goto exit;
    }

    exit:
    delete[] p1;
    delete[] p2;
    return res;
}

将同一个函数中的所有出口统一到一起,可读性提高,同时方便今后修改


#############################################################


Java中将goto作为关键字,但并没有给它赋予任何功能,但在Java中也有可替代goto功能的语句,就是带标签的break和带标签的continue语句

参考:Alternative to a goto statement in Java - http://stackoverflow.com/questions/2430782/alternative-to-a-goto-statement-in-java/2430829#2430829


带标签的break语句

语法:

break 标签名;


同时程序中还有另外一条语句

标签名:


注意:第二条语句必须放在希望跳出的语句块之前,并且必须紧跟一个分号,同时语句块中必须包含带标签的break语句,所以该语句仅能作为跳出语句块的操作。语句块可以使多重循环,也可以是if语句,for语句或者{}块语句。


一个简单的例子:输入数字,小于等于0则退出

package com.zj;

import java.util.Scanner;

public class Main {

    public static void main(String[] args) {
	// write your code here
        Scanner in = new Scanner(System.in);

        int n = 0;
        read_data:
        while (true) {
            while (true) {
                System.out.print("Enter a number >= 0:");
                n = in.nextInt();

                if (n <= 0)
                    break read_data;
            }
        }

        if (n < 0) {
            System.out.println("n < 0");
        } else if (n == 0) {
            System.out.println("n == 0");
        }
    }
}


还有一个continue加标签的用法,用于退出当前循环,继续上层循环,想要了解的可以查找相关资料

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值