c - 调用 next() 时最后一个元素不断重复。不返回 NULL

标签 c linked-list doubly-linked-list abstract-data-type

嘿,我正在尝试实现一个可以存储任何类型元素的通用列表迭代器。它还有其他文件来处理正整数类型和字符串类型。该文件编译正确。但是,当我在测试用例代码中调用 next() 函数(特别是下面代码中的测试用例 2)时,它会打印出添加的所有元素,但当它到达列表中的最后一个元素时,它会不断重复最后一个元素,当没有最后一个元素时,它应该返回 NULL

这是下一个函数:

void *next(IteratorG it){

  Node *tempo;
  if ((tempo = malloc(sizeof(Node))) == NULL) { 
    return 0; 
  }

  if(it->curr->next==NULL)
  {
    return NULL;
  }
  tempo=it->curr;
  it->curr=it->curr->next;

  // move to next node in list  
  return tempo->value;
}    

我使用的是 Linux 环境,错误从结果中可以看出。整个程序的代码如下:

#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include "iteratorG.h"

typedef struct Node {

  void *value;  // value of thee list item
  struct Node *prev;
  // pointer previous node in list
  struct Node *next;
  // pointer to next node in list

  // implemented struct here .. 
} Node;

typedef struct IteratorGRep {

  int  numofit;      // count of items in list
  Node *head;         // first node in list
  Node *curr;       // current node in list
  Node *tail;       // last node in list

  ElmCompareFp  cmpElm;
  ElmNewFp  newElm;
  ElmFreeFp freeElm;

  // implemented struct here .. 

} IteratorGRep;


/*


  //Your  functions below .... 
 */


IteratorG newIterator(ElmCompareFp cmpFp, ElmNewFp newFp, ElmFreeFp freeFp){

    IteratorG newit;


  if ((newit = malloc(sizeof (struct IteratorGRep)))==NULL)
  {
    printf("Error...! \n");

  }

  //assert (newit != NULL);
  newit->numofit = 0;
  newit->head = NULL;
  newit->tail = NULL;
  newit->curr = NULL;
  newit->cmpElm=cmpFp;
  newit->newElm=newFp;
  newit->freeElm=freeFp;
  return newit;

    // implemented function here and changed return value 
}



int  add(IteratorG it, void *vp){

  Node *temp;
  if ((temp = malloc(sizeof(Node))) == NULL) { 
    return 0; 
  }

  temp->value = it->newElm(vp);
  temp->next=NULL;

  if(it->curr==NULL)
  {
    //temp->next=it->curr;
    it->curr=temp;
    it->tail=it->head=it->curr;
  }  

  temp->next=it->curr;
  it->curr->prev=temp;
  it->curr=temp;
  it->head=it->curr;
  //it->curr->prev=temp;
  /*temp->next = it->curr;
  it->curr = temp;
  */
    // add node to list from front 
    return 1;
}
int  hasNext(IteratorG it){

  if(it->curr->next==NULL)
   {
     return 0;
   }


    // check if theres next element/node
    return 1;
}
int  hasPrevious(IteratorG it){

    if(it->curr->prev!=NULL)
    {
      return 1;
    }
    // check if theres previous element/node 
    return 0;
}
void *next(IteratorG it){

  Node *tempo;
  if ((tempo = malloc(sizeof(Node))) == NULL) { 
    return 0; 
  }

  if(it->curr->next==NULL)
  {
    return NULL;
  }
  tempo=it->curr;
  it->curr=it->curr->next;

  // implemented function here  
  return tempo->value;
}
void *previous(IteratorG it){

    Node *tempor;
  if ((tempor = malloc(sizeof(Node))) == NULL) { 
    return 0; 
  }
  tempor=it->curr;
  if(tempor->prev==NULL)
  {
    return NULL;
  }
  tempor=it->curr->prev;

  it->curr=it->curr->prev;
  //tempor=it->curr;

  // move to next node in list  
  return tempor->value;
}
int  del(IteratorG it){
  if(it->curr->prev!=NULL)
  {
    Node *temp_curr=it->curr;
    Node *temp_prev=it->curr->prev->prev;
    temp_curr->prev=temp_prev;
    temp_prev->next=temp_curr;
    return 1;

  }// delete previous node  from list 
  else
    return 0;
}
int  set(IteratorG it, void *vp){
  if(it->curr->prev!=NULL)
  {

  it->curr->prev->value=vp;


  /*  

  Node *wep;
  if ((wep = malloc(sizeof(Node))) == NULL) { 
      return 0; 
  }  


  wep->value=it->newElm(vp);  


  store_next=it->curr;
  store_prev=it->curr->prev->prev;
  store_next->prev=wep;
   wep->next=store_next;

  store_prev->next=wep;
  wep->prev=store_prev;
  */


  return 1;
  }
    // change previous node value with new 
    return 0;
}
IteratorG advance(IteratorG it, int n){



    //To be implemented
    //move forward by n times
    return NULL;
}
void reverse(IteratorG it){
  Node *curr = it->head;
  Node *temp = NULL;
  while(curr != NULL) {
    temp = curr->next;
    curr->next = curr->prev;
    curr->prev = temp;
    curr = temp;
  }
  temp = it->head;
  it->head = it->tail;
  it->tail = temp;// reverse elements of whole list
}
IteratorG find(IteratorG it, int (*fp) (void *vp) ){
    // To be implemented 
    // Find elements of vp in list after current position and put in new list.return the list.
      return NULL;
 }
