-3

I'm trying to create a function that given a word in input can find and delete the line that contain it. I've done some research on internet and I wrote some code but when i launch the program only find the line but it doesn't delete the line and the old file (database.txt).

This is the function that deletes the line:

FILE *database, *database2;
char str[500];
int linea = 0, ctr = 0;
char ID[256];

database2 = fopen("database2.txt", "a");
fclose(database2);

database = fopen("database.txt", "r");
if(!database){
    printf("Errore nell'apertura del file.\n");
    getch();
    return;
}

database2 = fopen("database2.txt", "r");

if(!database2){
    printf("Errore nell'apertura del file 2.\n");
    getch();
    return;
}

printf("Inserisci l'ID del libro da eliminare:");
scanf("%s", &ID);


int x = FindLine(ID);
printf("%d", x);

while(!feof(database)){
    strcpy(str, "\0");
    fgets(str, 256, database);
    if(!feof(database)){
        ctr++;
        if(ctr != x){
            fprintf(database2, "%s", str);
        }
    }
}

fclose(database);
fclose(database2);
remove("database.txt");
rename("database2.txt", "database.txt");
getch();

This is the function that find the line:

FILE *fp;
int line_num = 1;
int find_result = 0;
char temp[512];

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

if(fp == NULL){
    return(-1);
}


while(fgets(temp, 512, fp) != NULL) {
    if((strstr(temp, str)) != NULL) {
        return line_num;
        find_result++;
    }
    line_num++;
}

if(find_result == 0) {
    printf("\nSorry, couldn't find a match.\n");
}


if(fp) {
    fclose(fp);
}
return(0);

Some can help me to find the error please.

  • Hi, what exactly is the problem (exception, missing functionality)? Can you add the printouts of the execution? Why do you open ```database2.txt``` and close it at the beginning? – Kraego Aug 27 '21 at 08:29
  • 3
    First of all, [`while (!feof(...))` is always wrong](https://stackoverflow.com/questions/5431941/why-is-while-feof-file-always-wrong); Secondly, `strcpy(str, "\0");` isn't needed before the `fgets` call; Then the `scanf` format `%s` expect a `char *` argument, while `&ID` is of the type `char (*)[256]`. Use plain `ID` (which will decay to `&ID[0]` which is of the correct `char *` type). Mismatching format specifier and argument type leads to *undefined behavior*. – Some programmer dude Aug 27 '21 at 08:29
  • `scanf("%255s", ID);` -- there is no `&` as `ID` is already a pointer. Further, without the *field-width modifier*, `scanf()` into a character array is no safer than `gets()`, see [Why gets() is so dangerous it should never be used!](https://stackoverflow.com/q/1694036/3422102) Consider removing `getch()` and using `getchar()` instead which will allow you to remove `conio.h` header. – David C. Rankin Aug 27 '21 at 08:33
  • sounds very `grep -v {word}` like – tstanisl Aug 27 '21 at 08:35
  • @Someprogrammerdude, I thought `ID` was plain old `char ID[256];` -- where you getting `char (*)[256]` from ?? – David C. Rankin Aug 27 '21 at 08:35
  • OT: `strcpy(str, "\0");` is ... interresting – Support Ukraine Aug 27 '21 at 08:36
  • OT: `find_result++;` **after** `return line_num;` is .... not so interresting. And doesn't close the file – Support Ukraine Aug 27 '21 at 08:38
  • 1
    *"It doesn't work"* does not describe the problem – klutt Aug 27 '21 at 08:41
  • @DavidC.Rankin Because the OP is using `&ID` as argument to `scanf`, not plain `ID`. The pointer is correct, but the type isn't. – Some programmer dude Aug 27 '21 at 08:43
  • Writing to `database2` after opening it in read mode? – Ruud Helderman Aug 27 '21 at 08:44
  • OT: Kind of interresting that you use 256 as max in one function and 512 in the other... – Support Ukraine Aug 27 '21 at 08:45
  • Regarding those `fgets` calls, use `sizeof` to get the actual size of the buffers. As in `fgets(str, sizeof str, database);` – Some programmer dude Aug 27 '21 at 08:48
  • 1
    Yep, I see what you are sating now. Time for sleep :) – David C. Rankin Aug 27 '21 at 08:49
  • "Some can help me to find the error please." --> Unfortunalty there are many errors here. To fix well implies a complete re-write. Start with smaller complete steps. Buona fortuna! – chux - Reinstate Monica Aug 27 '21 at 09:52
  • Thanks to all, I will try to fix a bit all and then I will re-comment with the result –  Aug 27 '21 at 10:12
  • Please clarify your specific problem or provide additional details to highlight exactly what you need. As it's currently written, it's hard to tell exactly what you're asking. – Community Aug 27 '21 at 10:42

1 Answers1

1

Using feof() to check for end of file is incorrect, you should instead check the return value of fgets(). You can learn about this on this question: Why is “while ( !feof (file) )” always wrong? .

Here is a modified version:

#include <stdio.h>
#include <string.h>

int main() {
    FILE *database, *database2;
    char ID[256];
    char str[512];
    int linea, ctr;
    
    printf("Inserisci l'ID del libro da eliminare:");
    if (scanf("%255s", ID) != 1) {
        printf("input error\n");
        return 1;
    }

    database = fopen("database.txt", "r");
    if (!database) {
        printf("Errore nell'apertura del file database.txt.\n");
        return 1;
    }

    ctr = linea = 0;
    while (fgets(str, 512, database)) {
        ctr++;
        if (strstr(str, ID)) {
            linea = ctr;
            break;
        }
    }

    if (linea == 0) {
        printf("No matching line\n");
        fclose(database);
        return 1;
    }
    printf("linea: %d\n", linea);

    database2 = fopen("database2.txt", "w");
    if (!database2) {
        printf("Errore nell'apertura del file database2.txt.\n");
        fclose(database);
        return 1;
    }
    rewind(database);
    ctr = 0;
    while (fgets(str, 512, database)) {
        ctr++;
        if (ctr != linea) {
            fputs(str, database2);
        }
    }
    fclose(database);
    fclose(database2);
    remove("database.txt");
    rename("database2.txt", "database.txt");
    return 0;
}
chqrlie
  • 131,814
  • 10
  • 121
  • 189