-1

I have a program that processes calendar date type structures (day, month , year). How can I read the content of a file, regardless of the number of records in it?. at the moment, my code only reads the number of records I send as a parameter, which is not exactly correct and useful.

This is my function

void readN(struct data *element,int n){
    FILE *data_file;
    data_file = fopen("D:\\univer\\sem2\\tehProg\\struct_and_files\\data.txt","r");
    if(data_file == NULL){
        fprintf(stderr, "Unable to open file\n");
        return;
    }
    for (int i = 0; i < n; i++) {
        if (fscanf(data_file,"%d %d %d", &element[i].d, &element[i].m, &element[i].y) != 3){
            fprintf(stderr, "Incomplete input!!!\n");
            break;
        }
    }
    fclose(data_file);
}
int main() {

   struct data dd1[4];
    readN(dd1,4);

    return 0;
}

data.txt content

10 10 2001
1 1  2002
14 3 2004
18 4 2022
17 10 2002
kammy
  • 93
  • 8
  • 2
    What is the fomat of the file, precisely? Is it just DD MM YYYY space-separated ? – carce-bo Apr 28 '22 at 06:08
  • 2
    Please [edit] your question to include the first few lines of the file `data.txt`. – Some programmer dude Apr 28 '22 at 06:10
  • 1
    Did you try using the return value of your scan in a loop condition? You are aware of its use for finding errors, it can also find the end of file. I think `while (...==3)` might already do the trick... – Yunnosch Apr 28 '22 at 06:18
  • @carce-bo yes, dd mm yyyy – kammy Apr 28 '22 at 06:19
  • I recommend you use `fgets` to read whole lines, and `sscanf` to attempt to parse each line. That way it's much easier to keep track of the current line you're reading (it's a simple counter variable that you increase after each successful `fgets` call). When you get an error parsing the input, you can then easily print the line number where the problem is. You can also print the actual contents of the failing line. – Some programmer dude Apr 28 '22 at 06:31
  • If you want to read *all* records, not only a fixed amount, then you can't use fixed-sized arrays. You need dynamic allocation and *reallocation* as you read and parse the file contents. Your text-book should have chapters about that. – Some programmer dude Apr 28 '22 at 06:49
  • @Someprogrammerdude the idea is that I would like to read all the values in the file, regardless of their number, yes – kammy Apr 28 '22 at 06:54
  • @Someprogrammerdude I used such a construction,: struct data *dd1; dd1 = (struct data *)malloc(5*sizeof (struct data)); but here there are 5, I should use an N, but I do not know its value – kammy Apr 28 '22 at 07:00
  • That's where the *reallocation* comes in. Begin by reading one line and parsing it (into temporary variables). If that's successful use `realloc` to allocate (or reallocate) `n + 1` elements, where `n` is initialized to `0` and increased each iteration of the loop. – Some programmer dude Apr 28 '22 at 07:02
  • @Someprogrammerdude Can you please write this in code form?, I do not understand very well + I have not worked with dynamic allocation and do not know how to use – kammy Apr 28 '22 at 07:04
  • I suggest investing in [a couple of decent text books](https://stackoverflow.com/questions/562303/the-definitive-c-book-guide-and-list). They should have chapters about dynamic allocation (which is an integral part of C and many advanced C programs). Do the exercises from the books. In short, I think it's better you learn yourself by doing it yourself, not by copy-pasting ready code. – Some programmer dude Apr 28 '22 at 07:10
  • @Someprogrammerdude I appreciate that, but, temporarily, I can't look at these resources. and there's another problem, I'm not an English speaker and I don't understand many things – kammy Apr 28 '22 at 07:12

1 Answers1

0

In pseudo code it could be something like this:

struct data *elements = NULL;

char line[SOME_GOOD_SIZE];
int n = 0;

while (fgets(line, sizeof line, file))
{
    int y, m, d;
    if (parse_line(line, &y, &m, &d))
    {
        elements = reallocate(elements, n + 1);

        elements[n].d = d;
        // etc...

        ++n;
    }
}

Once finished you have either read all lines from the file (or ended early if there was an error, you need to handle that), and you can return the pointer elements from the function.

Read more about the realloc function and what it does. Pay close attention to what it returns, and what the arguments really are.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • You just stuck me harder than I was, Buddy)))))))))))) – kammy Apr 28 '22 at 07:23
  • I think I have implemented what you wrote above, but I still have a blur. How should I change the code in int main() ? – kammy Apr 28 '22 at 07:39
  • This is what it looks like now struct data *dd1; dd1 = (struct data *)malloc(sizeof (struct data)); Is that right? – kammy Apr 28 '22 at 07:42