jenya7 0 30 апреля, 2015 Опубликовано 30 апреля, 2015 · Жалоба Делаю так 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); когда иду в отладке шаг за шагом вроде все чары попадают куда нужно, но на выходе нулевые строки. что за чудеса? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 119 30 апреля, 2015 Опубликовано 30 апреля, 2015 · Жалоба Делаю так char *command=""; То есть под command вы отвели место ровно в один символ - символ конца строки. com[char_idx++] = *str; А теперь вылезли за пределы command и пошли портить соседние данные. Возможно есть и другие причины, но сначала надо устранить эту. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
psL 0 30 апреля, 2015 Опубликовано 30 апреля, 2015 · Жалоба Может проще парсить команду при помощи strtok в массив указателей? http://www.cplusplus.com/reference/cstring/strtok/ Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jenya7 0 30 апреля, 2015 Опубликовано 30 апреля, 2015 · Жалоба То есть под command вы отвели место ровно в один символ - символ конца строки. А теперь вылезли за пределы command и пошли портить соседние данные. Возможно есть и другие причины, но сначала надо устранить эту. Исправил char *command=""; на char *command; не помогло char_idx я обнуляю в начале и потом он обнуляется на каждом разделительном чаре - в данном случае пробел. Может проще парсить команду при помощи 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)); } } тот же результат Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Realking 0 30 апреля, 2015 Опубликовано 30 апреля, 2015 (изменено) · Жалоба 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; } Изменено 30 апреля, 2015 пользователем Herz Избыточное цитирование Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jenya7 0 30 апреля, 2015 Опубликовано 30 апреля, 2015 · Жалоба 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; } да, так работает. спасибо. странно - компайлер обычно закрывает все строки с '\0'. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 119 30 апреля, 2015 Опубликовано 30 апреля, 2015 · Жалоба Исправил char *command=""; на char *command; не помоглоЕще лучше. Сначала вы заводили массив из одного байта ("") и объявляли указатель (command *), указывающий на начало этого массива. После чего, двигая указатель уходили за пределы массива, круша все, что попадалось на пути. Теперь вы просто завели указатель, показывающий куда попало (потому что неиницимализированный и содержащий мусор из памяти) и начали крушить уже где попало. Не удивлюсь, если компилятор выдал предупреждение об этом, но вы на это предупреждение забили. странно - компайлер обычно закрывает все строки с '\0'. Компилятор автоматически добавляет завершающий ноль к строковым литералам. Он не обладает телепатическими свойствами чтобы понять, что выражением "arg[arg_idx-1][char_idx++] = *str;" вы создаете новую строку - для него это просто копирование символа из одного места в другое. Только копирование и ничего более. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jenya7 0 30 апреля, 2015 Опубликовано 30 апреля, 2015 (изменено) · Жалоба Еще лучше. Сначала вы заводили массив из одного байта ("") и объявляли указатель (command *), указывающий на начало этого массива. После чего, двигая указатель уходили за пределы массива, круша все, что попадалось на пути. Теперь вы просто завели указатель, показывающий куда попало (потому что неиницимализированный и содержащий мусор из памяти) и начали крушить уже где попало. Не удивлюсь, если компилятор выдал предупреждение об этом, но вы на это предупреждение забили. неа, молчит гад, не ругается. и кстати почему так работает? char *command=""; command = strtok(str," "); Компилятор автоматически добавляет завершающий ноль к строковым литералам. Он не обладает телепатическими свойствами чтобы понять, что выражением "arg[arg_idx-1][char_idx++] = *str;" вы создаете новую строку - для него это просто копирование символа из одного места в другое. Только копирование и ничего более. но последний символ строки он ведь '\0'. у меня же нет index overflow. да и кстати он таки телепат -у меня фиксированные строки char arguments[4][20]; Изменено 30 апреля, 2015 пользователем Jenya7 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
psL 0 30 апреля, 2015 Опубликовано 30 апреля, 2015 · Жалоба я пробовал так 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; } непонятно только, зачем отправлять команду в порт порциями? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jenya7 0 3 мая, 2015 Опубликовано 3 мая, 2015 · Жалоба По идее как-то так д.б. : #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; } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться