0

I am trying to read in data from a file that is formatted with ;. The data will always be of like this:

char[];int;int%;int

The char[] can have any number of spaces and the % should be disregarded when reading the data.

I am using fscanf() (I am allowed to use only that) for reading the data from the file.
Right now my code for that part of it is:

fscanf(file, "%[^;]%d%d%d", f_name, &f_id, &f_score, &f_section_num) != EOF)

Is there a regex for what I need? Or, how do I correct my fscanf?

mrflash818
  • 930
  • 13
  • 24
MinorMapillai
  • 159
  • 1
  • 10

3 Answers3

2

You can read the file using fscanf with this format string:

"%[^;];%d;%d%%;%d"
  • %[^;]: read up to first ;
  • ;: ignore the ;
  • %d: read one integer
  • ;: ignore the ;
  • %d: read one second integer
  • %%: ignore the %
  • ;: ignore the ;
  • %d: read one third integer

Do not forget to test the number of successful conversions made by fscanf by testing fscanf(...) == 4

So code will looks like:

FILE *f = fopen(...);
char name[64];
int i, integers[3];

while (fscanf(f, "%[^;];%d;%d%%;%d", name, &integers[0], &integers[1], &integers[2]) == 4)
{
    printf("name is %s\n", name);
    for (i = 0; i < 3; ++i)
    {
        printf("i[%d] = %d\n", i, integers[i]);
    }        
}
fclose(f);
Mathieu
  • 8,840
  • 7
  • 32
  • 45
0

The following code will allow you to read data separated by ; from your file:

char msg[100];
int  a;
char b[100];
int  c;

fscanf(fptr, "%[^;];%d;%[^;];%d", msg, &a, b, &c);
printf("%s\n %d\n %d\n %d\n", msg, a, atoi(b), c);
Grant Miller
  • 27,532
  • 16
  • 147
  • 165
Anand
  • 374
  • 2
  • 11
  • This assumes, perhaps unsafely, that no component on the line will exceed 99 characters. – tadman Sep 07 '18 at 21:24
  • 1
    The third field is, I think, meant to be an integer followed by `%`, so `;25%;` or similar. You seem to be treating it as a string, which is only partially correct — you'd have to convert the string to an integer, possibly after validating for a percent symbol at the end. – Jonathan Leffler Sep 07 '18 at 22:00
0

You could, alternatively, use strtok(). If, for example, you use a struct for each entry as follows,

typedef struct {
    char name[64];
    int id, score, section_num;
} entry_t;

the following would read each line of the file as follows.

char line[128] = {'\0'};
char *field = NULL;
entry_t entry;

while (fgets(line, sizeof(line), fp)) {
    field = strtok(line, ";");
    if (!field || strlen(field) > sizeof(entry.name)) continue;
    strcpy(entry.name, field);
    field = strtok(NULL, ";");
    if (!field) continue;
    entry.id = atoi(field);
    field = strtok(NULL, ";%");
    if (!field) continue;
    entry.score = atoi(field);
    field = strtok(NULL, ";");
    if (!field) continue;
    entry.section_num = atoi(field);
    // Do whatever you need with the entry - e.g. print its contents
}

I have removed some necessary boilerplate code for brevity. See http://codepad.org/lg6BJ0hk for a full example.

You can use strtol() instead of atoi() if you need to check the results of the integer conversions.

David Collins
  • 2,852
  • 9
  • 13
  • I tried using this, but I felt it's a bit unnecessary for what I am doing right now. – MinorMapillai Sep 07 '18 at 21:51
  • @Varun.R: It is, admittedly, more long-winded. If you have a solution using `fscanf()`, just go with that I suggest. I think I will leave this answer here anyway, as an alternative. – David Collins Sep 07 '18 at 21:55