2013-11-28 3 views
1

У меня есть следующая строка:C строка парсер внутри другого синтаксического анализатора

GET /index.html HTTP/1.0;;User-Agent: Wget/1.11.4;;Accept: */*;;Host: www.google.com;;Connection 

Я использую следующий код для разбора каждого элемента:

while (parser != NULL){ 
     printf ("%s\n",parser);   
     parser = strtok (NULL, ";;"); 
    } 

Это выходы:

GET /index.html HTTP/1.0 
User-Agent: Wget/1.11.4 
Accept: */* 
Host: www.google.com 
Connection 

сейчас Мне нужно только получить веб-адрес хоста, который в этом случае - www.google.com. Поэтому сначала я хочу отделить его от других вещей.

Для этого я поставил другой анализатор в моей предыдущей, так как:

while (parser != NULL){ 
     char * pars = strtok (string,":"); 
     while (pars != NULL) { 
      printf("%s\n", pars); 
      pars = strtok (NULL, ":"); 
     } 
     parser = strtok (NULL, ";;"); 
    } 

Выход это некоторые перепутались вещи. Я не понимаю, почему ... Может ли кто-нибудь увидеть ошибку? Спасибо

ответ

4

Причина, по которой ваш код не работает, заключается в том, что strtok не является реенрантным. Поскольку функция использует статические переменные для сохранения состояния (это то, что позволяет вызывать strtok с NULL в качестве первого параметра), вы не можете настроить вызовы strtok в вложенных циклах: после того, как вы сообщите strtok для разбора с разделителем ":", он «забывает», состояние разбора с разделителем ";".

Переключение на повторную версию strtok - strtok_r, исправит эту проблему. Эта функция требует, чтобы вы предоставили дополнительный параметр, savePtr. Важно: вам нужно указать две разные переменные для вашего savePtr для strtok_r во внутренней и внешней петлях, иначе код будет иметь такое же поведение.

Примечание: strtok_r не является частью стандарта C. Однако большинство популярных библиотек C делают его доступным. Если ваша библиотека не имеет strtok_r, найдите исходный код и добавьте ее в свою собственную базу кода.

+0

Я знал, что «strtok» столкнулся с этой проблемой: я не знал о версии повторного входа. – Floris

+0

Обратите внимание, что 'strtok_r' не является C-стандартным (но POSIX). – Kninnug

+0

@Kninnug Это правда. Я добавил примечание, чтобы упомянуть об этом. Спасибо! – dasblinkenlight

0

Существует большая проблема с вашим подходом - помимо вопроса strtok, не являющегося повторным участником. То есть strtok ищет «матч с любым токеном» - так strtok(NULL, ";;") остановится при первом ;, а не в первом ;;.

Я бы пошёл по-другому - вы ищете определенную строку ("\nHost: ") - ищите это, затем найдите бит, который следует за ним. Это похоже на более надежное решение.

отметить также, что strtok изменяет свой аргумент - в основном это добавит '\0', где он находит маркер, так что вы не сможете повторно использовать строку после того, как она манипулирует strtok. Если вы хотите использовать строку позже, сначала нужно сделать копию.

Все, что предполагает, что вы хотите пересмотреть свою стратегию синтаксического анализа. Как насчет

char * inputString = "GET /index.html HTTP/1.0 ;; User-Agent: Wget/1.11.4 ;; Принять: / ;; Host: www.google.com ;; Connection "; char * temp, * hostString, * endHost; temp = strstr (inputString," ;; Host: ") + 7; // точка сразу после" Host: " endHost = strstr (temp, ";;"); NCHAR = (INT) (endHost - темп) + 1; hostString = таНос (NCHAR); зЬгсру (hostString, темп, NCHAR);

Это просто, чтобы найти/извлечь host string.

Смежные вопросы