How to delete some Content in a File ?

Started by John1, September 21, 2019, 06:16:36 PM

Previous topic - Next topic

John1

Hello,

I was trying to delete some Strings from a File.

The Function below gets a String, which must be overwritten.
Nothing happens after the execution of the Function, it goes back to the Menu, and after showing the List there is still the same String in the content of the File. Seems the Function delete won't work.

What could be changed ?

void deleteElement(char* ow) {
char* overWrite = "                                     ";
FILE *fp;
fpos_t position;

fp = fopen(DATAFILE,"a+b");
fgetpos(fp, &position);
fputs(ow, fp);
 
fsetpos(fp, &position);
fputs(overWrite, fp);
fclose(fp);
}

TimoVJL

using that append mode is reason for that problem.
May the source be with you

John1

Hello TimoVJL,

Thanks, yes it was not correct with (a+b).

Instead now I use (r+), which seems the only option.

But now when I will delete something it deletes just one time the first String it can find, the other Strings remain, also after executing the delete function. Normaly it must find the String through "fgetpos(fp, &position);".

Kind regards
John1

TimoVJL

A string function strstr() may help.
If you want to delete string, use a temporary file and copy relevant parts to it.
May the source be with you

John1

Hello TimoVJL,

Thank you for your Answers.

I tried to change the code as your advices. But somehow it doesn't delete exactly the content.
Now it deletes all String, except the last String in the List.

In the Web I found some examples, but not clear how to use it.

Maybe you might give some hints with some code ?

void deleteElement(char* ow) {
FILE *fp;

fp = fopen(DATAFILE,"r");
while(fread(&carV, sizeof(carV), 1, fp) == 1) {
  printf("\nOld-Content: %s\n", carV);       //Debug
  printf("\nKey value to delete: %s\n", ow); //Debug
  if(strstr(carV, ow) != 0) {
   printf("\nString: %s\n", carV);           //Doesn't print out ?
  }             
}
fclose(fp);
printf("\nNew-Content: %s\n", carV);        //Debug
remove(DATAFILE);

fp = fopen(DATAFILE ,"a");
if(fwrite(&carV, sizeof(carV), 1, fp) != 1) {
  fprintf(stderr, "Error in write, in %s\n", DATAFILE);
  fclose(fp);
  return;
}   
fclose(fp);
}


Kind regards
John1

TimoVJL

#5
a silly example
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int __cdecl main(void)
{
char *file = "test_str_del.txt";
FILE *fp = fopen(file, "rb"); // binary format
char *s = "foo";
int keylen = strlen(s);
if (fp) {
fseek(fp, 0, SEEK_END);
int len = ftell(fp);
fseek(fp, 0, SEEK_SET);
char *pbuf = malloc(len+1);
//*(pbuf + 1) = 0; //
if (pbuf) {
fread(pbuf, len, 1, fp); // read text to buffer
fclose(fp);
fp = NULL;
char *p1 = pbuf, *p = pbuf;
while (p = strstr(p, s)) { // find next search keyword
if (!fp) fp = fopen(file, "wb"); // rewrite file
fwrite(p1, p - p1, 1, fp); // write block before keyword
p += keylen; // past deleted keyword
p1 = p; // savepoint after keyword
}
if (p1) // write rest of text
fwrite(p1, (pbuf + len) - p1, 1, fp);
}
fclose(fp);
}
return 0;
}
test_str_del.txt
test foo in foo
foo1
end

EDIT: fixed version with some comments
May the source be with you

John1

Hello TimoVJL,

Thanks a lot for your hint. it's deleting well.
Might be simple for you, but I have some problems to understand it.
I'm sorry I usually used Java as beginner with a lot of API prepared Methods(Functions), which seemed to be simpler.
That I'm using C for this it's just to test and learn as very new beginner, hopefully I can learn something.

Somehow I understand your code, but maybe you may post some //explains in it, seems in part to calculate something with keylen in the while loop ?

Perhaps I may ask you why the Code below, with little modification, doesn't work ?
It doesn't execute the while loop.

Thank you for your patience.

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

#define file "test_str_del.txt"

int main(void) {
  FILE *fp;
  char val[256];  // new add, instead "s" now it is "val"
  if(fgets(val,sizeof(val),stdin) == NULL) { // new add
   printf("Wrong Input\n");     
  } 

   fp = fopen(file, "r");
   int keylen = strlen(val);
   if (fp) {
    fseek(fp, 0, SEEK_END);
    int len = ftell(fp);
    fseek(fp, 0, SEEK_SET);
    char *pbuf = malloc(len);
    if (pbuf) {
     fread(pbuf, len, 1, fp);
     fclose(fp);
     fp = NULL;
     char *p1 = pbuf, *p = pbuf;
     while (p = strstr(p, val)) {
       if (!fp) fp = fopen(file, "w");
       fwrite(p1, p - p1, 1, fp);
       p += keylen;
       printf("keylen :  %d\n" , keylen); // ?
       p1 = p;
     }
   }
   fclose(fp);
  }
return 0;
}

TimoVJL

#7
1. fgets read a LF to buffer, so remove it
2. use binary format to avoid translations
3. write remainder buffer if needed
May the source be with you

John1

Hello TimoVJL,

