2016-04-08 21 views
0

Hy herkes Bu kodu ettik:Yinelenen Dosya Pointer

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"); 

ve böyle bir dosya üzerinde çalışacak:

<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> 

ana dosya işaretçisi (FILE *fp) main()’dur.

Benim fikrim bu etiketi ben silmek isterdim o hizmetin adı bağlıysa, ben, çünkü etiketi <item ...> bulursanız (prototip geçirilir) dosyası işaretçisi fp çoğaltmak olduğunu ve <item ...> dizesinin tamamını değiştirmek için.

Ancak, bir sorunum var ... snprintf() ve fputs()'u gerçekleştirdiğimde, dosyanın başlangıcında dosyanın üzerine yazılır, çünkü imho, dosya tanıtıcısının iyi olmadığına inanıyorum.

Bu sorunu gidermek/çözmek için bir yol veya bir çözüm var mı?

Teşekkürler!

+0

Ne "yinelenen"? Kodunuzda görebildiğimiz tek şey, görünüşe göre yerel bir değişken olan 'fpTemp'. Sen hiçbir yere "fopen" demiyorsun. Kimse sadece bu kodla verilen soruya cevap veremez. Ayrıca bkz. [Neden (! Feof (fp)) daima yanlıştır? ”(Http://stackoverflow.com/questions/5431941/why-is-while-feof-file-always-wrong). – Lundin

+2

POSIX 'dup()' işlevini ANSI 'FILE *' ile kullanmayın. – jdarthenay

+0

@Lundin Yayını düzenledim ... 'fopen'i ekledim. –

cevap

1

Dosya işaretçisini kopyalamanıza gerek yoktur, ftell()/fseek()'u kullanmanız gerekir. Hata işleme olmadan küçük kod. (Bu yüzden lütfen iade kontrol ederek hata işleme eklemeden kopyalamayın).

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 

Ayrıca, fgetpos() ve fsetpos() kullanabilirsiniz görünüyor.

+0

'fpospos()' ve 'fsetpos() işlevlerini' fpos_t position' değişkeniyle kullandım, ancak 'fgets()' 'fseç()' i koymak zorunda kaldım çünkü 'fgets()' Bir sonraki satırın başında dosya işaretçisi. Teşekkür ederiz dostum! –

+0

@Federic Cuozzo Ayrıca sorunuzda alternatif olarak dosyada okuyup yazdığınızı görüyorum. Bu, 'fseek();' örneğin fseek (f, SEEK_CUR, 0) gibi hareketli bir imleç ifadesine çağrı yapmadan çalışmamalı; imlecin mevcut konumunda (lol) hareket ettirilmesi için yeterli olabilir. – jdarthenay