Ошибка сегментации, но я не могу найти где - PullRequest
0 голосов
/ 15 января 2019

Я застрял, потому что не понимаю, почему мой код парсера не работает, один компилятор просто говорит об ошибке сегментации. Хотя другой компилятор компилирует его, но он просто возвращает код ошибки

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

const char *
getfield (char *line, int num)
{
  const char *tok;
  for (tok = strtok (line, ","); tok && *tok; tok = strtok (NULL, ",\n"))
  {
    if (!--num)
      return tok;
  }
  return NULL;
}

int
main ()
{
  FILE *stream = fopen ("input", "r");
  FILE *fp;
  char line[1024];
  while (fgets (line, 1024, stream))
  {
     char *tmp = strdup (line);
     char buf[0x100];
     snprintf (buf, sizeof (buf), "c:\\temp\\%s.txt", getfield (tmp, 1));
     fp = fopen (buf, "w");
     int count = 0;
     while ((tmp = strchr (tmp, ',')) != NULL)
     {
       count++;
       tmp++;
     }
     if (count == 4 ){
       fprintf (fp,
               "{This is my name %s\n I'm %s years old\n my       useragent is %s\n My hobbies are %s\n}",
               getfield (tmp, 1), getfield (tmp, 2),
               getfield (tmp, 4), getfield (tmp, 5));
     }
     else {
        fprintf (fp,
                 "{This is my name %s\n I'm %s years old\n my       useragent is %s%s\n My hobbies are %s\n}",
                 getfield (tmp, 1), getfield (tmp, 2),
                 getfield (tmp, 4), getfield (tmp, 5),
                 getfield (tmp, 6));
     }

     fclose (fp);
     free (tmp);
   }
}

У меня есть CSV-файл с тысячами строк. Пример

Name,age,gender,useragent,hobby
maximilian,16,Male,Mozilla/5.0 (compatible, MSIE 11, Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko,skateboard

Я пытаюсь создать файл для каждого имени и добавить в него другую информацию. таким образом, это вывело бы это например

maximilain.txt

This is my name maximilian
 I'm 16 years old
 my useragent is Mozilla/5.0 (compatible, MSIE 11, Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko
 My hobbies are skateboard

1 Ответ

0 голосов
/ 15 января 2019

после

while ((tmp = strchr (tmp, ',')) != NULL)
{
  count++;
  tmp++;
}

tmp имеет значение NULL, поэтому следующий вызов getfield получит нулевой указатель, , в то время как должен быть выполнен для другого указателя, или вам нужно сохранить tmp до

например, сделать:

char * p = tmp;

while ((p = strchr (p, ',')) != NULL)
{
  count++;
  p++;
}

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

Вы можете изменить getfield для работы с копией:

const char *
getfield (char *line, int num)
{
  static char l[1024];
  strcpy(l, line);
  const char *tok;
  for (tok = strtok (l, ","); tok && *tok; tok = strtok (NULL, ",\n"))
  {
    if (!--num)
      return tok;
  }
  return NULL;
}

Но это плохой способ сделать, потому что каждый раз, когда нужно идти, бросайте строку, минуя все больше и больше жетонов.

Я позволю вам оптимизировать ваш код, чтобы извлечь каждый токен только один раз в каждой строке.


Обратите внимание, что вы используете первую строку csv, поэтому вы создаете файл на основе 'Name' и т. Д.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...