Каков наилучший способ для анализа строки в массиве с нулевым символом в конце? - PullRequest
1 голос
/ 29 марта 2019

Я пишу простой интерпретатор командной строки. Мой код читает строку с использованием scanf и анализирует ее с помощью функции getArgs (), показанной ниже, а затем использует этот массив в качестве аргумента execvp для выполнения команды, такой как ls. Это работает, если я вызываю только «ls», но когда я вызываю «ls -la», это дает тот же результат, что и «ls».

void getArgs(char* command, char* args[]){

    int i = 0;
    char* p = strtok(command, " "); 
    args[i] = p;

    while(p != NULL){
        i++; 
        p = strtok(NULL, " ");
        args[i] = p;
}
}

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

int main(){
char *args[1024];
char example[30]; 
char exit[5] = {'q', 'u', 'i', 't', '\0'};
int f1; 
int status;
size_t n = sizeof(args)/sizeof(args[0]);

while(strncmp(example, exit, 30) !=0){

    printf(">>>");
    scanf("%s", example);
    getArgs(example, args);
    int x = strncmp(args[0], exit, 30);

    if (x != 0){
        f1 = fork(); 
        if (f1 != 0){
            /* wait  for child process to terminate */
            waitpid(f1, &status, 0);
        }
        else{myExec(args);}}         
    else{
        return 0;}}
    return 0; 
}

Я предполагаю, что проблема в том, что мой массив аргументов, args, не завершается нулем, и поэтому, когда я пытаюсь использовать его в myExec ():

void myExec(char* args[]){
    execvp(args[0], args);
}

это не работает. Итак, мой вопрос, могу ли я установить элемент после последней непустой части моего массива в null, чтобы попытаться заставить это работать? Если так, как я могу это сделать? Есть ли лучший способ решить эту проблему?

Ответы [ 2 ]

1 голос
/ 29 марта 2019

Директива %s прекращает сканирование с первого символа пробела, поэтому она не будет правильно захватывать любые команды с пробелами (например, ls -la). Вы должны использовать fgets для получения пользовательского ввода, если вы хотите сохранить любые пробелы:

if ( fgets( example, sizeof example, stdin ) )
{
  getArgs( example, args);
  ...
}

fgets прочитает до sizeof example - 1 символов в example (включая символ новой строки!) И завершит строку 0. Возможно, вы захотите принять эту новую строку во внимание при звонке strtok.

1 голос
/ 29 марта 2019

-la игнорируется, потому что scanf("%s", example); остановится на первом месте. Я предлагаю

scanf(" %29[^\n]", example);

Который будет

  • Игнорировать пробелы, оставленные в буфере от предыдущей команды.
  • Ограничить строковый ввод от переполнения.
  • Разрешить разделители пробелов в команде.

Обратите внимание, что при первом выполнении while(strncmp(example, exit, 30) !=0) example является неинициализированной переменной, поэтому должно быть

char example[30] = "";
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...