LINUX.ORG.RU

Си разделить строку на токены с учетом кавычек

 ,


0

1

Здравствуйте! Есть замечательная функция: strtok(). С помощью нее я могу разделить строку на токены. Но при этом, все что в кавычках, не будет считано как один токен.

echo "123 12"
Вот результат:
echo, "123, 12"
А мне нужно, что бы все что в кавычках, считывалось как один токен. Как это сделать?



Последнее исправление: egordorichev (всего исправлений: 1)

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

anTaRes ★★★★
()
Ответ на: комментарий от post-factum

Сгустим краски:

strtok:

НАЙДЕННЫЕ ОШИБКИ
Никогда не используйте эти функции.

strsep:

НАЙДЕННЫЕ ОШИБКИ
Эта функция испытывает некоторые проблемы с функцией strtok(). В частности, она изменяет исходную строку. Избегайте ее использование.

anonymous
()

Lex и Yacc тебе в помощь. Там это довольно таки элементарно.

UPD: par example

beastie ★★★★★
()
Последнее исправление: beastie (всего исправлений: 1)
Ответ на: комментарий от egordorichev

как-то так

#include <stdio.h>

const char *sep(const char *str) {
  int state = 0;
  while (1) {
    switch (state) {
      case 0:
        switch (*str) {
          case '"':
            state = 1;
            break;

          case ',': return str + 1;

          case '\0': return str;
        }
        break;

      case 1:
        switch (*str) {
          case '"':
            state = 0;
            break;

          case '\0': return NULL;
        }
        break;
    }
    str++;
  }
}

int main(int argc, char *argv[]) {
  const char *str = argv[1];
  while (1) {
    const char *next = sep(str);
    if (!next) {
      printf("Parse error\n");
      break;
    } else {
      int len = (int) (*next ? next - str - 1 : next - str);
      printf("%.*s\n", len, str);
    }
    if (!*next) break;
    str = next;
  }
}
Legioner ★★★★★
()

В библиотеке OSSP str (неподдерживаемой и бажной) есть удобная функция для этого - str_token(), она вполне годная. Умеет также экранирования и комменты.

Sorcerer ★★★★★
()
Ответ на: комментарий от anonymous

Для erlang не спорю. Но ты ведь не думаешь, что существует язык - «серебряная пуля»?

anonymous
()

re2c! Основной код в том странном «комментарии» /*re2c ... */.

#include <stdio.h>

// $ re2c -o main.c main.re && gcc main.c -o foo && ./foo '123 3.5 "hello world" bye'

static void pp_token (const char * t_start, const char * t_end)
{
    int t_len = t_end - t_start;
    printf ("TOKEN: '%.*s'\n", t_len, t_start);
}

int main(int argc, char * argv[]) {
    if (argc != 2) return 1;

    const char * p = argv[1];

    for (;;) {
        const char * token = p;
        const char * m;

        /*!re2c
           re2c:define:YYCTYPE  = char;
           re2c:define:YYCURSOR = p;
           re2c:define:YYMARKER = m;
           re2c:yyfill:enable   = 0;

           QSTR = "\x22" [^"\x00]+ "\x22";
           VAL  = [^ "\x00]+;

           QSTR | VAL { pp_token(token, p); continue; }
           " "+       { continue; }
           "\x00"     { break; }
           *          { fprintf (stderr, "ERROR: Bad input at: '%s'\n", token); return 1; }
         */
    }

    return 0;
}

Работает так:

$ ./foo '123 3.5 "hello world" bye'
TOKEN: '123'
TOKEN: '3.5'
TOKEN: '"hello world"'
TOKEN: 'bye'
$
$ ./foo '123 3.5 "hello world'
TOKEN: '123'
TOKEN: '3.5'
ERROR: Bad input at: '"hello world'

sf ★★★
()
Ответ на: комментарий от anonymous

Достаточно сохранить указатель перед её вызовом.

post-factum ★★★★★
()
size_t toklen(char *s) {
  char *term;
  term=s+strcspn(s,"\",");
  while ('\"'==*term) {
     term+=1+strcspn(term+1,"\"");
     term+=1+strcspn(term+1,"\",");
  }
  return term-s;
}
MKuznetsov ★★★★★
()
Последнее исправление: MKuznetsov (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.