При печати содержимого связанного списка печатается только первый узел - PullRequest
0 голосов
/ 27 октября 2011

Это обновленная версия кода. я пытаюсь добавить некоторую информацию в список ссылок каждый раз, когда клиент отправляет сообщение на сервер (это может быть несколько клиентов). Каждый раз, когда приходит новое сообщение, функция проверяет его время, чтобы добавить его в список до или после предыдущего узла в зависимости от его текущего времени. Сервер должен распечатать сообщения в порядке поступления. Если есть одинаковые метки времени, то он должен переместиться, чтобы отсортировать равные по идентификаторам серверов.

Вот моя структура списка:

   'typedef struct trade_list {
    char* trader_msg;
    u_int32_t id_of_sender;
    int sender_timer;
    int local_time;

    struct trade_list *next;
}trade_list;

trade_list *head = NULL;

следующая функция, которая вставляет в список и сортирует по времени:

  void add_transaction (char* received_msg_IN, int curr_time_IN, u_int32_t my_id_IN, int elapsedIn)
{ 
 /* Find the node with the smallest time >= curr_time_IN.  'found' starts as NULL, then
        is always the node before 'cur'.  'cur' moves through the list until its time is
        less than 'curr_time_IN'.  So at the end, 'cur' is the first node that's too 
        far in, and 'found' is either NULL or the node we insert after. */

    trade_list *newnode, *cur, *found;


     found = NULL;
  for (cur = head; cur && cur->sender_timer <= curr_time_IN; cur = cur->next)
     found = cur;


    if (found) {
      /* If 'found' isn't NULL, we're inserting after it*/
            /* Times match: Sort out in another way*/

      } else {
            newnode = malloc(sizeof(*newnode));
            newnode->trader_msg = malloc(strlen(received_msg_IN)*sizeof(received_msg_IN));
            strcpy(newnode->trader_msg,received_msg_IN);
            newnode->sender_timer = curr_time_IN;
            newnode->id_of_sender = my_id_IN;
            newnode->local_time = elapsedIn;
            newnode->next = found->next;
            found->next = newnode;

            }
    } else {                

        /* No node with more recent time found -- inserting at 'head' */
       newnode = malloc(sizeof(*newnode));
       newnode->trader_msg = malloc(strlen(received_msg_IN)*sizeof(received_msg_IN));
       strcpy(newnode->trader_msg,received_msg_IN);
       newnode->sender_timer = curr_time_IN;
       newnode->id_of_sender = my_id_IN;
       newnode->local_time = elapsedIn;
       newnode->next = head;
       head = newnode;
         }   

ИЗД. ПОСЛЕ НОВОЙ ПРОБЛЕМЫ

Мне удалось отсортировать список, используя метод сортировки позже. Так что теперь мой список отсортирован очень хорошо. Он печатает просто отлично, новая проблема, которая возникла сейчас, заключается в том, что я хочу удалить текущий узел после его печати. Таким образом, после того, как он получит печать, он будет удален. Я использовал следующую функцию, но мое приложение зависало.

void deletefirst (struct trade_list *head) {
    struct trade_list *tmp = *head;         
    if (tmp == NULL) return;            
    *head = tmp->next;                  
    free (tmp);                        
}

я вызываю эту функцию из моей функции печати:

void print_trades()
{

    trade_list * newnode = head;

        while (newnode) {

            if ((elapsed - newnode->local_time >= 8)) 
            {
            printf ("%s\n", newnode->trader_msg);
            newnode = newnode->next;
            deletefirst(newnode);
            }

          }
}

Как мне удалить текущий узел и двигаться дальше?

Ответы [ 2 ]

0 голосов
/ 27 октября 2011

Способ, которым вы печатаете список, должен работать нормально, если есть хотя бы один узел. Я бы порекомендовал изменить do { ... } while() на while() { ... }, чтобы он все еще работал, когда список пуст и head равен NULL:

trade_list *currentnode = head;
while (currentnode) {
  printf ("Trade: %s Time: %d ID: %d\n", 
      currentnode->trader_msg,
      currentnode->sender_timer,
      currentnode->id_of_sender);
  currentnode = currentnode->next;
}

