1

I am a new to C and currently trying to learn how to build a iterator for C. I set myself this question:

Create a queue program that stores a variable Data in it. Data contains char* name, int classroom, int labroom. Load the following data into the program:

Name:RP-SIT, Labs:4, Classrooms:20
Name:NP-SIT, Labs:6, Classrooms:30
Name:NYP-SIT, Labs:12, Classrooms:60
Name:SP-SIT, Labs:4, Classrooms:12
Name:NUS-Yale, Labs:50, Classrooms:60

This is the program that I built:

typedef struct data{
        char* name;
        int classroom;
        int labroom;
    }Data;

    typedef struct queue_element{
        Data d;
        struct queue_element* next;
    }Node;

    typedef struct queue{
        Node* first;
        Node* last;
        int count;
    }Queue;
Queue* Create(){
    Queue* q = (Queue*)malloc(sizeof(Queue));

    if(q){
        q->first = NULL;
        q->last = NULL;
        q->count = 0L;
    }

    return q;
}

int Enqueue(Queue* q, Data d){
    Node* n = (Node*)malloc(sizeof(Node));
    if(!n)
        return 0;
    n->next = NULL;
    n->d = d;

    if(q->count++ == 0){
        q->first = n;
    }

    else{
        q->last->next = n;
    }
    q->last = n;
    return 1;
}

Data Dequeue(Queue* q){
    Node* n;
    Data d;

    if(q->count == 0)
        return d;

    n = q->first;
    d= n->d;

    q->first = n->next;
    free(n);
    q->count--;
    q->last = NULL;

    return d;
}

int main(int argc, char* argv[]){
    Queue* q;
    Data d1 = {"RP-SIT", 20, 4},d2 = {"NP-SIT", 30, 6}, d3 = {"NYP-SIT",60,12}, d4={"SP-SIT", 12, 4}, d5 = {"NUS-Yale", 60, 50};


    if((q=Create()) == NULL){
        printf("Error creating Queue");
        exit(1);
    }

    if(!Enqueue(q,d1)){
        printf("Error enqueuing data");
        exit(1);
    }
    if(!Enqueue(q,d2)){
        printf("Error enqueuing data");
        exit(1);
    }
    if(!Enqueue(q,d3)){
        printf("Error enqueuing data");
        exit(1);
    }
    if(!Enqueue(q,d4)){
        printf("Error enqueuing data");
        exit(1);
    }
    if(!Enqueue(q,d5)){
        printf("Error enqueuing data");
        exit(1);
    }
    Data d;
    for(int i = 0; i<5; i++){
        d = Dequeue(q);
        printf("Name:%s, Labs:%d, Classrooms:%d\n",d.name, d.labroom, d.classroom);
    }
    return 1;
}

I am trying to add in a function that makes use of a Iterator to display the information without popping the information out of the Queue. This is my iterator code:

typedef struct iterator{
    long next;
    long size;
    void* *elements;
}Iterator;

Iterator* Iter_Create(void* *elements, long size){
    Iterator* it = (Iterator*)malloc(sizeof(Iterator));

    if(it){
        it->next = 0L;
        it->size = size;
        it->elements = elements;
    }
    return it;
}

int it_hasNext(Iterator* it){
    return((it->next<it->size)? 1: 0);
}

void* it_Next(Iterator* it, void* elements){
    if(it->next < it->size){
        elements = it->elements[it->next++];
    }

    return elements;
}

void it_Destroy(Iterator* it){
    free(it->elements);
    free(it);
}

I used this code in main to display the information retrieved.

Data* de;
Iterator* it = Iter_Create(q, q->count);

while(it_hasNext(it) == 1){
    de = it_Next(it,q);
    printf("Name:%s, Labs:%d, Classrooms:%d\n",de->name, de->labroom, de->classroom);
}

it_Destroy(it);

This is where I need all your help. I can't figure out why I am getting this segmentation fault when displaying the data. This is my output with the iterator code added:

Name:RP-SIT, Labs:4, Classrooms:20
Name:NUS-Yale, Labs:50, Classrooms:60
Segmentation fault: 11

