реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> Парсинг строки.
Jenya7
сообщение Apr 30 2015, 05:25
Сообщение #1


Профессионал
*****

Группа: Участник
Сообщений: 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);

когда иду в отладке шаг за шагом вроде все чары попадают куда нужно, но на выходе нулевые строки. что за чудеса?
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Apr 30 2015, 05:54
Сообщение #2


Гуру
******

Группа: Модераторы
Сообщений: 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)
Go to the top of the page
 
+Quote Post
psL
сообщение Apr 30 2015, 06:08
Сообщение #3


Знающий
****

Группа: Свой
Сообщений: 526
Регистрация: 5-08-05
Пользователь №: 7 390



Может проще парсить команду при помощи strtok в массив указателей?
http://www.cplusplus.com/reference/cstring/strtok/
Go to the top of the page
 
+Quote Post
Jenya7
сообщение Apr 30 2015, 06:52
Сообщение #4


Профессионал
*****

Группа: Участник
Сообщений: 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));
  }
}

тот же результат
Go to the top of the page
 
+Quote Post
Realking
сообщение Apr 30 2015, 07:37
Сообщение #5


Местный
***

Группа: Свой
Сообщений: 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
Причина редактирования: Избыточное цитирование


--------------------
Человек - это существо, которое охотнее всего рассуждает о том, в чем меньше всего разбирается.
Go to the top of the page
 
+Quote Post
Jenya7
сообщение Apr 30 2015, 07:50
Сообщение #6


Профессионал
*****

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



Цитата(Realking @ Apr 30 2015, 12:37) *
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'.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Apr 30 2015, 11:18
Сообщение #7


Гуру
******

Группа: Модераторы
Сообщений: 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)
Go to the top of the page
 
+Quote Post
Jenya7
сообщение Apr 30 2015, 11:32
Сообщение #8


Профессионал
*****

Группа: Участник
Сообщений: 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
Go to the top of the page
 
+Quote Post
psL
сообщение Apr 30 2015, 16:32
Сообщение #9


Знающий
****

Группа: Свой
Сообщений: 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;
}

непонятно только, зачем отправлять команду в порт порциями?
Go to the top of the page
 
+Quote Post
Jenya7
сообщение May 3 2015, 05:59
Сообщение #10


Профессионал
*****

Группа: Участник
Сообщений: 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;
}

Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 24th July 2025 - 04:11
Рейтинг@Mail.ru


Страница сгенерированна за 0.01468 секунд с 7
ELECTRONIX ©2004-2016