Однако при добавлении в список возникают некоторые проблемы. Если head не равно нулю, вы удаляете его ссылку на остальную часть списка:

if (head == NULL) 
    {
   ... /* skipped for brevity */
    }
else
    {
    currentnode->next = NULL;
    head = currentnode;
    }

Поскольку в этот момент currentnode == head, вы указываете head->next на NULL (если бы был другой узел, вы бы выбросили его), а затем присваиваете head себе.

Ваш код вставки в целом выглядит неправильно. Если вы хотите вставить только в начале списка, вам просто нужно что-то вроде:

trade_list *newnode = malloc(sizeof(trade_list));
/* *** Fill out newnode's fields here *** */
newnode->next = head;
head = newnode;

Если вы хотите вставить после произвольного узла, вы должны сначала найти его, пройдясь по списку, а затем сделать что-то вроде этого (держа более поздние времена во главе списка):

trade_list *newnode, *cur, *found;
/* Find the node with the smallest time >= curr_time_IN.  'found' starts as NULL, then
   is always the node before 'cur'.  'cur' moves through the list until its time is
   less than 'curr_time_IN'.  So at the end, 'cur' is the first node that's too far in,
   and 'found' is either NULL or the node we insert after. */
found = NULL;
for (cur = head; cur && cur->sender_timer >= curr_time_IN; cur = cur->next)
  found = cur;

if (found) {
  /* If 'found' isn't NULL, we're inserting after it (or skipping if the times match,
     since that seems to be what the original code was trying to do) */
  if (found->sender_timer == curr_time_IN) {
    /* Times match: skip it */
    printf("SKIPPED\n");
  } else {
    /* inserting after 'found' */
    newnode = malloc(sizeof(*newnode));
    /* *** Fill out newnode's fields here *** */
    newnode->next = found->next;
    found->next = newnode;
  }
} else {
  /* No node with more recent time found -- inserting at 'head' */
  newnode = malloc(sizeof(*newnode));
  /* *** Fill out newnode's fields here *** */
  newnode->next = head;
  head = newnode;
}

Отредактировано после комментария:

Чтобы изменить список для сортировки по убыванию по времени, а затем по ID в порядке возрастания, требуется всего пара изменений.

Редактировать Поскольку исходный цикл for для поиска узла продолжается до последнего узла, который соответствует критериям, нам просто нужно добавить тест в цикл, чтобы разорвать его, когда мы окажемся на правильном ... то есть разрывать, если следующий узел имеет равное время и более высокий ID, поскольку в этом случае мы хотим вставить перед этим. (предыдущая редакция была ошибочной ... извините за это).

Кроме того, проверка if (found->sender_timer == curr_time_IN) впоследствии больше не требуется, поскольку пропуски не выполняются, а сортировка по идентификатору обрабатывается новым циклом for.

Итак, этот фрагмент кода становится:

/* original search */
for (cur = head; cur && cur->sender_timer >= curr_time_IN; cur = cur->next) {
  /* *** added condition for ID sort */
  if (cur->sender_timer == curr_time_IN && cur->id_of_sender >= my_id_IN) break;
  found = cur;
}

if (found) {
  /* If 'found' isn't NULL, we're inserting after it */

  /* CHANGED: no need to skip when times are equal */
  newnode = malloc(sizeof(*newnode));
  /* *** Fill out newnode's fields here *** */
  newnode->next = found->next;
  found->next = newnode;

} else {
   /* No node with more recent time found -- inserting at 'head' */
  newnode = malloc(sizeof(*newnode));
  /* *** Fill out newnode's fields here *** */
  newnode->next = head;
  head = newnode;
}
0 голосов
/ 27 октября 2011

Проблема не в коде печати, а в добавлении.

Похоже, что при добавлении нового узла вы выделяете узел, но не подключаете его к головке или любому другому узлу.

У вас должен быть такой код для добавления в начало списка:

new_node->next = head;
head= new_node;

Кроме того, используемая вами логика затенена, и у вас много дубликатов кода.1009 * Добавление в связанный список имеет только две опции: начало списка (заголовок) или любой другой узел, вам не нужна вся эта логика.

...