Sorry for the long question but I wanted to be as clear as I can be. Thanks for the help!

Bocky
  • 483
  • 1
  • 7
  • 27
  • 3
    Welcome to Stack Overflow! It sounds like you may need to learn how to use a debugger to step through your code. With a good debugger, you can execute your program line by line and see where it is deviating from what you expect. This is an essential tool if you are going to do any programming. Further reading: [How to debug small programs](http://ericlippert.com/2014/03/05/how-to-debug-small-programs/). – Paul R Apr 13 '16 at 14:35
  • 1
    Have you tried a debugger, or at least some log output, to track *where exactly* your program segfaults? Or have you just gone "segfault, can't find it by staring at it, post to SO"? – DevSolar Apr 13 '16 at 14:35
  • 2
    `de = (Data*)malloc(sizeof(Data)); de = it_Next(it,q);` -- That's a memory leak. You allocate memory, then overwrite the pointer to it. – DevSolar Apr 13 '16 at 14:37
  • 2
    Note: They say [you shouldn't cast the result of `malloc()` in C](http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc). – MikeCAT Apr 13 '16 at 14:40
  • 1
    Passing `long` to `%d` in `printf()` invokes *undefined behavior*. Use `%ld` instead. – MikeCAT Apr 13 '16 at 14:41
  • @DevSolar I wasn't taught to use a IDE so I would have no idea how to use it. I wrote this code by hand and tested it using gcc in linux, so here I am asking for help. I appreciate the need to knock a learning student down though. – Bocky Apr 13 '16 at 14:46
  • 1
    @Bocky: No need to be defensive about it. I was talking about a debugger, not an IDE, which is two different things. GDB, for example, works just fine on the command line, although the ncurses-based UI you get with `-tui` really helps. If you were taught C, but not taught the use of a debugger, talk to your instructor and tell him to include debugger use in his course. Placing log `printf()`s into code to show what exactly happens, and at which point the program actually fails, is even simpler than using a debugger. (Although not as effective.) – DevSolar Apr 13 '16 at 14:50
  • 1
    You write, "I used this code in main to display the information retrieved." If I put that code into your `main()`, I get `warning: passing argument 1 of ‘Iter_Create’ from incompatible pointer type`, `expected ‘void **’ but argument is of type ‘struct Queue *’`? – DevSolar Apr 13 '16 at 14:53
  • @DevSolar I am not here to debate, so lets go back to the question. I did place printf code in it, I just can't figure out why it can print out the data properly for the first 2 rounds. I can confirm that count in Queue is 5, and the size of the Iterator started from 0, hangs at 1(before entering the third loop). *I fixed the statement you mentioned by casting q to be (void *)q. The error is not there anymore. – Bocky Apr 13 '16 at 14:54
  • 1
    Well, unfortunately I am not able to reproduce your problem given the code you posted (after fixing the includes and the `%ld` mentioned above). – DevSolar Apr 13 '16 at 14:59
  • 1
    run the debugger by hand, like `gdb ./program` and step thru it or just tell it `run` and it will run and crash. on the re-run, step iterativelly until you find out after which instruction it crashes, and perhaps you learn something new. also, there's rarely such a thing as "too long of a question" as long as the provided info is useful. – Shark Apr 13 '16 at 14:59
  • @Shark thanks i will try that! – Bocky Apr 13 '16 at 15:04
  • @DevSolar Does that mean you don't get the error? Thanks for the help anyway and sorry for earlier. – Bocky Apr 13 '16 at 15:04
  • 1
    No, I don't get a segfault out of the source after the mentioned edits (which I did to get rid of compiler warnings on `-Wall -Wextra`, which is why I was asking about the `incompatible pointer type` warning earlier). And I really meant that. A C/C++ course without teaching debugger use is negligent. – DevSolar Apr 13 '16 at 15:06
  • [Here's something you can find useful](http://lldb.llvm.org/lldb-gdb.html) It'll be useful for GDB and LLDB, the iOS debugger. – Shark Apr 14 '16 at 07:35

0 Answers0