Как я могу изменить массив строковых указателей в другой функции? - PullRequest
0 голосов
/ 30 апреля 2018

Я пытался выяснить, как изменить массив указателей на символы, но, независимо от того, что я делаю, я не вижу никаких изменений ниже, это три массива, которые я пытаюсь изменить, включая вызов функции, которую я использование.

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
}

Ответы [ 2 ]

0 голосов
/ 30 апреля 2018
  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;
}
0 голосов
/ 30 апреля 2018

Прежде всего - быть программистом указателя на три звезды нехорошо:)

Вы назначаете его указателем на локальную переменную, которая больше не доступна после возврата функции

Но если вам все еще нужны указатели на три звезды:

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
}

Вы можете улучшить многие вещи (например, не перераспределять каждый раз, но в больших кусках), и я ничего не изменил в логике вашего кода.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...