Search code examples
cstringpointer-arithmeticstrchr

Advance pointer and get 2 more characters after strchr in C


I'm trying to get 2 more characters after finding the first occurrence with strchr over a char pointer. The string can look like:

foo;bar;2012 -> should output foo;b
foo;caz;     -> should output foo;c
foo;         -> should output foo (there are no +2 chars)
foo          -> null

For the first case, I figure I can do something like,

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

int main ()
{
  char str[] = "foo;bar;2012";
  char *pch = NULL;

  if ((pch=strchr(str,';')) != NULL) {
    *pch++;
    *pch++;
    *pch = '\0';
  }
  puts(str);
  return 0;
}

But what's the proper way of checking if I can advance the pointer within the string without going over?


Solution

  • The *pch++ lines should be generating a compiler warning (if they don't, you aren't compiling with enough warnings enabled). I compile with warnings treated as errors so I get:

    xw31.c:10:5: error: value computed is not used [-Werror=unused-value]
         *pch++;
    

    You should use pch++; — that doesn't read but ignore the value.

    You should check that you've not reached end of string while accessing beyond where strstr() points you, so could use:

    #include <stdio.h>
    #include <string.h>
    
    int main(void)
    {
        char str[] = "foo;bar;2012";
        char *pch;
    
        if ((pch = strchr(str, ';')) != NULL)
        {
            if (pch[1] != '\0' && pch[2] != '\0')
                pch[3] = '\0';
            puts(str);
        }
        return 0;
    }
    

    If the inner test fails, the string is short enough already. pch[0] is the semicolon, of course. This generates foo;ba as the output. If you want just foo;b, then you only need to test one character less ahead:

    #include <stdio.h>
    #include <string.h>
    
    int main(void)
    {
        char str[] = "foo;bar;2012";
        char *pch;
    
        if ((pch = strchr(str, ';')) != NULL)
        {
            if (pch[1] != '\0')
                pch[2] = '\0';
            puts(str);
        }
        return 0;
    }