2010-04-02 31 views
2

Salut J'essaie de marquer une chaîne en chargeant un fichier entier dans un char[] en utilisant fread. Pour une raison étrange, cela ne fonctionne pas toujours, et Valgrind se plaint dans ce très petit exemple de programme.valgrind se plaint de faire un strtok très simple en c

Étant donnée une entrée comme test.txt

first 
second 

Et le programme suivant

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 
#include <sys/stat.h> 


//returns the filesize in bytes 
size_t fsize(const char* fname){ 
    struct stat st ; 
    stat(fname,&st); 
    return st.st_size; 
} 

int main(int argc, char *argv[]){ 
    FILE *fp = NULL; 
    if(NULL==(fp=fopen(argv[1],"r"))){ 
    fprintf(stderr,"\t-> Error reading file:%s\n",argv[1]); 
    return 0; 
    } 
    char buffer[fsize(argv[1])]; 
    fread(buffer,sizeof(char),fsize(argv[1]),fp); 
    char *str = strtok(buffer," \t\n"); 

    while(NULL!=str){ 
    fprintf(stderr,"token is:%s with strlen:%lu\n",str,strlen(str)); 
    str = strtok(NULL," \t\n"); 
    } 
    return 0; 
} 

compilation comme

gcc test.c -std=c99 -ggdb 

courir comme

./a.out test.txt 

grâce

+1

strtok est obsolète et présente plusieurs problèmes. ne l'utilisez pas. –

+0

Que recommanderiez-vous à la place? Pour les choses simples, cela ne doit pas être threadsafe etc. Je le trouve encore très utile – monkeyking

+0

Eh bien, évidemment ce n'est pas si simple, sinon 'valgrind' ne se plaindrait pas. –

Répondre

6

Votre taille buffer devrait être filesize + 1. Le +1 est pour le null char.

filesize = fsize(argv[1]); 
char buffer[filesize + 1]; 

également fread ne met pas \0 à la fin de la chaîne. Ainsi, vous aurez à faire vous-même comme:

fread(buffer,sizeof(char),filesize,fp); 
buffer[filesize] = 0; 
+0

La variable Can (taille de fichier + 1), pas une constante, peut-elle être utilisée comme taille de tableau ...? – sky

2

buffer est non nul terminé. Vous devez lui donner un octet plus grand que la taille du fichier, et vous devez définir le dernier octet à \0.

1

Votre tampon est trop petit. Essayez ceci:

int fileSize = fsize(argv[1]); 
char buffer[fileSize + 1]; 
buffer[fileSize] = 0; 

juste avant votre appel à fread.

2

Votre tampon doit être filesize + 1 et vous aurez également besoin de mettre fin à la 0:

int size = fsize(argv[1]); 
char buffer[size + 1]; 
buffer[size] ='\0'; 

En outre, vous devriez probablement affecter le tampon sur le tas au lieu de la pile ...

5

De ce site:

int main(int argc, char* argv[]) 
{ 
    std::string str = "The quick brown fox"; 

    // construct a stream from the string 
    std::istringstream stream(str); 

    // use stream iterators to copy the stream to the vector 
    // as whitespace separated strings 
    std::istream_iterator<std::string> it(stream), end; 

    std::vector<std::string> results(it, end); 

    // results = ["The", "quick", "brown", "fox"] 
} 

beaucoup plus facile que de traiter avec les C-cordes désagréables qui maintiennent vous frapper à la tête.

Et vous savez ce qui est génial avec l'utilisation de méthodes d'ordre supérieur? Il faut moins d'écran et est plus facile à comprendre.

+1

+1, La question est étiquetée à la fois C et C++, mais plusieurs fois cela signifie que * Je programme C++, mais peut utiliser une solution C * même si dans ce cas le code et le nom de fichier semblent indiquer C.Quoi qu'il en soit cela vaut la peine d'être upvote (les gens qui font du C++ le liront sûrement) même si cela ne convient pas à l'utilisateur. –