2016-04-30 94 views
-8

如果我有一个像矩阵或树的数据结构,并且我想从包含上述变量的非常大的函数中分解出一个for循环,那么调用应该如何进行?我尝试了以下,但我得到了分段错误。如何选择函数原型的类型?

void write_command(int w, char *argv[], char *string[]) { 
    char *dest; 

    for (int r = 0; argv[r] != NULL; r++) { 
     dest = malloc(sizeof(char *) * strlen(argv[r]) + 1); 
     *dest = '0'; 
     strcpy(dest, argv[r]); 
     string[w][r] = *dest; 
     free(dest); 
    } 
} 

我想你看看我在做什么,但我该如何声明变量?我在string[w][r] = *dest;处遇到段错误。

我不认为你想看看我在重构什么,但它是有史以来最大,最难读的功能。

static int runCmd(const char *cmd) { 
    const char *cp; 
    pid_t pid; 
    int status; 
    struct command structcommand[15]; 
    char **argv = 0; 
    int argc = 1; 
    bool pipe = false; 
    char *string[z][z]; 
    char *pString3[40]; 
    char *pString2[40]; 
    int n = 0; 
    char **ptr1; 
    char string1[z]; 
    bool keep = false; 
    char *pString1[z]; 
    char *pString[z]; 
    *pString1 = "\0"; 
    *pString = "\0"; 
    char *temp = {'\0'}; 
    int w = 0; 
    bool b = false; 
    int j = 0; 
    int i; 
    int p = 0; 
    char **ptr; 
    char *tmpchar; 
    char *cmdtmp; 
    bool b1 = false; 
    char *dest; 
    int y = 0; 
    i = 0; 
    int h = 0; 
    nullterminate(string); 
    if (cmd) { 
     for (cp = cmd; *cp; cp++) { 
      if ((*cp >= 'a') && (*cp <= 'z')) { 
       continue; 
      } 
      if ((*cp >= 'A') && (*cp <= 'Z')) { 
       continue; 
      } 
      if (isDecimal(*cp)) { 
       continue; 
      } 
      if (isBlank(*cp)) { 
       continue; 
      } 
      if ((*cp == '.') || (*cp == '/') || (*cp == '-') || 
       (*cp == '+') || (*cp == '=') || (*cp == '_') || 
       (*cp == ':') || (*cp == ',') || (*cp == '\'') || 
       (*cp == '"')) { 
       continue; 
      } 
     } 
    } 
    if (cmd) { 
     cmdtmp = malloc(sizeof(char *) * strlen(cmd) + 1); 
     strcpy(cmdtmp, cmd); 
     tmpchar = malloc(sizeof(char *) * strlen(cmd) + 1); 
     if (tmpchar == NULL) { 
      printf("Error allocating memory!\n"); /* print an error message */ 
      return 1; /* return with failure */ 
     } 
     strcpy(tmpchar, cmd); 
     ptr1 = str_split(pString3, cmdtmp, '|'); 
     if (strstr(cmd, "|") == NULL) {   /* not a pipeline */ 
      makeArgs(cmd, &argc, (const char ***) &argv, pipe, 0, 0); 
      for (j = 0; j < argc; j++) { 
       string[0][j] = argv[j]; 
       structcommand[i].argv = string[0]; /*process;*/ 
      } 
      n++; 
     } 
     else { 
      for (i = 0; *(ptr1 + i); i++) { /* tokenize the input string for each pipeline*/ 
       n++; /* save number of pipelines */ 
       int e = 0; /* a counter */ 
       *pString = "\0"; /* should malloc and free this? */ 
       strcpy(string1, *(ptr1 + i)); 
       if ((string1[0] != '\0') && !isspace(string1[0])) { /* this is neither the end nor a new argument */ 
        ptr = str_split(pString2, *(&string1), ' '); /* split the string at the arguments */ 
        h = 0; 
        for (j = 0; *(ptr + j); j++) { /* step through the arguments */ 
         /* the pipeline is in cmdtmp and the argument/program is in ptr[i] */ 
         if (ptr + j && !b && strstr(*(ptr + j), "'")) { 
          b = true; 
          strcpy(temp, *(ptr + j)); 
          if (y < 1) { 
           y++; 
          } 
         } 
         while (b) { 
          if (*(ptr + j) && strstr(*(ptr + j), "'")) { /* end of quote */ 
           b = false; 
           if (y < 1) { 
            string[i][j] = strcpy(temp, *(ptr + j)); 
           } 
           y = 0; 
          } 
          else if (*(ptr + j)) { /* read until end of quote */ 
           string[i][j] = temp; 
           continue; 
          } else { 
           b = false; 
           break; 
          } 
         } 
         if (ptr + j) { 
          if (*(ptr + j)[0] == '{') { 
           keep = true; 
          } 
          if (testFn(*(ptr + j))) { /* test for last char */ 
           string[i][j - p] = concat(*pString1, *(ptr + j)); 
           keep = false; 
           free(*pString1); 
           goto mylabel; 
          } 
          if (keep) { 
           *pString1 = concat(*pString1, *(ptr + j)); 
           *pString1 = concat(*pString1, " "); 
           p++; 
          } else { 
//        strcpy(temp, *(ptr + j)); 
           b1 = false; 
           int q = j; 
           for (e = 0; *(ptr + q + e); e++) { /* step through the string */ 
            b1 = true; 
            if (*(ptr + e + q)) { 
             *pString = concat(*pString, *(ptr + e + q)); 
             *pString = concat(*pString, " "); 
            } 
            j = e; 
           } 
           if (makeArgs(*pString, &argc, (const char ***) &argv, pipe, i, h)) { 

            write_command(&w, argv, string[w]); 

            /*for (int r = 0; argv[r] != NULL; r++) { 
             dest = malloc(sizeof(char *) * strlen(argv[r]) + 1); 
             *dest = '0'; 
             strcpy(dest, argv[r]); 
             string[w][r] = dest; 
            }*/ 
            w++; 


           } else { 
            if (!b1) { /* no args (?) */ 
             for (int r = 0; argv[r] != NULL; r++) { 
              string[i][r] = argv[r]; 
             } 

            } 
           } 

          } 
         } 
        } 
        mylabel: 
        free(ptr); 
        dump_argv((const char *) "d", argc, argv); 
       } 
      } 
      free(ptr1); 
      free(cmdtmp); 
      free(tmpchar); 
     } 
     for (i = 0; i < n; i++) { 
      for (j = 0; DEBUG && string[i][j] != NULL; j++) { 
       if (i == 0 && j == 0) printf("\n"); 
       printf("p[%d][%d] %s\n", i, j, string[i][j]); 
      } 
      structcommand[i].argv = string[i]; 
     } 
     fflush(NULL); 
     pid = fork(); 
     if (pid < 0) { 
      perror("fork failed"); 
      return -1; 
     } 
     /* If we are the child process, then go execute the string.*/ 
     if (pid == 0) { 
      /* spawn(cmd);*/ 
      fork_pipes(n, structcommand); 
     } 
     /* 
     * We are the parent process. 
     * Wait for the child to complete. 
     */ 
     status = 0; 
     while (((pid = waitpid(pid, &status, 0)) < 0) && (errno == EINTR)); 
     if (pid < 0) { 
      fprintf(stderr, "Error from waitpid: %s", strerror(errno)); 
      return -1; 
     } 
     if (WIFSIGNALED(status)) { 
      fprintf(stderr, "pid %ld: killed by signal %d\n", 
        (long) pid, WTERMSIG(status)); 

      return -1; 
     } 
    } 
    return WEXITSTATUS(status); 


} 
+1

