如何重新设计此代码以避免转到

时间:2016-05-17 22:44:30

标签: c

我有一个程序需要用户输入4个文件(无需订单)。然后我对文件做了不同的事情。现在我使用goto语句,我想替换goto语句,但不知道如何。我想知道这些是否有问题?这是我使用goto的代码:

int main(int argc, char **argv){
    char *tmp;
    int i, flag1=0, flag2=0, flag3=0, flag4=0;
    FILE *fp1;
    FILE *fp2;
    FILE *fp3;
    FILE *fp4;

    char file1[64];
    char file2[64];
    char file3[64];
    char file4[64];

    for( i=1; i<argc; i++){
        tmp = argv[i];
        if ( strcmp(tmp+8,"F1") == 0 ){
            sprintf(file1,argv[i]);
            flag1=1;
        }
        else if (strcmp(tmp+8,"F2") == 0 ){
            sprintf(file2,argv[i]);
            flag2=1;
        }
        else if (strcmp(tmp+8,"F3") == 0 ){
            sprintf(file3,argv[i]);
            flag3=1;
        }
        else if (strcmp(tmp+8,"F4") == 0 ){
            sprintf(file4,argv[i]);
            flag4=1;
        }
    }

    if( !(flag1 && flag2 && flag3 && flag4) ){
        printf("Must input four files!!\n");
        exit(-1);
    }

    if (access(file1,0) != 0){
        GOTO L1;
    }
    if((fp1 = fopen(file1,"r")) == NULL){
        exit(-1);
    }
    do_file_1(fp1);
    fclose(fp1);

    L1: if (access(file2,0) != 0 ){
        goto L2;
    }
    if((fp2 = fopen(file2,"r")) == NULL){
        exit(-1);
    }
    do_file_2(fp2);
    fclose(fp2);


    L2: if (access(file3,0) != 0)
    {
       goto L3;
    }
    if((fp3=fopen(file3,"r"))==NULL)
    {
      exit(-1);
    }
    do_file_3(fp3);
    fclose(fp3);



    L3: if (access(file4,0) !=0)
    {
      goto end;
    }
    if((fp4=fopen(file4,"r"))==NULL)
    {
      exit(-1);
    }
    do_file_4(fp4);
    fclose(fp4);


    end:
        return 0;
}

6 个答案:

答案 0 :(得分:2)

