【问题标题】:How can I change an array of string pointers in another function?如何在另一个函数中更改字符串指针数组?
【发布时间】:2018-10-10 06:04:54
【问题描述】:

我一直在试图弄清楚如何修改 char 指针数组,但无论我做什么,下面似乎都没有变化是我试图改变的三个数组,包括对我正在调用的函数的调用使用。

char*cm1[5];
char*cm2[5];
char*cm3[5];
setupCommands(&cm1,commands,file,0);
setupCommands(&cm2,commands,file,1);
setupCommands(&cm3,commands,file,2);

下面的代码是函数本身。我在想它可能涉及双指针,但如果我尝试 *cmd 来更改数组,我会遇到分段错误。

void setupCommands(char **cmd[], char* commands[],char file[],int index){



    char str1[255];
    strcpy(str1,commands[index]);
    char newString [5][255];
    int j = 0;
    int ctr = 0;
    int i;
    //printf("str1 %s\n" ,str1);

    for(i = 0; i <= strlen(str1); i++){

        if(str1[i] == ' '|| str1[i] =='\0'){
            newString[ctr][j] = '\0';
            ctr++;//next row
            j=0;// for next word, init index to 0
        }else{
            newString[ctr][j]=str1[i];
            j++;
        }
    }


    for(i = 0; i < ctr; i++){
            //printf(" test2 %s \n", newString[i]);
        cmd[i] = newString[i];
            //printf(" test2 %d %s \n", i,cmd[i]);
    }
 //printf("index %d", i);
  cmd[i]= file;
  cmd[i + 1] = NULL;

  //execvp(cmd[0],cmd);
   //cmd
}

【问题讨论】:

  • 这里有一个明显的问题:您只能在函数中创建具有自动存储持续时间(局部变量的默认值)的对象。一旦函数退出,这些对象就不再存在了。
  • 有了这样的函数接口,实现必须使用malloc()和朋友(调用者将负责使用free()进行清理)
  • cmd[i] = newString[i]; 考虑newString[i] 指向的内容。这是一个副本。
  • 变量 ctr 不得超过 4,但代码中没有任何内容可以强制执行该标准

标签: c arrays pointers


【解决方案1】:

首先——做三颗星指针程序员不好:)

你将它分配给函数返回后不再可用的局部变量的指针

但如果你仍然想要三颗星指针:

char **cm1;
char **cm2;
char **cm3;
setupCommands(&cm1,commands,file,0);
setupCommands(&cm2,commands,file,1);
setupCommands(&cm3,commands,file,2);

#define MAXWORD 256

int setupCommands(char ***cmd, const char *commands,const char *file,int index){

    char str1[255];
    strcpy(str1,commands[index]);

    int j = 0;
    int ctr = 0;
    int i;
    //printf("str1 %s\n" ,str1);

    *cmd = malloc(sizeof(char *));
    **cmd = malloc(MAXWORD);
    if(!*cmd || !**cmd) 
    {
        /* do spmething if mallocs failed*/
        return -1;
    }
    for(i = 0; i <= strlen(str1); i++){

        if(str1[i] == ' '|| str1[i] =='\0'){
            (*cmd)[ctr][j] = '\0';
            ctr++;//next row
            *cmd = realloc((ctr + 1) * sizeof(int));
            (*cmd)[ctr] = malloc(MAXWORD);
            if(!*cmd || !*cmd[ctr]) 
            {
            /* do spmething if mallocs failed*/
                return -1;
            }

            j=0;// for next word, init index to 0
        }else{
            (*cmd)[ctr][j]=str1[i];
            j++;
        }
    }


    *cmd = realloc(sizeof(char *)  * ctr + 2)  
    (*cmd)[ctr - 2] = malloc(MAX);
    if(!*cmd || !*cmd[ctr - 2]) 
    {
        /* do spmething if mallocs failed*/
        return -1;
    }
    strcpy((*cmd)[ctr - 2], file);
    (*cmd)[ctr - 1] = NULL;

    return 0;

  //execvp(cmd[0],cmd);
   //cmd
}

您可以改进很多事情(例如,不要每次都重新分配,而是在更大的块中),我没有更改您的代码逻辑中的任何内容。

【讨论】:

  • 你真的认为这里的答案就足够了吗?
  • 对于一个答案,您至少应该说明哪个代码有误以及如何纠正它。
【解决方案2】:
  1. 您的代码存在一些问题:
    • 当函数退出时,您正试图返回对本地 'char newString [5][255]' 的引用。在简单的世界中 - 永远不要返回堆栈上本地分配的任何内容。这就是您遇到分段错误的原因。
    • char **cmd[] 必须声明为 char *cmd[] - 即使您会从编译器 assignment from incompatible pointer type 收到警告,代码也会正确运行和执行(本质上 **cmd[] 将与 *cmd[] 执行相同的工作,甚至虽然它的类型不正确)如果您没有返回对本地对象的引用;

简单简单的优化就是去掉数组str1,直接对数组commands进行操作。

除了这个简单的优化之外,我还更改了代码以克服分段错误,方法是在堆上分配,而不是在堆栈上(将一直存在到程序终止)多维数组,我还计算了它的大小,所以我会知道分配多少内存。现在可以安全地返回对它的引用了。

请注意,可以进行更多优化,但为了简单起见,这是该代码工作的最低限度。

int setupCommands(char *cmd[], char *commands[], char file[], int index)
{
int j = 0;
int ctr = 0;
int i = 0;

int rows = 0;
int cols = 0;

char **newString = NULL;

while(commands[index][i])
{
    if (commands[index][i] == ' ')
    {
        ++rows;
    }

    ++i;
}
++rows;

cols = strlen(commands[index]) + 1;

newString = malloc(rows * sizeof(*newString));
if (newString == NULL)
{
    return -1;
}

for (i = 0; i < rows; ++i)
{
    newString[i] = malloc(cols * sizeof(*newString));
    if (newString[i] == NULL)
    {
        return -1;
    }
}

for(i = 0; i <= strlen(commands[index]); i++){

    if(commands[index][i] == ' '|| commands[index][i] =='\0'){
        newString[ctr][j] = '\0';
        ctr++;//next row
        j=0;// for next word, init index to 0
    }else{
        newString[ctr][j]=commands[index][i];
        j++;
    }
}

for(i = 0; i < ctr; i++){

    cmd[i] = newString[i];

}

cmd[i]= file;
cmd[i + 1] = NULL;

return 0;
}

【讨论】:

    猜你喜欢
    • 2013-10-22
    • 1970-01-01
    • 2014-10-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-08
    • 2021-02-24
    相关资源
    最近更新 更多