0

I needed to know when there was no data between two delimiters so I found the following code on Stack Overflow.

char *strtok_single (char * str, char const * delims)
{
  static char  *src = NULL;
  char  *p,  * ret = 0;

  if (str != NULL)
    src = str;

  if (src == NULL)
    return NULL;

  if ((p = strpbrk (src, delims)) != NULL) {
    *p  = 0;
    ret = src;
    src = ++p;

  } else if (*src) {
    ret = src;
    src = NULL;
  }

  return ret;
}

Sampling the function

char delims[] = ",";
char data  [] = "foo,bar,,baz,biz,,";

char *p = strtok_single(data, delims);

while (p) {
  printf ("%s\n", *p ? p : "<empty>");

  p = strtok_single (NULL, delims);
}

Output

foo                                                                                                                                                                                
bar                                                                                                                                                                                
<empty>                                                                                                                                                                            
baz                                                                                                                                                                                
biz                                                                                                                                                                                
<empty>
// missing another <empty>

With the current code, it does not process data after the last ',' There should be one more empty field. I am unsure how to get the correct output.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Ayelir
  • 41
  • 1
  • 1
  • 6
  • 1
    Why aren't you actually using `strtok()`? – tadman Feb 23 '21 at 02:45
  • 1
    Tip: Function calls usually have a syntax like `f(...)` with no space, while constructs like `if` or `while` get special treatment so they stand out, as in `if (...)` or `while (...)` with a space. Spacing out your function calls makes them look broken. – tadman Feb 23 '21 at 02:46
  • 1
    @tadman It collapses multiple consecutive delimiters. – dbush Feb 23 '21 at 02:46
  • You can do that by wrapping around `strtok()` if you prefer. There's no need to reinvent `strtok()`. Just have it skip a token if you get a zero length result. – tadman Feb 23 '21 at 02:46
  • Using strtok when there is no data between two delimiters such as ",," it will count it as a single token. I need to know that there is no data there as I am assigning values to them. – Ayelir Feb 23 '21 at 02:47
  • From whence cometh your code for `strtok_single()`? Is it [SO 3029-4129](https://stackoverflow.com/q/30294129/15168)? Should you not say so? – Jonathan Leffler Feb 23 '21 at 03:17
  • If you have strsep, use it instead of strtok. That's what it's for. If you don't have it, there are open-source implementations available. – rici Feb 23 '21 at 03:18
  • 1
    @tadman: Probably because `strtok()` treats multiple consecutive separator characters as a single delimiter, rather than as separating multiple fields. And no, you can't just wrap `strtok()` to get the effect. You might be able to use `strsep()` instead — but that's just as much a non-standard function as `strtok_single()`. – Jonathan Leffler Feb 23 '21 at 03:19
  • @JonathanLeffler edited post to show where I got code – Ayelir Feb 23 '21 at 03:22
  • 1
    OK; that's a different SO question (SO 0870-5844) from what I suggested. Try looking at SO 3029-4192; it might help. Also, do look at `strsep()`. I have a chunk of test code kicking around which I wrote in response to a question (on SO) that I can no longer identify, so it probably got deleted. It shows `strsep()` at work, and it can report on the empty field at the end of the string `",abc,def,,ghi,"` (and the one at the beginning) when the delimiter is `,`. That seems to be what you're after, is it not? You could look at [SO 5824-4300](https://stackoverflow.com/q/58244300/15168) too. – Jonathan Leffler Feb 23 '21 at 03:28
  • @JonathanLeffler Yes, that is what im looking for. I will take a look at those. Thank you – Ayelir Feb 23 '21 at 03:31

1 Answers1

2

You should use strsep instead of strtok. Indeed, strsep supports empty fields: See this answer

Here is an example:

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

int main () {
        char delims[] = ",";
        char data  [] = "foo,bar,,baz,biz,,";
        char *p = strdup(data);
        char * tok;
        while ((tok = strsep(&p, delims)) != NULL) {
                printf ("%s\n", *tok ? tok : "<empty>");
        }
        free(p);
        return 0;
}

The ouput:

foo
bar
<empty>
baz
biz
<empty>
<empty>
tadman
  • 208,517
  • 23
  • 234
  • 262
ThunderPhoenix
  • 1,649
  • 4
  • 20
  • 47
  • This seems to be the correct solution. However, on the code Im working on my data is a csv file and for some reason, the while loop isn't evaluating as true when the data is coming from a csv file, but I might have others issues idk. – Ayelir Feb 23 '21 at 03:59
  • @Ayelir: note that a CSV file can, in general, also have quoted fields, and those quoted fields might contain commas. For example, `"abc,\"def,ghi\",jkl"` is a C string containing 3 fields in a CSV format. The middle field is enclosed in quotes and contains `"def,ghi"`. Without seeing your data, it is hard to know whether this is actually your problem, but you should be aware of the issue. – Jonathan Leffler Feb 23 '21 at 04:05
  • Thank you for the tip. The issue with my code wasn't actually the csv. I wasn't updating the ptr with each line being read from the file. – Ayelir Feb 23 '21 at 04:31