Бег в Бесконечном L oop C - PullRequest
       17

Бег в Бесконечном L oop C

0 голосов
/ 03 февраля 2020

Я бегу в бесконечном l oop, и я не знаю почему. Я попытался отладить мой код безуспешно. Может быть, кто-то может помочь мне исправить это.

void init_list(list* mylist)
{

  mylist->first = NULL;
  mylist->last = NULL;
}



void insert_list(list_element* le, list* mylist)
{

  if(mylist->first == NULL)
  {
    mylist->first = le;
    mylist->last = le;
    return;
  }

  mylist->last->next = le;
  mylist->last = le;
  //printf("Test");

  return;

}

void free_list(list* mylist)
{
    list_element* tmp = mylist->first;
    while(tmp->next != NULL)
    {
      free(mylist->first->password);
      free(mylist->first);
      tmp = tmp->next;
      mylist->first = tmp;
    }
}


void read_data(char* filename, list* mylist)
{
  FILE * file = fopen(filename,"r");

  char line[100];


  while (fgets(line, sizeof(line), file) != NULL)
  {
    char * teile;
    int index;
    teile = strrchr(line, ' ');

    //printf("%s\n",teile);

    index = (int) (teile - line);

    //printf("%d\n",index);

    char password[index+1];

    strncpy(password, line, index);

    password[index] = '\0';

    //printf("%s\n",password);

    list_element * le = malloc(sizeof(list_element));
    le->password = malloc(sizeof(char) * (strlen(password)+1));
    strncpy(le->password,password,(strlen(password)+1));
    le->next = NULL;
    int anzahl = atoi(teile);
    le->count = anzahl;

    //printf("%d %s\n", le->count, le->password);

    insert_list(le, mylist);

  }

  fclose(file);

}

list_element* partition( list* input, list* left, list* right )
{
    list_element * pivot = input->first;


    list_element * tmp;
    for (tmp = pivot->next; tmp != NULL; tmp= tmp->next)
    {
      if((tmp->count) < (pivot->count))
      {
        insert_list(tmp, left);
      }
      else
      {
        insert_list(tmp, right);
      }
    }  
    return pivot;
}

void qsort_list(list* mylist)
{
    list right;
    init_list(&right);
    list left;
    init_list(&left);
    list_element* pivot;

    if(mylist->first != mylist->last)
    {
      pivot = partition(mylist, &left, &right );
      qsort_list(&left);
      qsort_list(&right);


      if(left.first == NULL) 
      {
        mylist->first = pivot;
      } 
      else 
      {
        mylist->first = left.first;
        left.last->next = pivot;
      }
      if(right.first == NULL) 
      {
        pivot->next = right.first;
        mylist->last = pivot;
      } 
      else 
      {
        pivot->next = right.first;
        mylist->last = right.last;
      }     
    }
    return;

}

void print_list(list* mylist)
{
    list_element * current = mylist->first;
    while (current != NULL)
    {
      printf("%s %d \n", current->password, current->count);
      current = current->next;
    }
}

Циклы в части insert_list. После вызова из read_data. Он также зацикливается только тогда, когда функция вызывается в последний раз.

int main(int argc, char** args)
{
    if (argc != 2)
    {
        printf("USE: %s <Filename>\n",args[0]);
        return 1;
    }
    list mylist;
    init_list(&mylist);
    read_data(args[1],&mylist);
    qsort_list(&mylist);
    printf("Sorted:\n");
    print_list(&mylist);
    free_list(&mylist);
    return 0;
}

typedef struct list_element list_element;

struct list_element {
    char *password;
    int count;
    list_element* next;
};

typedef struct list list;

struct list {
    list_element* first;
    list_element* last;
};

Ввод выглядит следующим образом:

asdfgh 31554
snoopy1 15637
qwertyuiop 24372

Редактировать: Исправлен ввод. Edit2: исправил код с помощью комментариев. Теперь я работаю в al oop в моей функции разделения.

Ответы [ 3 ]

3 голосов
/ 03 февраля 2020

Функция read_data имеет как минимум три серьезные ошибки.

Прежде всего, вы должны проверить, был ли файл открыт успешно.

Во-вторых, вы пишете за паролем массива, используя индекс index потому что вы не зарезервировали память в массиве для завершающего нуля.

char password[index];

strncpy(password, line, index);

password[index] = '\0';

В этом операторе

le->password = password;

все элементы списка назначаются с указателем на локальный массив, который не будет жив после выхода из функции. Вы должны динамически выделять память для каждого элемента данных le->password.

Так что программа в любом случае имеет неопределенное поведение.

Функция free_list

void free_list(list* mylist)
{

    free(mylist->first);
    free(mylist);
}

не освобождает всю выделенную память.

Также у вас есть логическая ошибка в дизайне вашего списка. Если у вас есть двухсторонний связанный список, то функция insert_list должна добавить новый узел в конец списка. В противном случае нет большого смысла иметь хвостовой узел для односвязного списка.

3 голосов
/ 03 февраля 2020

Ну, это не так

char password[index];
strncpy(password, line, index);
password[index] = '\0';

Вы выделяете index количество символов, но переписываете за пределы массива с помощью вашего последнего оператора. Вместо этого вы должны выделить

char password[index+1];
1 голос
/ 03 февраля 2020

Вот проблема. Присмотритесь к функции free_list.

void free_list(list* mylist)
{
    list_element* tmp = mylist->first;
    while(tmp->next != NULL)
    {
      free(mylist->first->password);
      free(mylist->first);
      tmp = tmp->next;
    }
    free(mylist);
}

В первый раз через l oop сначала вы устанавливаете tmp = mylist->, затем сначала освобождаете mylist->, затем пытаетесь получить «следующий» указатель из tmp. За исключением того, на что указала tmp, теперь нет, потому что вы только что освободили его.

...