|
|
  |
Парсинг строки. |
|
|
|
Apr 30 2015, 05:25
|
Профессионал
    
Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075

|
Делаю так Код uint32_t ParseCommandArguments(char *str, char *com, char arg[4][20]) { uint32_t char_idx = 0; uint32_t arg_idx = 0; while(*str) { if(*str != 32) //not space { if(arg_idx==0) //command { com[char_idx++] = *str; } else //arguments { arg[arg_idx-1][char_idx++] = *str; } } else // space { char_idx = 0; arg_idx++; } str++; } return arg_idx; } и потом Код char *str = "run arg1 arg2"; char *command=""; char arguments[4][20];
uint32_t argc = ParseCommandArguments(str, command, arguments); UART_SendString(UART0,command); UART_SendString(UART0,arguments[0]); UART_SendString(UART0,arguments[1]); UART_SendInt(UART0,argc); когда иду в отладке шаг за шагом вроде все чары попадают куда нужно, но на выходе нулевые строки. что за чудеса?
|
|
|
|
|
Apr 30 2015, 05:54
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(Jenya7 @ Apr 30 2015, 08:25)  Делаю так Код char *command=""; То есть под command вы отвели место ровно в один символ - символ конца строки. Цитата(Jenya7 @ Apr 30 2015, 08:25)  Код com[char_idx++] = *str; А теперь вылезли за пределы command и пошли портить соседние данные. Возможно есть и другие причины, но сначала надо устранить эту.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Apr 30 2015, 06:52
|
Профессионал
    
Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075

|
Цитата(Сергей Борщ @ Apr 30 2015, 10:54)  То есть под command вы отвели место ровно в один символ - символ конца строки. А теперь вылезли за пределы command и пошли портить соседние данные.
Возможно есть и другие причины, но сначала надо устранить эту. Исправил char *command=""; на char *command; не помогло char_idx я обнуляю в начале и потом он обнуляется на каждом разделительном чаре - в данном случае пробел. Цитата(psL @ Apr 30 2015, 11:08)  Может проще парсить команду при помощи strtok в массив указателей? http://www.cplusplus.com/reference/cstring/strtok/я пробовал так Код void Split(char *str, char *com, char arg[4][20]) { uint32_t arg_idx = 0; char * pch; pch = strtok (str," "); strncpy(com,pch,strlen(pch)); while (pch != NULL) { pch = strtok (NULL, " "); strncpy(arg[arg_idx++],pch,strlen(pch)); } } тот же результат
|
|
|
|
|
Apr 30 2015, 07:37
|
Местный
  
Группа: Свой
Сообщений: 498
Регистрация: 4-10-04
Из: Нижний Новгород
Пользователь №: 771

|
char command[64];if(arg_idx==0) //command { com[char_idx++] = *str; com[char_idx] = 0; } else //arguments { arg[arg_idx-1][char_idx++] = *str; arg[arg_idx-1][char_idx] = 0; }
Сообщение отредактировал Herz - Apr 30 2015, 11:20
Причина редактирования: Избыточное цитирование
--------------------
Человек - это существо, которое охотнее всего рассуждает о том, в чем меньше всего разбирается.
|
|
|
|
|
Apr 30 2015, 11:18
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(Jenya7 @ Apr 30 2015, 09:52)  Исправил char *command=""; на char *command; не помогло Еще лучше. Сначала вы заводили массив из одного байта ("") и объявляли указатель (command *), указывающий на начало этого массива. После чего, двигая указатель уходили за пределы массива, круша все, что попадалось на пути. Теперь вы просто завели указатель, показывающий куда попало (потому что неиницимализированный и содержащий мусор из памяти) и начали крушить уже где попало. Не удивлюсь, если компилятор выдал предупреждение об этом, но вы на это предупреждение забили. Цитата(Jenya7 @ Apr 30 2015, 10:50)  странно - компайлер обычно закрывает все строки с '\0'. Компилятор автоматически добавляет завершающий ноль к строковым литералам. Он не обладает телепатическими свойствами чтобы понять, что выражением "arg[arg_idx-1][char_idx++] = *str;" вы создаете новую строку - для него это просто копирование символа из одного места в другое. Только копирование и ничего более.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Apr 30 2015, 11:32
|
Профессионал
    
Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075

|
Цитата(Сергей Борщ @ Apr 30 2015, 16:18)  Еще лучше. Сначала вы заводили массив из одного байта ("") и объявляли указатель (command *), указывающий на начало этого массива. После чего, двигая указатель уходили за пределы массива, круша все, что попадалось на пути. Теперь вы просто завели указатель, показывающий куда попало (потому что неиницимализированный и содержащий мусор из памяти) и начали крушить уже где попало. Не удивлюсь, если компилятор выдал предупреждение об этом, но вы на это предупреждение забили. неа, молчит гад, не ругается. и кстати почему так работает? char *command=""; command = strtok(str," "); Цитата(Сергей Борщ @ Apr 30 2015, 16:18)  Компилятор автоматически добавляет завершающий ноль к строковым литералам. Он не обладает телепатическими свойствами чтобы понять, что выражением "arg[arg_idx-1][char_idx++] = *str;" вы создаете новую строку - для него это просто копирование символа из одного места в другое. Только копирование и ничего более. но последний символ строки он ведь '\0'. у меня же нет index overflow. да и кстати он таки телепат -у меня фиксированные строки char arguments[4][20];
Сообщение отредактировал Jenya7 - Apr 30 2015, 11:37
|
|
|
|
|
Apr 30 2015, 16:32
|
Знающий
   
Группа: Свой
Сообщений: 526
Регистрация: 5-08-05
Пользователь №: 7 390

|
Цитата(Jenya7 @ Apr 30 2015, 09:52)  я пробовал так Код void Split(char *str, char *com, char arg[4][20]) { uint32_t arg_idx = 0; char * pch; pch = strtok (str," "); strncpy(com,pch,strlen(pch)); while (pch != NULL) { pch = strtok (NULL, " "); strncpy(arg[arg_idx++],pch,strlen(pch)); } } тот же результат По идее как-то так д.б. : Код #define ARGS_MAX 16 #define ARGS_DELIM " "
static char* args[ARGS_MAX]={ NULL };
int parse_command(char* str, char** args) { int argc=0;
args[argc] = strtok (str, ARGS_DELIM);
while (args[argc] != NULL) { if(argc >= ARGS_MAX) break; args[++argc] = strtok (NULL, ARGS_DELIM); }
return argc; }
void uart_send_string(int uart, char* command) { printf("send: %s\n", command); }
int main () { char str[] = "run arg1 arg2"; int argc, i;
argc = parse_command(str, args);
for(i=0;i<argc; i++) { uart_send_string(1, args[i]); }
return 0; } непонятно только, зачем отправлять команду в порт порциями?
|
|
|
|
|
May 3 2015, 05:59
|
Профессионал
    
Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075

|
Цитата(psL @ Apr 30 2015, 21:32)  По идее как-то так д.б. : Код #define ARGS_MAX 16 #define ARGS_DELIM " "
static char* args[ARGS_MAX]={ NULL };
int parse_command(char* str, char** args) { int argc=0;
args[argc] = strtok (str, ARGS_DELIM);
while (args[argc] != NULL) { if(argc >= ARGS_MAX) break; args[++argc] = strtok (NULL, ARGS_DELIM); }
return argc; }
void uart_send_string(int uart, char* command) { printf("send: %s\n", command); }
int main () { char str[] = "run arg1 arg2"; int argc, i;
argc = parse_command(str, args);
for(i=0;i<argc; i++) { uart_send_string(1, args[i]); }
return 0; } непонятно только, зачем отправлять команду в порт порциями? да, спасибо. так работает. самый лучший ваиант - он к тому же разруливает множественные пробелы. в моем варианте я должен почистить пробелы в начале и в середине. Код uint32_t PARSER_ParseCommandArguments(char *str, char *com, char arg[4][20]) { uint32_t char_idx = 0; uint32_t arg_idx = 0; //trim leading spaces while(*str++ == ' '); str--; while(*str) { if(*str != ' ') //not space { if(arg_idx==0) //command { com[char_idx++] = *str; com[char_idx] = 0; //*com++ = *str; } else //arguments { arg[arg_idx-1][char_idx++] = *str; arg[arg_idx-1][char_idx] = 0; } } else //space { char_idx = 0; arg_idx++; //to avoid multiple spaces while(*str++ == ' '); //str++; str-=2; } str++; } return arg_idx; }
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|