Thanks for the explanation, now I can understand it a bit better.

Sorry for annoying you, but I added your corrections, and now it can't execute.
I think because of the last fwrite(p1, (pbuf + len) - p1, 1, fp);  , throws an exception, as I could more or less find out with debugging.

CRT: unhandled exception (main) -- terminating
*** Process returned 255 ***


Kind regards
John1

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

#define file "test_str_del.txt"

int main(void) {
  FILE *fp;
  char val[256];
  val[strcspn(val, "\r\n")] = 0;  // does remove the carriage return and newline ?
  if(fgets(val,sizeof(val),stdin) == NULL) {
   printf("Wrong Input\n");     
  } 
  fp = fopen(file, "rb");
  int keylen = strlen(val);

  if (fp) {
   fseek(fp, 0, SEEK_END);
   int len = ftell(fp);
   fseek(fp, 0, SEEK_SET);
   char *pbuf = malloc(len+1);

   if (pbuf) {
    fread(pbuf, len, 1, fp);
    fclose(fp);
    fp = NULL;
    char *p1 = pbuf, *p = pbuf;

    while (p = strstr(p, val)) {
     if (!fp){ fp = fopen(file, "wb");}
      fwrite(p1, p - p1, 1, fp);
      p += keylen;
      p1 = p;
     }
     if (p1) { // write rest of text
      fwrite(p1, (pbuf + len) - p1, 1, fp); // doesn't execute
      printf("file almost finished");
     }
    }
    fclose(fp);
   }
  return 0;
}


TimoVJL

#9
use debugger to learn how code works.
  int keylen = strlen(val); // keyword length with LF
  val[--keylen] = 0; // remove LF and fix keylen
May the source be with you

John1

Hello TimoVJL,

Thanks a lot, it works now. It compile and execute well, just I have a problem that it do not delete as expected. Something is messed up, maybe from the adding function. I will play with it around, and perhaps open another post.

And thank you, I will try to learn, how to debug through Pelles C, or maybe also using some other Debugger (e.g. GDB or WinDbg) .

Kind Regards
John1

p.s my adding function :

void addNewElement(void) {
printf("Data :  ");
if(fgets(carV, BUF, stdin) == NULL) {
  fprintf(stderr, "Wrong Input\n");
  return;
}
killNL(carV);

FILE *fp = fopen(DATAFILE, "ab");

if(fp == NULL) {
  printf("Error in open: %s\n", DATAFILE);
  exit(EXIT_FAILURE);
}
if(fwrite(&carV, sizeof(carV), 1, fp) != 1) {
  fprintf(stderr, "Error in write, in %s\n", DATAFILE);
  fclose(fp);
  return;
}
fclose(fp);
}

//killNL
void killNL(char *str) {
size_t p = strlen(str);
if(str[p-1] == '\n') {
  str[p-1] = '\0';
}
}



Grincheux


John1

#12
Hello Grincheux,

What do you mean, with, some parts might be locked ?

The Strings in the File are not listed straight.

Sting one
  String two
  String three


But instead somewhere randomly.

String one
                                                      String two
                                                                                               String three


Perhaps this prevents the funciton to find and delete the Strings as well ?

In this Code it is deleted well, but not ever :

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

#define file "test_str_del.txt"

char carV[256];

void deleteElement() {
FILE *fp;
    char value[256];
value[strcspn(value, "\r\n")] = 0;  // new add, instead "s" now it is "val"
printf("Data to delete :  ");
    if(fgets(value,sizeof(value),stdin) == NULL) { // new add
     printf("Wrong Input\n");     
            } 


fp = fopen(file, "rb");
int keylen = strlen(value);
value[--keylen] = 0; // remove CR and fix keylen
if (fp) {
fseek(fp, 0, SEEK_END);
int len = ftell(fp);
fseek(fp, 0, SEEK_SET);
char *pbuf = malloc(len+1);
if (pbuf) {
fread(pbuf, len, 1, fp);
fclose(fp);
fp = NULL;
            char *p1 = pbuf, *p = pbuf;
while (p = strstr(p, value)) {
if (!fp){ fp = fopen(file, "wb");}
fwrite(p1, p - p1, 1, fp);
p += keylen;
p1 = p;
}
            if (p1) { // write rest of text
     fwrite(p1, (pbuf + len) - p1, 1, fp); // doesn't execute
//printf("file almost finished");
    }
}
fclose(fp);
    }
}


void killNL(char *str) {
size_t p = strlen(str);
if(str[p-1] == '\n') {
  str[p-1] = '\0';
}
}

void addNewElement(void) {
printf("Data to input :  ");
if(fgets(carV, 256, stdin) == NULL) {
  fprintf(stderr, "Wrong Input\n");
  return;
}
killNL(carV);

FILE *fp = fopen(file, "ab");

if(fp == NULL) {
  printf("Error in open: %s\n", file);
  exit(EXIT_FAILURE);
}
if(fwrite(&carV, sizeof(carV), 1, fp) != 1) {
  fprintf(stderr, "Error in write, in %s\n", file);
  fclose(fp);
  return;
}
fclose(fp);
}

int main(void) {
addNewElement();
addNewElement();
    deleteElement();
return 0;
}


Thanks