0

Is there a simple way to use fscanf or fgets in C to simulate this behaviour:

Suppose I have a file which is structured like this:

Integer \t String \t double

Integer \s String \s double

Is there a way I can apply fscanf in this situation to input it in a struct?

I have tried using multiple regular expressions in my fscanf and I have failed to accomplish what I need to do.

I would want the struct to look like this:

struct foo {
    int first;
    char * second;
    double third;
};

and then fscanf in those 3 elements.

  • 2
    `fscanf()` does not accept regular expressions. Read the whole line with `fgets()`, then parse it into the struct members. Remember to `malloc()` memory for the string! – pmg Apr 26 '14 at 16:49
  • Even in C++ you'd have to write a function to do this, so just write a function to input your struct data (and be sure to allocate some space to `second`). – ooga Apr 26 '14 at 16:51
  • Ah, thanks, could you tell me what the name of those conditions in scanf are, say: `scanf ("%[^\n]", str);` –  Apr 26 '14 at 16:52
  • 1
    @Frows: those conversions (the ones starting with `"%["`) are called *scanlists* ( or *scansets*). – pmg Apr 26 '14 at 17:15

1 Answers1

2

This is how you would use fscanf to read in the data for your struct.

struct foo Foo;
Foo.second = malloc(10); // max string size
fscanf(fp, "%d %s %lf", &Foo.first, Foo.second, &Foo.third);

Where fp is a FILE* to your opened file.

Note that %s will only scan a string up to the next whitespace character. If you want to include whitespace characters as part of the string then you will need to redefine how your delimiter works and probably use RegEx or write your own parsing function.

For future reference, the documentation on how to use fscanf() can be found here. This includes all the scan strings and how they work.

Daniel
  • 1,920
  • 4
  • 17
  • 35
  • You'd need to initialize `second` first. – sepp2k Apr 26 '14 at 16:59
  • Thanks, I just caught that myself. – Daniel Apr 26 '14 at 17:00
  • Wow, I've overcomplicated this way too much, this worked, thanks. –  Apr 26 '14 at 17:02
  • This would only work if the string contained no spaces, also. – Crowman Apr 26 '14 at 17:02
  • @PaulGriffiths Yes but that is implied by Frows description of the input `Integer \s String \s double`. I assume he wouldn't knowingly use space as a delimiter and still assume he could use it in the string. – Daniel Apr 26 '14 at 17:03
  • Well, if he's representing that as a regular expression, the spaces aren't really "delimiters". A greedy regex match would pick up the whole string, spaces and all, as along as there was a space after the integer and before the double. – Crowman Apr 26 '14 at 17:05
  • @PaulGriffiths That is true, I did not think about it in the context of RegEx. I'll edit the answer. – Daniel Apr 26 '14 at 17:09
  • Regarding casting the result of `malloc()` - you might find ***[THIS](http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc)*** interesting. – ryyker Apr 26 '14 at 17:32
  • @ryyker That post is rather interesting. I've been doing a lot of C++ lately which is why I thought the cast was necessary (or I thought it would at least cause a warning when compiled with -Wall in C). I think I will remove the cast in light of that post. – Daniel Apr 26 '14 at 17:49