int distanceFromStart(IteratorG it){

  Node *c=it->curr;
  int count=0;


  while(c->prev!=NULL)
  {
    c=c->prev;
    count++;
  }
  return count;
    // count number of elements from start of list to current position 

}
int distanceToEnd(IteratorG it){

  Node *cu=it->curr;
  int count=0;

  while(cu->next!=NULL)
  {
    cu=cu->next;
    count++;
  }
  return count;
    // count number of elements from end of list to current position
}
void reset(IteratorG it){



  while(it->curr->prev!=NULL)
  {

    it->curr=it->curr->prev;

  }
  return;
    // move current position to start of list

}
 void freeIt(IteratorG it){
  assert(it != NULL);
  Node *curr, *prev;
  curr = it->head;
  while (curr != NULL) {
    prev = curr;
    curr = curr->next;
    free(prev->value);
    free(prev);
  }
  free(it); // free items  

}

这是代码的头文件:

#ifndef LISTITERATORG_H
#define LISTITERATORG_H

#include <stdio.h>

typedef struct IteratorGRep *IteratorG;

typedef int   (*ElmCompareFp)(void const *e1, void const *e2);
typedef void *(*ElmNewFp)(void const *e1);
typedef void  (*ElmFreeFp)(void *e1);


IteratorG newIterator(ElmCompareFp cmpFp, ElmNewFp newFp, ElmFreeFp freeFp);
int  add(IteratorG it, void *vp);
int  hasNext(IteratorG it);
int  hasPrevious(IteratorG it);
void *next(IteratorG it);
void *previous(IteratorG it);
int  del(IteratorG it);
int  set(IteratorG it, void *vp);
IteratorG advance(IteratorG it, int n);
void reverse(IteratorG it);
IteratorG find(IteratorG it, int (*fp) (void *vp) );
int distanceFromStart(IteratorG it);
int distanceToEnd(IteratorG it);
void reset(IteratorG it);
void freeIt(IteratorG it);

#endif

其中一个功能尚未实现,并在代码本身中指出。但我想这可能不是问题的根源。我认为 NULL 在这里没有被正确使用。

编辑: 这是测试用例代码。仅在上面的程序中测试用例代码没有错误:

#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include "iteratorG.h"
#include "positiveIntType.h"
#include "stringType.h" 

#define MAXARRAY 5

/* Helper Functions Below */

/* Returns 1 if marks >= 50, 0 otherwise  */
int passMarks(void *marks){
  return (*((int *) marks) >= 50); 

  /* Easy to understand below .. 
     int *ip = (int *) marks;
     if(*ip >= 50) { return 1; }
     else { return 0; } 
  */
}

/* Returns 1 if str starts with "jo" */
int prefixJo(void *str){
  return (strncmp("jo", (char *) str, 2) == 0) ; 
}

/* A function to print a string from a void pointer */
void prnStr(void *vp){
  assert(vp != NULL);
  printf(" %s", (char *) vp );      
}

/* A function to print an integer from a void pointer */
void prnInt(void *vp){
  assert(vp != NULL);
  printf(" %d", *((int *) vp) );    
}

