Valgrind жалуется, что делает очень простой strtok в C - PullRequest
2 голосов
/ 02 апреля 2010

Привет. Я пытаюсь токенизировать строку, загружая весь файл в char[], используя fread. По какой-то странной причине это не всегда работает, и Вальгринд жалуется на этот очень маленький пример программы.

С учетом ввода типа test.txt

first
second

и следующая программа

#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;
}

компилируется как

gcc test.c -std=c99 -ggdb

работает как

./a.out test.txt

спасибо

Ответы [ 5 ]

6 голосов
/ 02 апреля 2010

Ваш buffer размер должен быть filesize + 1. +1 - для null char.

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

Также fread не ставит \0 в конце строки. Так что вам придется сделать это самостоятельно как:

fread(buffer,sizeof(char),filesize,fp);
buffer[filesize] = 0;
5 голосов
/ 02 апреля 2010

С этого сайта :

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"]
}

НАСТОЛЬКО гораздо проще, чем иметь дело с теми противными струнами С, которые постоянно бьют тебя по голове.

А вы знаете, что хорошего в использовании методов высшего порядка? Это занимает меньше экрана и его легче понять.

2 голосов
/ 02 апреля 2010

Ваш буфер должен быть filesize + 1, и вам также нужно будет установить завершающий 0:

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

Кроме того, вам, вероятно, следует выделить буфер в куче, а не в стеке ...

2 голосов
/ 02 апреля 2010

buffer не заканчивается нулем. Вам нужно сделать его на один байт больше, чем размер файла, и вам нужно установить последний байт \0.

1 голос
/ 02 апреля 2010

Ваш буфер слишком мал. Попробуйте это:

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

прямо перед вашим звонком на fread.

...