你有&#34;如果这个条件为真,请跳过一些代码&#34;。这是您ruby 2.2.5p319 (2016-04-26 revision 54774) [x86_64-darwin14] ============================================================ Running tests for obj = 1000000 (Fixnum) user system total real obj: 0.970000 0.000000 0.970000 ( 0.987204) nil_obj: 0.980000 0.010000 0.990000 ( 0.980796) obj.nil?: 1.250000 0.000000 1.250000 ( 1.268564) nil_obj.nil?: 1.280000 0.000000 1.280000 ( 1.287800) !obj: 1.050000 0.000000 1.050000 ( 1.064061) !nil_obj: 1.070000 0.000000 1.070000 ( 1.170393) !!obj: 1.110000 0.000000 1.110000 ( 1.122204) !!nil_obj: 1.120000 0.000000 1.120000 ( 1.147679) obj == nil: 2.110000 0.000000 2.110000 ( 2.137807) nil_obj == nil: 1.150000 0.000000 1.150000 ( 1.158301) obj != nil: 2.980000 0.010000 2.990000 ( 3.041131) nil_obj != nil: 1.170000 0.000000 1.170000 ( 1.203015) ============================================================ Running tests for obj = 100000.0 (Float) user system total real obj: 0.940000 0.000000 0.940000 ( 0.947136) nil_obj: 0.950000 0.000000 0.950000 ( 0.986488) obj.nil?: 1.260000 0.000000 1.260000 ( 1.264953) nil_obj.nil?: 1.280000 0.000000 1.280000 ( 1.306817) !obj: 1.050000 0.000000 1.050000 ( 1.058924) !nil_obj: 1.070000 0.000000 1.070000 ( 1.096747) !!obj: 1.100000 0.000000 1.100000 ( 1.105708) !!nil_obj: 1.120000 0.010000 1.130000 ( 1.132248) obj == nil: 2.140000 0.000000 2.140000 ( 2.159595) nil_obj == nil: 1.130000 0.000000 1.130000 ( 1.151257) obj != nil: 3.010000 0.000000 3.010000 ( 3.042263) nil_obj != nil: 1.170000 0.000000 1.170000 ( 1.189145) ============================================================ Running tests for obj = false (FalseClass) user system total real obj: 0.930000 0.000000 0.930000 ( 0.933712) nil_obj: 0.950000 0.000000 0.950000 ( 0.973776) obj.nil?: 1.250000 0.000000 1.250000 ( 1.340943) nil_obj.nil?: 1.270000 0.010000 1.280000 ( 1.282267) !obj: 1.030000 0.000000 1.030000 ( 1.039532) !nil_obj: 1.060000 0.000000 1.060000 ( 1.068765) !!obj: 1.100000 0.000000 1.100000 ( 1.111930) !!nil_obj: 1.110000 0.000000 1.110000 ( 1.115355) obj == nil: 1.110000 0.000000 1.110000 ( 1.121403) nil_obj == nil: 1.100000 0.000000 1.100000 ( 1.114550) obj != nil: 1.190000 0.000000 1.190000 ( 1.207389) nil_obj != nil: 1.140000 0.000000 1.140000 ( 1.181232) ============================================================ Running tests for obj = true (TrueClass) user system total real obj: 0.960000 0.000000 0.960000 ( 0.964583) nil_obj: 0.970000 0.000000 0.970000 ( 0.977366) obj.nil?: 1.260000 0.000000 1.260000 ( 1.265229) nil_obj.nil?: 1.270000 0.010000 1.280000 ( 1.283342) !obj: 1.040000 0.000000 1.040000 ( 1.059689) !nil_obj: 1.070000 0.000000 1.070000 ( 1.068290) !!obj: 1.120000 0.000000 1.120000 ( 1.154803) !!nil_obj: 1.130000 0.000000 1.130000 ( 1.155932) obj == nil: 1.100000 0.000000 1.100000 ( 1.102394) nil_obj == nil: 1.130000 0.000000 1.130000 ( 1.160324) obj != nil: 1.190000 0.000000 1.190000 ( 1.202544) nil_obj != nil: 1.200000 0.000000 1.200000 ( 1.200812) ============================================================ Running tests for obj = string (String) user system total real obj: 0.940000 0.000000 0.940000 ( 0.953357) nil_obj: 0.960000 0.000000 0.960000 ( 0.962029) obj.nil?: 1.290000 0.010000 1.300000 ( 1.306233) nil_obj.nil?: 1.240000 0.000000 1.240000 ( 1.243312) !obj: 1.030000 0.000000 1.030000 ( 1.046630) !nil_obj: 1.060000 0.000000 1.060000 ( 1.123925) !!obj: 1.130000 0.000000 1.130000 ( 1.144168) !!nil_obj: 1.130000 0.000000 1.130000 ( 1.147330) obj == nil: 2.320000 0.000000 2.320000 ( 2.341705) nil_obj == nil: 1.100000 0.000000 1.100000 ( 1.118905) obj != nil: 3.040000 0.010000 3.050000 ( 3.057040) nil_obj != nil: 1.150000 0.000000 1.150000 ( 1.162085) ============================================================ Running tests for obj = (?-mix:\w) (Regexp) user system total real obj: 0.930000 0.000000 0.930000 ( 0.939815) nil_obj: 0.960000 0.000000 0.960000 ( 0.961852) obj.nil?: 1.270000 0.000000 1.270000 ( 1.284321) nil_obj.nil?: 1.260000 0.000000 1.260000 ( 1.275042) !obj: 1.040000 0.000000 1.040000 ( 1.042543) !nil_obj: 1.040000 0.000000 1.040000 ( 1.047280) !!obj: 1.120000 0.000000 1.120000 ( 1.128137) !!nil_obj: 1.130000 0.000000 1.130000 ( 1.138988) obj == nil: 1.520000 0.010000 1.530000 ( 1.529547) nil_obj == nil: 1.110000 0.000000 1.110000 ( 1.125693) obj != nil: 2.210000 0.000000 2.210000 ( 2.226783) nil_obj != nil: 1.170000 0.000000 1.170000 ( 1.169347) 唯一使用的内容。

这正是goto的作用(如果条件为假,则if跳过代码除外)。

您可以替换:

if

使用:

L2: if (access(file3,0) != 0)
{
   goto L3;
}
if((fp3=fopen(file3,"r"))==NULL)
{
  exit(-1);
}
do_file_3(fp3);
fclose(fp3);

L3:

,类似于if (access(file3,0) == 0) { if((fp3=fopen(file3,"r"))==NULL) { exit(-1); } do_file_3(fp3); fclose(fp3); } 的其他用途。

答案 1 :(得分:2)

你分步重构。

您可以使用结束标签语句并将其直接放在调用它的位置。这很容易。

对于其他人,您可以使用else语句:

if (access(file1,0) != 0){
    //GOTO L1;
}else{
  if((fp1 = fopen(file1,"r")) == NULL){
      exit(-1);
  }
  do_file_1(fp1);
  fclose(fp1);
}

L1: if (access(file2,0) != 0 ){
        //goto L2;
    }else{
      if((fp2 = fopen(file2,"r")) == NULL){
          exit(-1);
      }
      do_file_2(fp2);
      fclose(fp2);
    }

    L2: if (access(file3,0) != 0)
    {
       //goto L3;
    }else{
      if((fp3=fopen(file3,"r"))==NULL)
      {
        exit(-1);
      }
      do_file_3(fp3);
      fclose(fp3);
    }



    L3: if (access(file4,0) !=0)
    {
        end:
        return 0;
    }
    if((fp4=fopen(file4,"r"))==NULL)
    {
      exit(-1);
    }
    do_file_4(fp4);
    fclose(fp4);

当然,由于if语句中没有其他语句,if else可以重构为if

