2014-11-09 3 views
0

Я пытаюсь запустить execvp, используя данные из типа char [] [] (также известный как массив строк). Теперь я знаю, что execvp() берет указатель на строку в качестве своего первого параметра, а затем указатель на массив строк в качестве второго - на самом деле я даже использовал его успешно раньше как таковой - однако я не могу получить правильную комбинацию указатели & строки, чтобы заставить его работать ниже - все, что я пробовал, считается несовместимым!Запуск execvp из параметра 2D-массива

Любая помощь очень благодарна :) - Я удалил свои заголовки, чтобы немного сжать код!

struct userinput { 
    char anyargs[30][30]; //The tokenised command 
}; 

int main() { 

    struct userinput input = { { { 0 } } }; //I believe is valid to set input to 0's 
    struct userinput *inPtr = &input; //Pointer to input (direct access will be unavailable) 

    strcpy(inPtr->anyargs[0], "ls"); //Hard code anyargs to arbitary values 
    strcpy(inPtr->anyargs[1], "-lh"); 

    char (*arrPointer)[30]; //Pointer to an array of char * 
    arrPointer = &(inPtr->anyargs[0]); 

    printf("arrPointer[0]: %s, arrPointer[1]: %s\n", arrPointer[0], 
      arrPointer[1]); 

    printf("At exec case; "); 
    execvp(arrPointer[0], arrPointer); 
    perror("Command not recognised"); //Prints string then error message from errno 

    return 0; 
} 
+0

Вы пробовали 'arrPointer = (inPtr-> anyargs);' without &? – Christophe

+0

Да - исправьте меня, если я ошибаюсь - оператор -> de-ссылки и возвращает значение, которое мы не хотим, поскольку arrPointer и execvp не принимают значения напрямую - они принимают указатели на значения? – davidhood2

ответ

2

Там нет такого понятия, как char[][] в С. execvp требует массив указателей на const char. Это можно записать в виде либо char * const * или char * const [].

Вы, однако есть массив из 30-символов -длинные массивы, а не массив указателей. два типа не совместимы, не взаимозаменяемы, а не конвертируемые один к другому в любом направлении.

в этой строке

char (*arrPointer)[30]; //Pointer to an array of char * 

вы пытаетесь объявить указатель на массив char *, неправильно. Вместо этого вы указали указатель на char[30], который сильно отличается от того, что ожидает execvp.

Следующая строка

arrPointer = &(inPtr->anyargs[0]); 

желает, чтобы инициализировать указатель на массив char* с указателем на char[30], который не может быть правильным, даже если объявить указатель на массив char*, поскольку право сторона указателя не является указателем на массив из char*, это указатель на char[30], и никакая последовательность слепок, индексов, адресов и разметок не превратится одна в другую.

Массив из 30 указателей на char объявлен как это:

char* arguments[30]; 

Динамически размера массив указателей на char делается так:

char** arguments = calloc (nargs, sizeof(char*)); 

Вы должны использовать один из те, если вы хотите позвонить execvp.

В любом случае каждый указатель в массиве указателей должен быть инициализирован, чтобы указывать на отдельный массив символов с нулевым символом (возможно, на элементы вашего массива char[30][30]) и последний указатель (один за другим argumenrs, который мы хотим передать) должно быть установлено значение NULL. (Интересно, как вы ожидали найти NULL в char[30][30]).

2

В execvp() ожидает как второй аргумент char *const argv[]. Это означает массив указателей на char. Это отличается от char[30][30], который представлен в памяти как 30x30 смежных символов (так что не указатель).

Чтобы решить эту проблему, определить структуру

struct userinput { 
    char *anyargs[30]; //space for 30 char* pointers 
}; 

Вы можете так же определить anyargs как char** и инициализировать, если динамически (char**)calloc(number_of_args+1,sizeof(char*))

Позже, назначить непосредственно указатели:

inPtr->anyargs[0] = "ls"; //Hard code (or use strdup()) 
inPtr->anyargs[1] = "-lh"; 
inPtr->anyargs[2] = NULL; // end of the argument list !!! 
char **arrPointer; //Pointer to an array of char * 
arrPointer = inPtr->anyargs; 

Изменить: Внимание: «Массив указателей mu st заканчивается указателем NULL.».