我有一个程序,其中我的代码使用goto语句,但我想以一种不错的方式摆脱它,但是我似乎找不到解决方案。如果goto是最好的方法,请告诉我。以下是代码摘要:

//Counts how many times every word appears in a file
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define NUMWORDS 1000
#define WORDLEN 50

typedef struct
{
  char word[WORDLEN + 1];
  int num;
} Appearance;

int main(int argc, char *argv[]) {
  FILE *readfile;
  Appearance *appearlist[NUMWORDS] = {NULL};
  char word[WORDLEN + 1];
  int i;
  //Get a valid filename and open the file, store pointer into readfile
  ...

  char c;

  while (c != EOF) {
    skip:  //Annoying label
    //Get a word from readfile, store into word
    ...

    if (word[0] != '\0') {
      for (i = 0; i < NUMWORDS && appearlist[i]; i++) {
        if (strcmp(appearlist[i] -> word, word) == 0) {
          appearlist[i] -> num++;
          goto skip; //Annoying goto
        }
      }
      appearlist[i] = (Appearance *) malloc(sizeof(Appearance));
      appearlist[i] -> num = 1;
      strcpy(appearlist[i] -> word, word);
    }
  }

  //Display results, free memory
  ...

  return 0;
}


问题是,我想跳过要跳过的循环之外的代码。我不想创建仅为此设计的另一个变量。如果您需要完整的代码,请单击“显示代码片段”。



//Counts how many times every word appears in a file
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define NUMWORDS 1000
#define WORDLEN 50
#define FILENAMELEN 50

typedef struct
{
  char word[WORDLEN + 1];
  int num;
} Appearance;

int main(int argc, char *argv[])
{
  char filename[FILENAMELEN];
  FILE *readfile;
  Appearance *appearlist[NUMWORDS] = {NULL};
  char word[WORDLEN + 1];
  size_t ln;
  int i;

  if (argc == 2)
    strncpy(filename, argv[1], sizeof(filename));
  else {
    printf("Enter a filename to count appearances from, or just press enter to quit: ");
    fgets(filename, FILENAMELEN, stdin);
    ln = strlen(filename) - 1;
    if (filename[ln] == '\n')
      filename[ln] = '\0';
  }

  while((readfile = fopen(filename, "r")) == NULL) {
    if (filename[0] == '\0')
      return 0;
    printf("Invalid file! Please enter another filename, or just press enter to quit: ");
    fgets(filename, FILENAMELEN, stdin);
    ln = strlen(filename) - 1;
    if (filename[ln] == '\n') filename[ln] = '\0';
  }

  char c;

  while (c != EOF) {
    skip:
    for (i = 0; (c = getc(readfile)) != EOF && (isalnum(c) || c == '\''); i++) {
      if (i >= WORDLEN) {
        word[i] = '\0';
        printf("\nWarning: word too long (over %d characters), trimming to: %s\n", WORDLEN, word);
        while ((c = getc(readfile)) != EOF && (isalnum(c) || c == '\'')) ;
      } else {
        word[i] = tolower(c);
      }
    }
    word[i] = '\0';

    if (word[0] != '\0') {
      for (i = 0; i < NUMWORDS && appearlist[i]; i++) {
        if (strcmp(appearlist[i] -> word, word) == 0) {
          appearlist[i] -> num++;
          goto skip;
        }
      }
      appearlist[i] = (Appearance *) malloc(sizeof(Appearance));
      appearlist[i] -> num = 1;
      strcpy(appearlist[i] -> word, word);
    }
  }

  for (i = 0; i < NUMWORDS && appearlist[i]; i++) {
    printf("Word: %s, Appearances: %d\n", appearlist[i] -> word, appearlist[i] -> num);
    free(appearlist[i]);
  }

  return 0;
}

最佳答案

在这种情况下,使用goto通常被认为是可以接受的。

替代方法是设置一个变量,这样您就可以从内部的continue中将break放在外部循环中,或者将要转义的整个段变成一个单独的函数,然后从中返回而不是使用goto

我忽略了与该问题无关的代码中可能存在的任何其他问题!

关于c - 没有Goto的更好方法?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/32640164/

10-12 14:13