2014-12-28 3 views
1

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

void readcmd(char* cmd, char* params) { 
    char* input; 
    size_t size = 0; 
    char* sep = "\t\v\r\f\n\b "; // separator 

    getline(&input, &size, stdin); 
    cmd = strtok(input, sep); 
} 

И мой вклад:

Мне нравится Stackoverflow!

В приведенном выше коде я сделал свой программный магазин первым жетоном в cmd массив. Я хочу, чтобы остальная часть предложения хранилась в массиве params; таким образом:

CMD: I

PARAMS: как Stackoverflow!

Как я могу это достичь?

Спасибо

+1

Это также, чтобы убедиться, что 'вход = 0;' - безопасность прежде всего - даже несмотря на то, спецификация 'GetLine () 'говорит: _ Приложение должно гарантировать, что' * lineptr' является допустимым аргументом, который может быть передан функции 'free()'. Если '* n' не равно нулю, приложение должно гарантировать, что' * lineptr' либо указывает на объект размером не менее '* n' байт, либо является нулевым указателем. Вы не должны передавать неинициализированный указатель на 'free()', поэтому вы не должны передавать (адрес) неинициализированный указатель на 'getline()'. Вам также необходимо «освободить (ввести)» перед возвратом. –

+1

Кроме того, поскольку вы не знаете, сколько пространства 'params' указывает на, вы не можете безопасно скопировать остаток строки в' params'. Аналогично 'cmd'; вы не можете сказать, насколько велика имя команды в безопасности. Я предлагаю обновить вашу функцию, чтобы иметь подпись 'void readcmd (char * cmd, size_t cmdlen, char * params, size_t paramslen)'. Кроме того, вы не проверяете наличие ошибок ('getline()' возвращает '-1', а не EOF, кстати), и вы не можете сообщить, что произошла ошибка (если не использовать одну или обе строки для пустых). –

+0

Большое спасибо Jonathan –

ответ

0

после обработки комментариев, более полный пример:

#include <stdlib.h> 
#include <stdio.h> 
#include <string.h> 

void readcmd(char** cmd, char** params) { 
    char* input = 0; 
    size_t size = 0; 
    char* sep = "\t\v\r\f\n\b "; // separator 

    if (getline(&input, &size, stdin) < 0) { 
    printf("failed to read a line\n"); 
    exit(-1); 
    } 

    *cmd = strtok(input, sep); 

    if (*cmd) { 
    *cmd = strdup(*cmd); 
    *params = strdup(input + strlen(input) + 1); 
    } 
    free(input); 
} 

int main(int argc, char** argv) { 
    char *cmd = 0; 
    char *params = 0; 

    readcmd(&cmd, &params); 

    if (cmd) { 
    printf("cmd: %s\n", cmd); 
    free(cmd); 
    } 
    if (params) { 
    printf("params: %s\n", params); 
    free(params); 
    } 

    return 0; 
} 
+2

Вам придется разделить команду на параметры, возможно, с помощью 'strtok_r()' или 'strtok_s()', или, возможно, используя 'strcspn()' или 'strpbrk()'. Вероятно, вы тогда поместите нулевой байт в точку разделения. Тогда '* params = input + strlen (cmd);' будет указывать на нулевой байт; вам нужно '* params = input + strlen (cmd) + 1;'. Обратите внимание, что если вам нужно пропустить ведущее белое пространство от ввода, то возвращаемое значение не будет пропускаемым для 'free()', но если вы не 'free()' то, что возвращается, вы протекаете. Это лучше для 'strdup()' строк: '* params = strdup (input + strlen (input) + 1);' и 'free (input);'? –

+2

"* о чем-то *" - это битва. Также результат вашего предложенного фрагмента может не вернуть то, что ожидает OP, так как оно будет указывать на '' \ 0''. – alk

+0

Это решило мой вопрос с помощью @JonathanLeffler. Большое спасибо! –