Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Парсинг строки.
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > Программирование
Jenya7
Делаю так
Код
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);

когда иду в отладке шаг за шагом вроде все чары попадают куда нужно, но на выходе нулевые строки. что за чудеса?
Сергей Борщ
Цитата(Jenya7 @ Apr 30 2015, 08:25) *
Делаю так
Код
char *command="";

То есть под command вы отвели место ровно в один символ - символ конца строки.
Цитата(Jenya7 @ Apr 30 2015, 08:25) *
Код
                com[char_idx++] = *str;
А теперь вылезли за пределы command и пошли портить соседние данные.

Возможно есть и другие причины, но сначала надо устранить эту.
psL
Может проще парсить команду при помощи strtok в массив указателей?
http://www.cplusplus.com/reference/cstring/strtok/
Jenya7
Цитата(Сергей Борщ @ 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));
  }
}

тот же результат
Realking
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;
}
Jenya7
Цитата(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'.
Сергей Борщ
Цитата(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;" вы создаете новую строку - для него это просто копирование символа из одного места в другое. Только копирование и ничего более.
Jenya7
Цитата(Сергей Борщ @ 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];
psL
Цитата(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;
}

непонятно только, зачем отправлять команду в порт порциями?
Jenya7
Цитата(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;
}

Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.