0

Hy everyone, I've this code:

int lenInput;
char input[64], buffer[512], temp[512], *ret, tagName[] = "<name>", tagItem[] = "<item ";
bool deleted = false;
FILE *fp, *fpTemp = NULL;

if(! (fp = fopen(nameFile, "r+")) ) {
    perror("Error Opening File");
    exit(-1);
}

printf("Insert the Name of the service you want to erase... ");
fgets(input, sizeof(input), stdin);

lenInput = (int) strlen(input);
input[lenInput-1] = '\0';
lenInput = (int) strlen(input);

do {
    fgets(buffer, sizeof(buffer), fp);
    buffer[strlen(buffer)-1] = '\0';

    if( (ret = strstr(buffer, tagName)) != NULL ) {
        if( strncmp(ret, tagName, strlen(tagName)) == 0 ) {
            if( (ret = strstr(ret, input)) != NULL ) {
                 if( strncmp(ret, input, lenInput) == 0 ) {
                     snprintf(temp, sizeof(temp), "<item present=\"false\">\n");
                     fputs(temp, fpTemp);

                     deleted = true;
                  }
             }
        }
    }
    else if( (ret = strstr(buffer, tagItem)) != NULL ) {
        if( strncmp(ret, tagItem, strlen(tagItem)) == 0 ) {
             fpTemp = fdopen( dup ( fileno(fp) ), "r+");     /* associates a stream with the existing file descriptor, fd */
        }
    }
} while( (deleted != true) && (!(feof(fp))) );

if(deleted == false)
    printf("Error: Service Not Found!\n");
else
    printf("Success: Service Erased!\n");

and it would work on a file like this:

<serviceNumber>2</serviceNumber>
<item present="true">
    <id>1</id>
    <name>name1</name>
    <description>descr1</description>
    <x>1</x>
    <y>1</y>
</item>
<item present="true">
    <id>2</id>
    <name>name2</name>
    <description>descr2</description>
    <x>2</x>
    <y>2</y>
</item>

The main file pointer (FILE *fp) is in the main().

My idea is to duplicate the file pointer fp (which is passed in the prototype) if I find the tag <item ...> because, if this tag is linked to the name of the service that I'd want to erase, I've to replace the entire <item ...> string.

But, I've a problem ... when I'll perform snprintf() and fputs(), the file is overwritten at the start of file, because, imho, I think the file pointer is not duplicate well.

There's a way or a workaround to fix/resolve this problem?

Thank you in advance!

Federico Cuozzo
  • 363
  • 1
  • 7
  • 20
  • What "duplicate"? The only thing we can see in your code is `fpTemp` which is apparently a local variable. You don't call `fopen` anywhere. Nobody can answer the question just with this code given. Also see [why is while(!feof(fp)) always wrong](http://stackoverflow.com/questions/5431941/why-is-while-feof-file-always-wrong). – Lundin Apr 08 '16 at 11:05
  • 2
    Do not use the POSIX `dup()` with the ANSI `FILE *`. – jdarthenay Apr 08 '16 at 11:06
  • @Lundin I've edited the post ... I've added the `fopen`. – Federico Cuozzo Apr 08 '16 at 13:49
  • @jdarthenay How I can backup/save/store at which line/position I've found the tag ``? – Federico Cuozzo Apr 08 '16 at 13:51

1 Answers1

1

You don't need to duplicate file pointer, you need to use ftell() / fseek(). Small code without error handling. (So please don't copy it without adding error handling by checking returns).

FILE *f = fopen(f, "r");

// do various things with file
long where_am_i = ftell(f); // if it fails, -1 is returned and errno is set to indicate the error.

// Do stuff requiring moving cursor in f stream

fseek(f, SEEK_SET, where_am_i); // same returns convention as ftell()
// You moved cursor back, you can start reading again

Also, it seems you can use fgetpos() and fsetpos().

jdarthenay
  • 3,062
  • 1
  • 15
  • 20
  • I've used `fgetpos()` and `fsetpos()` functions with `fpos_t position` variable, but I had to put a `fseek()` after `fsetpos()` because the `fgets()` puts the file pointer at the beginning of the next row. Thank u mate! – Federico Cuozzo Apr 08 '16 at 15:12
  • @Federic Cuozzo Also I see in your question you alternatively read and write in file. This is not supposed to work without a call to a moving cursor statement such as `fseek();` for instance `fseek(f, SEEK_CUR, 0);` for moving the cursor at its current position (lol) can suffice. – jdarthenay Apr 08 '16 at 15:18