1

I wrote this C function because I still study in university and I am studying files currently and this code is running a infinite loop while I go to case 1 in switch case

void input() {
    int hasil[1];
    int tambah[1];
    int i;
    int z = 0;
    int a;
    int c = 0;
    wDATA = fopen("Data.txt", "a");
    rDATA = fopen("Data.txt", "r");
    wDATAs = fopen("DataS.txt", "a");

    while (fscanf(rDATA, "%[^;];%[^;];%[^;];%[^;];%[^;];%[^\n]\n", operator[z], mode[z], jenis[z], jumlah[z], rak[z], tanggal[z]) != EOF) {
        printf("test");
        z++;
    }

    printf("======= Input Barang =======\n");
    printf("Jenis Barang \t\t: ");
    scanf("%s", &jeniss);

    for (i = 0; i < z; i++) {
        if (strstr(strupr(jeniss), jenis[i])) {
            printf("Jumlah barang \t\t: ");
            scanf("%i", &tambah[0]);
            hasil[0] = jumlah[i][0] + tambah[0];
            jumlah[i][0] = hasil[0];
            printf("Tempat penyimpanan \t: ");
            scanf("%s", &rak[i]);
            fprintf(wDATAs, "%s;", operator);
            fprintf(wDATAs, "%s;", mode[i]);
            fprintf(wDATAs, "%s;", jenis[i]);
            fprintf(wDATAs, "%i;", jumlah[i]);
            fprintf(wDATAs, "%s;", rak[i]);
            fprintf(wDATAs, "%s", __DATE__);
            fprintf(wDATAs, "%s", __TIME__);
        }
        else {
            fprintf(wDATAs, "%s;", operator);
            fprintf(wDATAs, "%s;", mode[i]);
            fprintf(wDATAs, "%s;", jenis[i]);
            fprintf(wDATAs, "%i;", jumlah[i]);
            fprintf(wDATAs, "%s;", rak[i]);
            fprintf(wDATAs, "%s;", tanggal[i]);
        }

        remove("Data.txt");
        rename("DataS.txt", "Data.txt");
        c = 1;
    }

    if (c == 0) {
        printf("Jenis Barang \t\t: ");
        scanf("%s", jenis[a]);
        printf("Jumlah barang \t\t: ");
        scanf("%s", jumlah[a]);
        printf("Tempat penyimpanan \t: ");
        scanf("%s", rak[a]);
        fprintf(wDATA, "Input Barang;");
        fprintf(wDATA, "%s;", strupr(jenis[a]));
        fprintf(wDATA, "%s;", jumlah[a]);
        fprintf(wDATA, "%s;", rak[a]);
        fprintf(wDATA, "%s", __DATE__);
        fprintf(wDATA, " %s\n", __TIME__);
        a = a + 1;
    }

    fclose(wDATA);
    fclose(wDATAs);
    fclose(rDATA);
}

*I print test in while loop because I want to know how it works and I discover it looping for infinity *sorry for my bad english

Chris
  • 26,361
  • 5
  • 21
  • 42
  • Post input used and definition of `jeniss`.: {MCVE] – chux - Reinstate Monica Jan 17 '22 at 04:09
  • Your targets, `operator[z]`, etc, must be pointers to allocated character arrays of sufficient size. Are they? – Dúthomhas Jan 17 '22 at 04:13
  • 1
    Certainly infinite loop is due to `fscanf(rDATA,"%[^;];%[^;];%[^;];%[^;];%[^;];%[^\n]\n",operator[z],mode[z],jenis[z],jumlah[z],rak[z],tanggal[z])` returning something other than `EOF`, but not a full scan. – chux - Reinstate Monica Jan 17 '22 at 04:13
  • You are also using `a` without properly initializing. Turn up your compiler’s warnings to as high a level as you can. – Dúthomhas Jan 17 '22 at 04:23
  • Be very cautious about using trailing white space in a `fscanf()` format string. When the input is from a file, as here, it isn't too horribly awful, but if a user might be typing the input, it gives a horrendous UX. See [What is the effect of trailing white space in a `scanf()` format string?](https://stackoverflow.com/questions/19499060/what-is-the-effect-of-trailing-white-space-in-a-scanf-format-string) – Jonathan Leffler Jan 17 '22 at 04:45
  • Note that if you want diagnostic output to appear reliably and timely, at minimum ensure the output ends with a newline. You have `printf("test");` — at minimum you need `printf("test\n");` (or `puts("test");`). – Jonathan Leffler Jan 17 '22 at 04:47
  • Use `while (fscanf(rDATA, "%[^;];%[^;];%[^;];%[^;];%[^;];%[^\n]\n", operator[z], mode[z], jenis[z], jumlah[z], rak[z], tanggal[z]) == 6) { … }`. You might even capture the value returned so you can test for EOF vs format error outside the loop: `int rv; while ((rv = fscanf(rDATA, "%[^;];%[^;];%[^;];%[^;];%[^;];%[^\n]\n", operator[z], mode[z], jenis[z], jumlah[z], rak[z], tanggal[z])) == 6) { … }`. You should also consider limiting the length of the `%[^;]` items, specifying one less than the size of the array into which it will be read. – Jonathan Leffler Jan 17 '22 at 04:50

1 Answers1

2

Reading the file using

while (fscanf(rDATA, "%[^;];%[^;];%[^;];%[^;];%[^;];%[^\n]\n", .... ) != EOF) {

are bad for several reasons. One of them is that it can lead to an infinite loop if fscanf can't match anything. In such cases fscanf returns 0 (zero) and it won't advance in the file. Consequently you never reach EOF so you have an infinite loop.

The above can for instance happen for your code if the file contains a line that starts with a ;.

Instead of using fscanf use fgets to read a whole line and then do the parsing afterwards, e.g. using sscanf.

Incidentally, when using one of the scan-functions, you should always check the return value to see how many matches you got. For instance your code blindly expects 6 matches but in case the input file has unexpected data, you may get less. Your code need to check for that.

halfer
  • 19,824
  • 17
  • 99
  • 186
Support Ukraine
  • 42,271
  • 4
  • 38
  • 63