/* Prints previous element using the given function 'fp'
   examples: prnPrev(it1, prnInt); prnPrev(it2, prnStr);
*/
void prnPrev(IteratorG it, void (*fp) (void *p) ){
  void *prevP = previous(it);
  assert(prevP != NULL);
  printf("> Previous value is: "); 
  fp(prevP);
  printf("\n"); 
}

/* Prints next element using the given function 'fp'
   examples:   prnNext(it1, prnInt); prnNext(it2, prnStr);
*/
void prnNext(IteratorG it, void (*fp) (void *p) ){
  void *nextP = next(it);
  assert(nextP != NULL);
  printf("> Next value is: "); 
  fp(nextP);
  printf("\n"); 
}

/* Prints elements of 'it' from current to last position 
   using the given function 'fp'. The current position 
   of 'it' will change to the end of the list.
   examples: prnIt(it1, prnInt); prnIt(it2, prnStr);
*/
void prnIt(IteratorG it, void (*fp) (void *p) ){
  int count = 0;
  while(hasNext(it)){
    void *nextP = next(it); 
    count++;
    if(count > 1) { printf(", "); }
    fp(nextP);      
  }
  printf("\n"); 
}


/* Few Tests Below  */

void test1(){
  printf("\n--====  Test-01       ====------\n");
  IteratorG it1 = newIterator(positiveIntCompare, positiveIntNew,  positiveIntFree);
  int a[MAXARRAY] = { 25, 78, 6, 82 , 11};
  for(int i=0; i<MAXARRAY; i++){
    int result = add(it1 , &a[i]); 
    printf("> Inserting %d: %s \n", a[i], (result==1 ? "Success" : "Failed") );
  }
  freeIt(it1);
  printf("--====  End of Test-01 ====------\n");
}

void test2(){
  printf("\n--====  Test-02       ====------\n");
  IteratorG it1 = newIterator(positiveIntCompare, positiveIntNew, positiveIntFree);
  int a[MAXARRAY] = { 72, 14, 62, 8, 93};
  for(int i=0; i<MAXARRAY; i++){
    int result = add(it1 , &a[i]); 
    printf("> Inserting %d: %s \n", a[i], (result==1 ? "Success" : "Failed") );
  }

  prnNext(it1, prnInt);
  prnNext(it1, prnInt);
  prnPrev(it1, prnInt);

  int newVal1 = 55;
  int result1 = set(it1, &newVal1);
  printf("> Set value: %d ; return val: %d \n", newVal1,  result1 );  

  prnPrev(it1, prnInt);

  freeIt(it1);
  printf("--====  End of Test-02 ====------\n");
}



int main(int argc, char *argv[])
{


  test1();
  test2();

  return EXIT_SUCCESS;

}

最佳答案

add函数中,当您第一次添加时,it->currnull并且它使temp ->next 指向自身,不为 null,因此链表似乎没有尽头:

您的原始代码:

 if(it->curr==NULL)
 {
    it->curr=temp; // the current element is the add element
    it->tail=it->head=it->curr;
  }  

  temp->next=it->curr; // for the first element, it->curr is already valued to temp : temp->next points to temp :(

add 函数可以是:

// add node to list from front 
int  add(IteratorG it, void *vp){

  Node *temp;
  if ((temp = malloc(sizeof(Node))) == NULL) { 
    return 0; 
  }

  temp->value = it->newElm(vp);

  temp->prev = null;
  temp->next = it->curr;
  if (it->curr != NULL)
      it->curr->prev = temp;
  it->curr = temp;
  it->head = it->curr;
  return 1;
}

而且,我知道这不是您所要求的,但是 nextprevious 中存在丑陋内存泄漏功能...

关于c - 调用 next() 时最后一个元素不断重复。不返回 NULL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49912688/

相关文章:

java - 为什么我不能只执行 node = node.next 来迭代链表?

java - 我想找到链表之间的数字

java - Java中向循环双向链表添加节点

c - 变量声明上的函数

只调用一个函数并让其他函数访问它的返回值?

java - int/String 链表和变量的问题

linked-list - Ocaml双链表: remove a node satisfying a condition from a double linked list

c - 在 if 语句 poll() block 中,每个请求触发函数多次

c - Eclipse/Neon.2 忽略源文件

c# - 如何将 int 值转换为等效的泛型类型参数,例如 char?