Как найти подстроку между кавычками в C

Если у меня есть строка, такая как строка, которая является командой

эхо 'foobar'|кошка

Есть ли хороший способ получить текст между кавычками ("foobar")? Я читал, что можно было использовать scanf, чтобы сделать это в файле, это также возможно в памяти?

Моя попытка:

  char * concat2 = concat(cmd, token);
  printf("concat:%s\n", concat2);
  int res = scanf(in, " '%[^']'", concat2);
  printf("result:%s\n", in);

person Niklas R.    schedule 24.04.2016    source источник
comment
cplusplus.com/reference/cstdio/sscanf   -  person Michael Albers    schedule 24.04.2016
comment
@Я рад, что ты понял вопрос. Я решил использовать sscanf .   -  person Niklas R.    schedule 25.04.2016


Ответы (3)


Если ваша строка имеет этот формат -"echo 'foobar'|cat", можно использовать sscanf-

char a[20]={0};
char *s="echo 'foobar'|cat";
if(sscanf(s,"%*[^']'%[^']'",a)==1){
   // do something with a
} 
else{
 // handle this condition 
}

%*[^'] будет читать и отбрасывать строку до тех пор, пока не встретит одинарную кавычку ' , второй спецификатор формата %[^'] будет читать строку до ' и сохранять ее в a.

person ameyCU    schedule 24.04.2016
comment
Хороший ответ! Однако он не устанавливает a в NULL, если он не найден или что-то в этом роде. Как насчет char a[20] = {0};? :) Кроме того, в случае, если он найдет то, что мы ищем, sscanf() позаботится о \0? - person gsamaras; 24.04.2016
comment
@gsamaras Инициализация была бы хорошей, а также следует выполнить проверку sscanf. - person ameyCU; 24.04.2016
comment
Точно! Ваш ответ более элегантный, но я оставлю свой в качестве альтернативы. +1. - person gsamaras; 24.04.2016
comment
@gsamaras Да, внес изменения. :) - person ameyCU; 24.04.2016
comment
Мне нравится решение, но что, если строка начинается с одинарной кавычки (например, char *s="'foobar'|cat";) Исходное подавление присваивания терпит неудачу (что приводит к совпадению с остальной частью строки формата). Я пробовал несколько альтернатив и не могу найти ту, которая работает в обоих случаях. Есть ли у вас какие-либо предложения для строки формата, которая будет работать независимо от того, является ли первый символ одинарной кавычкой? - person David C. Rankin; 25.04.2016

Используйте strtok() один раз, чтобы найти первое вхождение разделителя, которое вы хотите (' в вашем случае), а затем еще раз, чтобы найти конечную пару, например:

#include <stdio.h>
#include <string.h>

int main(void) {
  const char* lineConst = "echo 'foobar'|cat"; // the "input string"
  char line[256];  // where we will put a copy of the input
  char *subString; // the "result"

  strcpy(line, lineConst);

  subString = strtok(line, "'"); // find the first double quote
  subString=strtok(NULL, "'");   // find the second double quote

  if(!subString)
    printf("Not found\n");
  else
    printf("the thing in between quotes is '%s'\n", subString);
  return 0;
}

Выход:

между кавычками написано "foobar"


Я основывался на этом: Как извлечь подстроку из строки в C ?

person gsamaras    schedule 24.04.2016
comment
Было бы достойно голосования, если бы не было посторонних символов \, вставленных как в исходную строку, так и в токены поиска strtok. Я утверждаю, что они ничего не делают, чтобы помочь делу, а только запутывают его. Конечно, если исходная строка была echo "foobar"|cat, я согласен через секунду. Но это не так. Нет ничего, от чего нужно убегать. На самом деле мне довольно любопытна ваша мотивация добавить их в этом случае. - person enhzflep; 24.04.2016
comment
@enhzflep спасибо за это, я улучшил свой ответ, теперь он лучше? :) Сначала я тестировал двойные кавычки (которые требуют экранирования) и планировал удалить экранирование для одинарных кавычек, но затем появился ответ ameyCU, и я попался на этом. - person gsamaras; 24.04.2016
comment
Пожалуйста. Я думаю, что да, хотя я всего лишь один человек. Вы уже получили мой голос за него. (шучу--›) У меня где-то есть трофей, на котором написано, что меня легко отвлечь, я отвлекаюсь каждый раз, когда ищу его.. :смеется: - person enhzflep; 24.04.2016
comment
@enhzflep, ха-ха, один человек с твоим представителем много значит. :) Надеюсь, это поможет ОП! - person gsamaras; 24.04.2016

Существует большое количество подходов к проблеме. От обхода пары указателей вниз по строке для поиска разделителей и большого количества строковых функций, предоставляемых в string.h. Вы можете использовать функции поиска символов, такие как strchr, или функции поиска строк, такие как strpbrk, вы можете использовать функции токенизации, такие как strtok и т. д.

Посмотрите и учитесь у них всех. Вот реализация с strpbrk и разницей указателей. Это неразрушающий метод, поэтому вам не нужно делать копию исходной строки.

#include <stdio.h>
#include <string.h>

int main (void) {

    const char *line = "'foobar'|cat";
    const char *delim = "'";        /* delimiter, single quote */
    char *p, *ep;

    if (!(p = strpbrk (line, delim))) { /* find the first quote */
        fprintf (stderr, "error: delimiter not found.\n");
        return 1;
    }
    p++;                        /* advance to next char */
    ep = strpbrk (p, delim);    /* set end pointer to next delim */

    if (!p) {   /* validate end pointer */
        fprintf (stderr, "error: matching delimiters not found.\n");
        return 1;
    }

    char substr[ep - p + 1];        /* storage for substring */
    strncpy (substr, p, ep - p);    /* copy the substring */
    substr[ep - p] = 0;             /* nul-terminate */

    printf ("\n single-quoted string : %s\n\n", substr);

    return 0;
}

Пример использования/вывода

$ ./bin/substr

 single-quoted string : foobar

Без использования string.h

Как упоминалось выше, вы также можете просто пройти пару указателей вниз по строке и таким же образом найти свои пары кавычек. Для полноты приведем пример поиска нескольких строк в кавычках в одной строке:

#include <stdio.h>

int main (void) {

    const char *line = "'foobar'|cat'mousebar'sum";
    char delim = '\'';
    char *p = (char *)line, *sp = NULL, *ep = NULL;
    size_t i = 0;

    for (; *p; p++) {                /* for each char in line */
        if (!sp && *p == delim)             /* find 1st delim */
            sp = p, sp++;                   /* set start ptr  */
        else if (!ep && *p == delim)        /* find 2nd delim */
            ep = p;                         /* set end ptr    */
        if (sp && ep) {                     /* if both set    */
            char substr[ep - sp + 1];       /* declare substr */
            for (i = 0, p = sp; p < ep; p++)/* copy to substr */
                substr[i++] = *p;
            substr[ep - sp] = 0;            /* nul-terminate  */

            printf ("single-quoted string : %s\n", substr);
            sp = ep = NULL;
        }
    }

    return 0;
}

Пример использования/вывода

$ ./bin/substrp
single-quoted string : foobar
single-quoted string : mousebar

Просмотрите все ответы и дайте нам знать, если у вас есть какие-либо вопросы.

person David C. Rankin    schedule 24.04.2016