是'char * string []'错字'char * string [z] [z]'实例或其他变量? – user3078414

+5

不,实际上,它不清楚你想要做什么。我最好的猜测是,你正试图对给定的'argv'数组做一个深层次的拷贝,但是在这种情况下,你根本不清楚你开始的变量声明char * string [z] [z]; ',符合图片。也不清楚为什么你似乎在函数内释放分配的内存。 –

+0

我试图重构一个大功能,将一个for-loop分解成一个函数并调用函数,但我不习惯传递指针,因为我是OOP。关键的见解是要理解我不需要传递矩阵作为参数,传递矩阵可以作为数组完成。现在我尝试为我的下一个重构传递一个'struct',并且我遇到了类似的问题,因为我不是专家级的C程序员。 –

回答

3

我会假设你正在试图使argv阵列的深层副本,有了这样的字符串的NULL封端阵列,如C语言程序main()函数的第二个参数。您呈现的功能似乎假定您已经为目标阵列本身分配了空间;它的工作似乎仅限于复制参数字符串。

首先要做的第一件事就是:让我们来看看调用者。如果你正在制作一个标准参数向量的深层副本,那么目标变量的类型应该与argv本身的类型兼容(口语意义上的“兼容”)。如果复制的寿命并不需要延长过去的主机功能的回归,那么变长数组将是一个不错的选择:

char *copy[argc + 1]; 

这免除了您手动管理阵列本身的内存,但而不是管理任何唯一分配给其元素的内存。在另一方面,如果你需要复制生存在声明它的函数返回,那么你就必须使用手动分配:

char **copy = malloc((argc + 1) * sizeof(*copy)); 
if (!copy) /* handle allocation failure */ ; 

无论哪种方式,您可以通过生成的数组或指针本身为您的write_command()函数,并且所需的参数类型相同。将指针传递给copy毫无意义,因为该函数不会修改它接收的指针作为其参数;相反,它会修改它指向的内存。

下面是函数的你似乎要签名:

void write_command(char *argv[], char *string[]) { 

鉴于这样的签名,你就称呼其为...

write_command(argv, copy); 

....

你似乎想在循环里面执行的关键步骤是

string[r] = strdup(argv[r]); 

可以完成同样的事情用malloc(),初始化,strcpy()序列,但是这是一个有点傻的时候是stdrup()现成的为同一任务。但是,如果内存分配失败,不要忘记检查其返回值(或者在原始代码中,返回值为malloc())。周围的任何方式,你必须write_command()释放分配的内存,因为离开你与你的复制数组内无效指针。


而且,即使你真的有char *在调用一个二维数组,如...

char *copies[n][argc + 1]; 

... 没有什么变化与功能write_command()。它不需要知道或关心它拷贝到的数组是否是2D数组的元素。您只需适当地调用它,是这样的:不管是什么,你必须确保释放被复制的参数字符串

write_command(argv, copies[w]); 

,但只有在你不再需要他们。再次,您不能在write_command()函数中执行此操作。