我已经解决了更复杂的问题,例如in the past

答案 2 :(得分:1)

也许像下面那样使用带数组的循环的方法会更短,更紧凑。这是一个相当简单的转换,将单独的变量合并到数组中。这确实使用了一组函数指针(参见How do Function pointers in C work)。

do_file_1()do_file_2()等功能只是您正在使用的实际功能的占位符。这会保留您指定的文字文件名(&#34; F1&#34;,&#34; F2&#34;等),但我不确定您为什么需要某些特定的文件名。

我还使用strcpy()函数将文件名参数复制到文件名数组中,而不是使用sprintf()函数。

#include <stdio.h>
#include <stdlib.h>
#include <io.h>
#include <string.h>

void do_file_1 (FILE *fp)
{
    printf ("function do_file_1 called.\n");
}
void do_file_2 (FILE *fp)
{
    printf ("function do_file_2 called.\n");
}
void do_file_3 (FILE *fp)
{
    printf ("function do_file_3 called.\n");
}
void do_file_4 (FILE *fp)
{
    printf ("function do_file_4 called.\n");
}

int main(int argc, char **argv)
{
    int   i;
    char  *fileArray[4] = { "F1", "F2", "F3", "F4"};
    char  fname[4][64] = {0};
    void  (*funcs[4]) (FILE *fp) = {do_file_1, do_file_2, do_file_3, do_file_4};

    for( i = 1; i < argc; i++) {
        int  j;
        for (j = 0; j < 4; j++) {
            if ( strcmp(argv[i], fileArray[j]) == 0 ) {
                strcpy(fname[j],argv[i]);
                break;
            }
        }
    }

    if( !(fname[0][0] && fname[1][0] && fname[2][0] && fname[3][0]) ) {
        printf("Must input four files!!\n");
        exit(-1);
    }

    for (i = 0; i < 4; i++) {
        if (access(fname[i],0) == 0) {
            FILE *fp = fopen(fname[i],"r");
            if (fp != NULL) {
                funcs[i](fp);
                fclose(fp);
            } else {
                break;
            }
        } else {
            break;
        }
    }
    if (i < 4) exit(-1);

    return 0;
}

答案 3 :(得分:0)

明显的变体是改变if这样的陈述:

if (access(file1,0) == 0){
    if((fp1 = fopen(file1,"r")) == NULL) exit(-1);
    do_file_1(fp1);
    fclose(fp1);
}

if (access(file2,0) == 0 ){
    if((fp2 = fopen(file2,"r")) == NULL) exit(-1);
    do_file_2(fp2);
    fclose(fp2);
}

...

答案 4 :(得分:0)

您只是使用goto作为反转if子句的方法。直接反转它们并缩进它们之间的内容:

if (access(file1,0) != 0){
    GOTO L1;
}
if((fp1 = fopen(file1,"r")) == NULL){
    exit(-1);
}
do_file_1(fp1);
fclose(fp1);

L1: ...

变为:

if (access(file1,0) == 0) 
{
    if((fp1 = fopen(file1,"r")) == NULL){
        exit(-1);
    }
    do_file_1(fp1);
    fclose(fp1);
}
//L1: 

答案 5 :(得分:0)

int main(int argc, char **argv){
    char *tmp;
    int i, flag1=0, flag2=0, flag3=0, flag4=0;
    FILE *fp1;
    FILE *fp2;
    FILE *fp3;
    FILE *fp4;

    char file1[64];
    char file2[64];
    char file3[64];
    char file4[64];

    for( i=1; i<argc; i++){
        tmp = argv[i];
        if ( strcmp(tmp,"F1") == 0 ){
            sprintf(file1,argv[i]);
            flag1=1;
        }
        else if (strcmp(tmp,"F2") == 0 ){
            sprintf(file2,argv[i]);
            flag2=1;
        }
        else if (strcmp(tmp,"F3") == 0 ){
            sprintf(file3,argv[i]);
            flag3=1;
        }
        else if (strcmp(tmp,"F4") == 0 ){
            sprintf(file4,argv[i]);
            flag4=1;
        }
    }

    if( !(flag1 && flag2 && flag3 && flag4) ){
        printf("Must input four files!!\n");
        return -1;
    }

    if (access(file1,0) == 0) {

        if((fp1 = fopen(file1,"r")) == NULL){
            return -1;
        }

        do_file_1(fp1);
        fclose(fp1);
    }
    /*L1:*/
    if (access(file2,0) == 0 ) {

        if((fp2 = fopen(file2,"r")) == NULL){
            return -1;
        }

        do_file_2(fp2);
        fclose(fp2);
    }

    /*L2:*/
    if (access(file3,0) == 0) {

       if((fp3=fopen(file3,"r"))==NULL) {
           return -1;
        }

        do_file_3(fp3);
        fclose(fp3);
    }

    /* L3: */
    if (access(file4,0) == 0) {

       if((fp4=fopen(file4,"r"))==NULL) {
           return -1;
       }

       do_file_4(fp4);
       fclose(fp4);
    }

    return 0;
}

但实际上,没有一个程序员不会这样做。