1

I need to scan values from .txt to a structure so I can work further on with my program. I've been trying various methods from the thread and this is the closes I got to a successful build.

I can NOT get the values to be printed out so I can test if they scanned correctly before working my way further into the program.

I have different values in struct:

struct knyga
{
    char vardas[10];
    char pavadinimas[50];
    int metai;
    double kaina;
};

and this is my reading function:

void Skaitymas(struct knyga arr_knyga[]){
FILE *fp;

fp = fopen("duomenys.txt", "r");
int skaicius;
int txt;
txt = fgetc(fp);

while((txt = fgetc(fp)) != EOF){
    if(txt == '\n') skaicius++;
        txt = fgetc(fp);
}
printf("%d", skaicius);

fp = fopen("duomenys.txt", "r");


for(int i = 0; i < skaicius; i++){
    fscanf(fp, "%s %s %d %lf", arr_knyga[i].vardas, arr_knyga[i].pavadinimas, &arr_knyga[i].metai, &arr_knyga[i].kaina);
 }
fclose(fp);

}

EDIT:

This is the content of my text file:

Onute Knyga 1999 12.12
Petras Knygute 2001 9.99

EDIT 2:

my main function:

int main() {
    
    
    struct knyga arr_knyga[10];
    
    Skaitymas(arr_knyga);
    
    return 0;
}
Upsice
  • 23
  • 6
  • 2
    [Why is “while ( !feof (file) )” always wrong?](https://stackoverflow.com/questions/5431941/why-is-while-feof-file-always-wrong) – Rohan Bari Dec 20 '20 at 14:40
  • 1
    Use `int txt; while((txt = fgetc(fp)) != EOF) { if(txt == '\n') skaicius++; }` Most C library functions use `int` not `char` for a character. – Weather Vane Dec 20 '20 at 14:44
  • @WeatherVane thank you for the int tip, but after I try and printf the "skaicius" which should be 2, because that is the amount of lines I have in my text file, it gives 1 instead. – Upsice Dec 20 '20 at 14:51
  • If you want to parse the values from `fp` you have to use `fscanf` instead of `scanf`. Check the return code of `fscanf` (see the documentation) and use `feof` and `ferror` afterwards to find out if end-of-file is reached or if an error occurred.. You don't need to count the lines first. – Bodo Dec 20 '20 at 14:52
  • Please show the contents of the input file in your question. If you modified your program as suggested in a comment, please [edit] your question and add the modified code and the corresponding output. – Bodo Dec 20 '20 at 14:53
  • Added the .txt file content and edited the void function by a recommendation. @Bodo – Upsice Dec 20 '20 at 14:59
  • Does the last line of the input file end with `'\n'`? Please show the output of `od -c duomenys.txt` – Bodo Dec 20 '20 at 15:05
  • Show how you call `Skaitymas` and how the array is defined. The function `Skaitymas` does not know the size of the array and cannot check for possible out-of-bounds access. – Bodo Dec 20 '20 at 15:07
  • @Bodo The input file is exactly as I pasted it. Added my main function too. I assume that struct knyga arr_knyga[10]; will have 11 lines maximum. – Upsice Dec 20 '20 at 15:11
  • @Upsice The problem is that "exactly as you pasted it" does not tell if the last line ends with a newline character or not. That's why I suggested a command that would make this clear. If you declare the array as `arr_knyga[10]` your function `Skaitymas` must not try to store more than 10 data records. – Bodo Dec 20 '20 at 15:22

1 Answers1

1

You call txt = fgetc(fp); too often. The two occurrences of this line must be removed.

Especially in the loop you have one call to fgetc that is checked for '\n' and a second call that is not checked, so there is a 50%/50% chance that a '\n' is not counted.

You forgot to initialize the counter variable.

The counting would be correct with this version:

void Skaitymas(struct knyga arr_knyga[]){
    FILE *fp;

    fp = fopen("duomenys.txt", "r");
    int skaicius = 0;
    int txt;

    while((txt = fgetc(fp)) != EOF){
        if(txt == '\n') skaicius++;
    }
    printf("%d", skaicius);

    fclose(fp);
}

But it would be better to omit the line-counting and detect the end-of-file condition in the fscanf loop.

void Skaitymas(struct knyga arr_knyga[]){
    FILE *fp;

    fp = fopen("duomenys.txt", "r");
    int skaicius = 0;
    int rc;

    while(1)
    {
        rc = fscanf(fp, "%s %s %d %lf", arr_knyga[skaicius].vardas, arr_knyga[skaicius].pavadinimas, &arr_knyga[skaicius].metai, &arr_knyga[skaicius].kaina);
        if(rc == 4)
        {
           skaicius++;
        }
        else
        {
            break;
        }
    }
    if(!feof(fp))
    {
        fprintf(stderr, "error reading file or wrong data after line %d\n", skaicius);
    }
    else
    {
        printf("%d", skaicius);
    }
    fclose(fp);
}
Bodo
  • 9,287
  • 1
  • 13
  • 29