-5

Suppose my string is: haha "lol"
I want to extract only lol

#include<stdio.h>

int main() {  
   char a[20]={0};  
   char *s="haha \"lol\"";  
   if(sscanf(s,"%*[^\"]'%[^\"]\"",a)==1){  
      printf("Found stuff inside quotes");
   } 
}
Andre Kampling
  • 5,476
  • 2
  • 20
  • 47
fredj0hnson
  • 21
  • 1
  • 3
  • 2
    And where is the problem? Show us what you have tried and where you got stuck. – diiN__________ Aug 24 '17 at 12:59
  • I tried : #include int main() { char a[20]={0}; char *s="echo \"foobar\"|cat"; if(sscanf(s,"%*[^\"]'%[^\"]\"",a)==1){ printf("printing stuff inside double-quotes"); } } but this doesn't work – fredj0hnson Aug 24 '17 at 13:08
  • I don't suppose suggesting writing actual code to iterate/parse the string would be considered useful:( – Martin James Aug 24 '17 at 13:28

3 Answers3

2

By applying a proper parser for the source language that you are parsing.

One-liners for parsing input are often fragile and hard get right.

That said, you can try with something like

const char *input = "haha \"lol\"";
char quoted[32];

if(sscanf(input, "%*[^\"]\"%31[^\"]\"", quoted) == 1)
{
  printf("got '%s'\n", quoted);
}

This should be hardened but is enough to get you started.

unwind
  • 391,730
  • 64
  • 469
  • 606
  • @chux That's a good point. I won't edit to fix since that was (part of) my point as well. :) Using `strchr()` would probably have been better. – unwind Aug 24 '17 at 13:17
  • thank you! May I ask where can I learn more about the sscanf and line 3? – fredj0hnson Aug 24 '17 at 13:20
  • 1
    @fredj0hnson: Buying a good [C book](https://stackoverflow.com/questions/562303/the-definitive-c-book-guide-and-list). But for quick reference the [manpage of scanf()](https://linux.die.net/man/3/scanf) is good. – Andre Kampling Aug 24 '17 at 13:27
2

Sometimes a little code goes a long way. All that is need is 2 calls to strchr()

extract_quoted_string() changed to pseudo-code.

const char *extract_quoted_string(const char *s, size_t *sz) {
  const char *left = look_for_quote_start_at_s;
  if (failure?) {
    return NULL;
  }
  Update_left_to_the_next_possible_position
  const char *right = look_for_quote_start_at_updated_left;
  if (failure?) {
    return NULL;
  }
  Compute_and_save_size_based_on_left_and_right
  return left;
}

Test harness

void test(const char *s) {
  printf("<%s> --> ", s);
  size_t sz;
  const char *extract =  extract_quoted_string(s, &sz);
  if (extract) {
    printf("<%.*s>\n", (int) sz, extract);

  } else {
    printf("None\n");
  }
}

int main() {
  test("");
  test("123");
  test("\"123");
  test("123\"");
  test("\"123\"");
  test("abc\"123");
  test("abc\"123\"");
  test("123\"xyz");
  test("\"123\"xyz");
  test("abc\"123\"xyz");
}

Expected output

<> --> None
<123> --> None
<"123> --> None
<123"> --> None
<"123"> --> <123>
<abc"123> --> None
<abc"123"> --> <123>
<123"xyz> --> None
<"123"xyz> --> <123>
<abc"123"xyz> --> <123>
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
0

I think that it is enough in the answer by unwind (even if you add code according to requirements)

A question similar to this question already exists.
Split unquoted string in C

When using that approach you can write follows:

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

#define ESCAPE '\\' //ESCAPE CHARACTER

typedef struct token {
    const char *top;
    const char *end;//point to next character
} Token;

Token getToken(const char **sp, char sep){
    const char *s = *sp;
    const char *top, *end;
    Token token = { NULL, NULL};

    while(*s && *s == sep)//skip top separators
        ++s;
    if(!*s){
        *sp = s;
        return token;
    }
    token.top = s;
    while(*s && *s != sep){
        if(*s == ESCAPE)
            ++s;
        else if(*s == '"'){
            char *p = strchr(s + 1, '"');//search end '"'
            while(p && p[-1] == ESCAPE)
                p = strchr(p + 1, '"');
            if(p)
                s = p;
        }
        ++s;
    }
    token.end = s;
    *sp = s;

    return token;
}

char *remove_escape(char *s){
    char *from, *to;
    from = to = s;
    while(*from){
        if(*from != ESCAPE)
            *to++ = *from;
        ++from;
    }
    *to = 0;
    return s;
}

char *ft_strsub(Token token){
    size_t len = token.end - token.top;
    char *sub = malloc(len + 1);//check return value
    if (sub){
        memcpy(sub, token.top, len);
        sub[len] = 0;
    }
    return sub;
}

int main(int argc, char **argv){
    char *str = NULL;  
    const char *s="haha \"lol\"";  

    Token token = getToken(&s, ' ');

    while(token.top != NULL){
        str = ft_strsub(token);
        remove_escape(str);
        if(*str == '"')//find it!
            break;
        free(str);
        token = getToken(&s, ' ');
    }
    if(str){
        printf("Found stuff inside quotes: ");
        //remove "
        size_t len = strlen(str);
        str[len-1] = 0;
        printf("'%s'\n", str + 1);//ignore first character or use memmove
        free(str);
    }

    return 0;
}
BLUEPIXY
  • 39,699
  • 7
  • 33
  • 70