Related
A Program to implement Queue ADT using C
Declaring the headers in .c file or header file doesn't change anything in the errors
1) Header File (queue.h)
#ifndef QUEUE
#define QUEUE
#include <stdio.h>
#include <stdlib.h>
typedef struct QNodeType
{
char ch;
struct QNodeType *next;
}QNode;
typedef struct QueueType
{
QNode *head,*tail;
}Queue;
Queue **Create_Queue(); // Initialize the queue
void ClearQueue(); // Remove all items from the queue
int Enqueue(Queue **q,char ch); // Enter an item in the queue
char Dequeue(Queue **q); // Remove an item from the queue
int isEmpty(Queue **q); // Return true if queue is empty
int isFull(Queue **q); // Return true if queue is full
// Define TRUE and FALSE if they have not already been defined
#ifndef FALSE
#define FALSE (0)
#endif
#ifndef TRUE
#define TRUE (!FALSE)
#endif
#endif
2) .c File for defining the queue functions
#include "queue.h"
Queue** Create_Queue()
{
Queue **q;
(*q)->head = (*q)->tail = NULL;
return q;
}
void ClearQueue(Queue **q)
{
QNode *temp;
while((*q)->head != NULL)
{
temp = (*q)->head;
(*q)->head = (*q)->head->next;
free(temp);
}
(*q)->head = (*q)->tail = NULL; // Reset indices to start over
}
int Enqueue(Queue **q,char ch)
{
QNode *temp;
if(isFull(q)) return FALSE;
temp = (QNode *)malloc(sizeof(QNode));
temp->ch = ch;
temp->next = NULL;
if((*q)->head == NULL)
(*q)->head = (*q)->tail = temp;
else
{
(*q)->tail->next = temp; // Insert into the queue
(*q)->tail = temp; // Set tail to new last node
}
return TRUE;
}
char Dequeue(Queue **q)
{
char ch;
QNode *temp;
if(isEmpty(q)) return '\0';
else
{
ch = (*q)->head->ch;
temp = (*q)->head;
(*q)->head = (*q)->head->next;
free(temp);
if(isEmpty(q))
{
(*q)->head = (*q)->tail = NULL;
}
}
return ch;
}
int isEmpty(Queue **q)
{
return ((*q)->head == NULL);
}
int isFull(Queue **q)
{
return FALSE;
}
3) Driver program or the main code
#include "queue.h"
int main()
{
char testString[27];
int i;
char ch;
Queue **q=Create_Queue();
Enqueue(q,'A');
printf("Enqueued: %c\n", Dequeue(q));
strcpy(testString, "abcdefghijklmnopqrasuvwxyz");
i = 0;
printf("Testing enqueuing of string: %s\n", testString);
while(testString[i] != '\0')
{
if(!Enqueue(q,testString[i]))
{
printf("Queue is full. Unable to enqueue %c\n", testString[i]);
}
i++;
}
printf("Dequeued letters are...\n");
while((ch = Dequeue(q)) != '\0') // Dequeue returns null terminator
printf("%c", ch); // when queue is empty
printf("\nEnd of queue encountered...\n");
return 0;
}
The above program shows segmentation fault when run on Linux and an arbitrary return value when run on dev c++.
But when I run the code without the QUEUE Structure(basically this means declaring a *head and *tail pointer of static type in the queue.c file which allows for only one queue to be created at a time. And thus the CreateQueue function will be of void type and other functions doesn't require an argument of type Queue**)) it ran without any bugs.
I think that the problem is in create_Queue() you are not allocating any memory in it, after that in void ClearQueue() you are using free().
Hi am trying to create a generic list iterator that stores elements of integer or string.I am trying to test a case where it calls the IteratorG advance(IteratorG it, int n) function which takes in the list it and if n is a positive integer,it advances(moves) towards the first element by n times.If n is negative,it advances towards the last element in the list by n times.The elements are then copied to a newly created list lis and the list returned.If advancing by n times is not possible,the function returns NULL.
This is tested in test case 3 under the test cases below.
However,it is responding with a segmentation fault error and i tried using gdp to diagnose the problem and i suspect it is from the advance function at the line add(lis,&(tem->value));
This is the advance function:
IteratorG advance(IteratorG it, int n){
int zero;
zero=0;
IteratorG lis;
lis = malloc(sizeof (struct IteratorGRep));
assert (lis != NULL);
lis->numofit = 0;
lis->head = NULL;
lis->tail = NULL;
lis->curr = NULL;
Node *tem;
if ((tem = malloc(sizeof(Node))) == NULL) {
return 0;
}
if(n<0 && distanceFromStart(it)!=0 )
{
for(tem=it->curr;n!=zero;it->curr=it->curr->prev)
{
add(lis,&(tem->value));
zero++;
}
return lis;
}
if(n>0 && distanceToEnd(it)!=0)
{
for(tem=it->curr;n!=zero;it->curr=it->curr->next)
{
add(lis,&(tem->value));
zero++;
}
return lis;
}
//To be implemented
//move forward by n times
return NULL;
}
I am using a Linux environment and the errors are indicative from the results. The rest of the functions that are required to test this(test in test case 3 under the test code) should be working fine.Here is the code for the whole program:
#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;
}
Node *tempe;
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->head=it->tail=temp;
it->curr=temp;
}
else
{
tempe=it->curr;
tempe->prev=temp;
temp->next=tempe;
it->curr=tempe;
it->curr=temp;
it->head=temp;
}
//it->tail=it->head=it->curr;
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(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;
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;
return 1;
}
// change previous node value with new
return 0;
}
IteratorG advance(IteratorG it, int n){
int zero;
zero=0;
IteratorG lis;
lis = malloc(sizeof (struct IteratorGRep));
assert (lis != NULL);
lis->numofit = 0;
lis->head = NULL;
lis->tail = NULL;
lis->curr = NULL;
Node *tem;
if ((tem = malloc(sizeof(Node))) == NULL) {
return 0;
}
if(n<0 && distanceFromStart(it)!=0 )
{
for(tem=it->curr;n!=zero;it->curr=it->curr->prev)
{
add(lis,tem);
zero++;
}
return lis;
}
if(n>0 && distanceToEnd(it)!=0)
{
for(tem=it->curr;n!=zero;it->curr=it->curr->next)
{
add(lis,&(tem->value));
zero++;
}
return lis;
}
//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
}
This is the header file for the code:
#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
One of the functions have yet to be implemented and is indicated in the code itself. But I guess that might not be the source of issue here.
EDIT:
heres the test case code. Theres no errors in the test case code just in the program above only :
#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");
}
void test3(){
printf("\n--==== Test-03 ====------\n");
IteratorG it1 = newIterator(positiveIntCompare, positiveIntNew, positiveIntFree);
int a[MAXARRAY] = { 04, 54, 15, 12, 34};
for(int i=0; i<MAXARRAY; i++){
int result = add(it1 , &a[i]);
printf("> Inserting %d: %s \n", a[i], (result==1 ? "Success" : "Failed") );
}
reset(it1);
printf("> it1 (after reset): \n");
prnIt(it1, prnInt);
reset(it1);
IteratorG advIt1 = advance(it1, 4);
printf("> advance(it1, 4) returns: \n");
prnIt(advIt1, prnInt);
//IteratorG advIt2 = advance(it1, -3);
//printf("> advance(it1, -3) returns: \n");
//prnIt(advIt2, prnInt);
//printf("> In 'it1', ");
//prnPrev(it1, prnInt);
freeIt(it1);
//freeIt(advIt1);
//freeIt(advIt2);
printf("--==== End of Test-03 ====------\n");
}
int main(int argc, char *argv[])
{
test1();
test2();
test3();
return EXIT_SUCCESS;
}
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include "locker.h"
void QueueInit(Queue* p)
{
p->front = NULL;
p->rear = NULL;
}
int QIsEmpty(Queue* p)
{
if(p->front == NULL)
{
return 1;
}
return 0;
}
void Enqueue(Queue* p, int data)
{
Node* newNode = (Node*)malloc(sizeof(Node));
newNode->next = NULL;
newNode->id = data;
if(QIsEmpty(p))
{
p->front = newNode;
p->rear = newNode;
} else {
p->rear->next = newNode;
p->rear = newNode;
}
}
void attachEnqueue(Queue* p, int user_id)
{
Node* temp = p->front;
temp->user_id = user_id;
p->front = temp;
printf("Locker %d Owned By %d\n", temp->id, temp->user_id);
temp->owned = 1;
temp = temp->next;
}
int Dequeue(Queue* p)
{
Node* temp = p->front;
uint16_t item;
if(QIsEmpty(p))
{
printf("No element exists!");
exit(0);
} else {
item = temp->id;
p->front = temp->next;
free(temp);
if(temp == NULL)
{
p->rear = NULL;
}
return (item);
}
}
void printList(Queue* p)
{
Node* v = p->front;
while(v != NULL){
printf("Locker: %d\n", v->id);
v = v->next;
}
}
int count (Queue p)
{
int c = 0 ;
Node* temp = p.front ;
while ( temp != NULL )
{
temp = temp->next;
c++ ;
}
return c ;
}
void SearchQueue(Queue* p, int val1)
{
Node* v = p->front;
int sw = 0;
while( v != NULL)
{
if(v->id == val1)
{
printf("Locker ID: %d\n", val1);
printf("Lock Status: locked\n");
if(v->owned == 0){
printf("unowned\n");
} else if(v->owned == 1)
{
printf("owned by %d\n", v->user_id);
}
sw = 1;
}
v = v->next;
}
if(!sw)
{
printf("locker %d does not exists\n", val1);
}
}
int main(int argc, char* argv[])
{
Queue queue;
QueueInit(&queue);
char input[50];
char command[20];
int val1;
uint16_t id = 1;
while(1)
{
scanf(" %49[^\n]s", input);
sscanf(input, "%s %d", &command, &val1);
if(strcmp(command, "CREATE") == 0)
{
printf("New Locker created: %d\n", id);
Enqueue(&queue, id);
id++;
} else if(strcmp(command, "DISPLAY") == 0)
{
SearchQueue(&queue, val1);
} else if(strcmp(command, "ATTACH") == 0)
{
attachEnqueue(&queue, val1);
} else if(strcmp(command, "DISPLAYALL") == 0)
{
printList(&queue);
}else if(strcmp(command, "DELETE") == 0)
{
printf("Deleted the locker, %d\n",Dequeue(&queue));
}else if(strcmp(command, "QUIT") == 0)
{
printf("Good Bye!\n");
exit(0);
}
continue;
}
return 0;
}
This is what I have so far and the contents for "locker.h" is:
#ifndef LOCKER_H
#define LOCKER_H
#include <stdint.h>
typedef struct locker_t {
uint16_t id;
uint16_t user_id;
uint8_t locked;
uint8_t owned;
int write_fd;
int read_fd;
struct locker_t* next;
}Node;
typedef struct queue_t {
Node* front;
Node* rear;
size_t size;
}Queue;
#endif
Everything works fine except for the attachEnqueue part.
The purpose is, when I create locker 1 and locker 2 and input ATTACH 20,
locker 1's owner should be 20 and again if I input ATTACH 30, locker 2`s owner should be 30.
However, when I create 2 lockers and firstly ATTACH 20 and then again input ATTACH 30, the locker 1's owner`s value only changes from 20 to 30, not assigning the 30 owner to locker 2.
I am 100% sure that the attachEnqueue function involves the wrong contents but I am really not sure how to modify it..
Also, I need to include a "LOCK" command to make the locker whether to be locked or unlocked, but the problem is, school wants me to do this by using signal SIGUSR. How should I use the signal function to lock or unlock the locker? Would pthread.mutex.lock and unlock work?
Any help or advice would be very thankful!
The comment is right. The last line of attachEnqueue is temp = temp->next;
Maybe you assume temp keeps that information in mind next time you call the function, but right now, absolutely not. This line is of no use, the next time, temp will be assigned to the front of the queue.
To go around that, you may create a flag in your struct as stated above, add a counter argument to your function to keep track of which element in your queue to attach, or make temp a static argument, so its state persists between calls.
I apologise if this concept has been explained on SOF before! I believe my case is slightly different and couldn't find a similar question in the website.
Here's the problem:
I'm trying to store char arrays (strings) in a Queue structure that I'm trying to implement.
The structure and its functions seem to work fine when I hardcode the data myself like this:
#include "Time.h"
#include <unistd.h>
int main(void){
struct Queue* q = CreateQueue();
Enqueue(q, "element1");
Enqueue(q, "element2");
Enqueue(q, "element3");
Enqueue(q, "element4");
PrintAll(q->first); // this outputs all elements and the time they've been in the queue.
return 0;
}
The output is as expected, a list of all 4 elements.
However, as soon as I put a simple menu together, to capture the data from the user instead of it being hardcoded as above, the PrintAll() function outputs a duplicate of the very last element enqueued. You also notice that I am timing each node to keep a track on when it was added to the queue and that seem to work fine. Although the ouput shows the last element entered duplicated N times (N being the size of the queue) the timer seems to show correctly for each node!
I am suspecting it's to do with the stdin stream that is not being cleaned but I thought I handled that with a block of code that is shown in main() function.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void){
char name[31];
char c;
int option;
int ch;
struct Queue* q = CreateQueue();
do
{
printf("\n 1. Add a an element to the queue");
printf("\n 2. Print all elements");
printf("\n 0. Exit");
printf("\n Please select an option");
while(scanf("%d", &option)!=1){
puts("Value non good");
ch=getchar();
while(ch!=EOF && ch!='\n'){
ch=getchar();
}
}
switch(option)
{
case 1:
{
ch=getchar();
while(ch!=EOF && ch!='\n')
{
ch=getchar();
}
printf("Please enter the name of the element.\n ");
fgets(name,30,stdin);
Enqueue(q, name);
PrintAll(q->first);
break;
}
case 2:
{
PrintAll(q->last);
break;
}
default:
return 0;
}
}while(option != 0);
return 0;
}
Can anybody please shed light on the problem ? I would appreciate it.
here's the rest of the code:
Time.c:
#include "Time.h"
struct Queue* CreateQueue()
{
struct Queue* q = malloc(sizeof(struct Queue));
q->first = NULL;
q->last = NULL;
q->size = 0;
return q;
}
void Enqueue(struct Queue* queue, char* string)
{
struct Node* newNode = malloc(sizeof(struct Node));
newNode->next = NULL;
newNode->student = string;
newNode->start_time = time(0);
if(queue->size == 0)
{
queue->first = newNode;
}
else
{
queue->last->next = newNode;
}
queue->last = newNode;
queue->size = queue->size + 1;
}
char* Dequeue(struct Queue* queue)
{
if (queue->size < 0)
{
exit(0);
}
char* toBeRemoved = queue->first->student;
struct Node* oldNode = queue->first;
queue->first = oldNode->next;
queue->size = queue->size - 1;
if(queue->size == 0)
{
queue->last = NULL;
}
free(oldNode);
return toBeRemoved;
}
int IsEmpty(struct Queue *q)
{
return q->size == 0;
}
char* Peek(struct Queue *q)
{
return q->first->student;
}
void PrintOne(struct Node *node)
{
if(node !=NULL)
{
int elapsed = ElapsedTime(node);
printTime(elapsed, node->student);
//printf("%s\n", node->student);
}
}
void PrintAll(struct Node* node)
{
if (node !=NULL)
{
PrintAll(node->next);
PrintOne(node);
}
}
// returns the waiting time for a student node.
int ElapsedTime(struct Node* node)
{
int elapsed;
time_t stop_time;
stop_time = time(NULL);
elapsed = difftime( stop_time , node->start_time );
return elapsed;
}
void printTime(int elapsed, char* student_name)
{
printf("%s : waiting for ", student_name);
int minutes_or_hours = 0; //Stores a zero to indicate that it is not neccesary to print minutes or hours.
//Stores a one to indicate that hours and/or minutes have been printed.
if( (elapsed / 3600) >= 1)
{
int hours = elapsed/3600;
if(hours == 1)
{
printf("1 hour, ");
}
else
{
printf("%d hours, ", hours);
}
elapsed = elapsed - (hours*3600);
minutes_or_hours = 1;
}
if( (elapsed / 60) >= 1)
{
int minutes = elapsed/60;
if(minutes == 1)
{
printf("1 minute, ");
}
else
{
printf("%d minutes, ", minutes);
}
minutes_or_hours = 1;
elapsed = elapsed - (minutes*60);
}
if(minutes_or_hours == 1)
{
printf("and ");
}
printf("%d seconds\n", elapsed);
}
Time.h:
#ifndef TIME_H_
#define TIME_H_
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
struct Node
{
time_t start_time;
struct Node* next;
char* student;
};
struct Queue
{
int size;
struct Node* first;
struct Node* last;
};
struct Queue* CreateQueue();
void Enqueue(struct Queue* , char* );
char* Dequeue(struct Queue* );
int IsEmpty(struct Queue *);
char* Peek(struct Queue *);
void PrintOne(struct Node *);
void PrintAll(struct Node *);
int ElapsedTime(struct Node* );
void printTime(int , char* );
#endif /* TIME_H_ */
In the function Enqueue() you have only copied the string pointer to your structure. In your first case that works, because all the four strings have different pointers to string literals. But in your second example, you are storing the pointer of your data entry name, and the contents of this string change with each entry. Each structure store the same pointer, so all point to the most recent string you typed in. If your struct stored the actual string, it would work (but you need to be careful with string lengths).
struct Node
{
time_t start_time;
struct Node* next;
char student[31];
};
void Enqueue(struct Queue* queue, char* string)
{
...
strncpy (newNode->student, 30, string);
...
}
I've got a programming class assignment due tonight at 8 PM CDT that I'm having trouble with. We are to take a list of the following numbers via reading a file:
9
30
20
40
35
22
48
36
37
38
place them in an array (easy enough), and then read these into a binary search tree using C. The first number in the list is the number of elements in the tree. The rest are placed into the following struct:
typedef struct node_struct {
int data;
struct node_struct* left;
struct node_struct* right;
} Node;
I think I've got the first part down pat. Take the stuff in using fscanf (I didn't choose to use this method, I like fgets better), call an insertion function on each member of the array, then call a "createNode" function inside the insertion function.
Problem is, I'm only getting one member into the BST. Furthermore, the BST must satisfy the condition node->left->data <= node->data < node->right->data... in other words, the nodes must be in order in the tree.
Here's what I have so far:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// def BST node struct
typedef struct node_struct {
int data;
struct node_struct* left;
struct node_struct* right;
} Node;
// prototypes
Node* createNode(int data);
Node* bstInsert(Node* root, int data);
// helper function prototypes
void padding(char ch, int n);
void displayTree(Node* root, int depth);
int main(int argc, char **argv)
{
FILE *in = NULL;
int num_read, count=0, array_size = 0;
if(argc != 2){
printf("hw3 <input-file>\n");
return 1;
}
in = fopen(argv[1], "r");
if(in == NULL){
printf("File can not be opened.\n");
return 2;
}
// read in the first line to get the array size
fscanf(in, "%d", &array_size);
// declare the array
int array[array_size];
// read from the second line to get each element of the array
while(!feof(in)){
fscanf(in, "%d", &num_read);
array[count] = num_read;
count++;
}
fclose(in);
if (array_size != count) {
printf("data error. Make sure the first line specifies the correct number of elements.");
return 3;
}
Node *root1 = NULL, *root2 = NULL, *root3 = NULL;
int i;
// task1: construct a bst from the unsorted array
printf("=== task1: construct a bst from the unsorted array ===\n");
for (i = 0; i < array_size; i++) {
root1 = bstInsert(root1, array[i]);
}
displayTree(root1, 0);
return 0;
}
Node* bstInsert(Node* root, int data) {
if(root == NULL){
root = createNode(data);
if(root != NULL){
root= createNode(data);
}
else{
printf("%d not inserted, no memory available.\n", data);
}
}
Node* current, previous, right;
current = root;
previous = root->left;
next = root->right;
else{
if(previous->data <= current->data){
}
}
return root;
}
Node* createNode(int data) {
// TODO
Node* aRoot;
if(!data)
return NULL;
aRoot = malloc(sizeof(Node));
if(!aRoot){
printf("Unable to allocate memory for node.\n");
return NULL;
}
aRoot->data = data;
aRoot->left = NULL;
aRoot->right = NULL;
return aRoot;
}
/* helper functions to print a bst; You just need to call displayTree when visualizing a bst */
void padding(char ch, int n)
{
int i;
for (i = 0; i < n; i++)
printf("%c%c%c%c", ch, ch ,ch, ch);
}
void displayTree(Node* root, int depth){
if (root == NULL) {
padding (' ', depth);
printf("-\n");
}
else {
displayTree(root->right, depth+1);
padding(' ', depth);
printf ( "%d\n", root->data);
displayTree(root->left, depth+1);
}
}
main, createNode, displayTree, and padding are okay, I believe. It's bstInsert where I'm having trouble. I'm just not sure how to order things to create a valid tree.
EDIT:
I've edited bstInsert and injected some more logic. It should be printing out more leaves on the tree, but alas, it's only printing out the number "30". Here's the new function.
Node* bstInsert(Node* root, int data) {
if(root == NULL){
root = createNode(data);
if(root != NULL){
root= createNode(data);
}
else{
printf("%d not inserted, no memory available.\n", data);
}
}
else{
if(data < root->data){
bstInsert(root->left, data);
}
else if(data > root->data || data == root->data){
bstInsert(root->right, data);
}
}
return root;
}
You have to assign the newly created node pointer to the correct part of the tree. This code does that. The key change is using the return value from bstInsert() correctly. The other changes are cosmetic. Note that I checked the input array by printing it out; also, it is sensible to print out the BST as you build it.
Don't use feof() as a loop control condition. It is almost invariably wrong when used as a loop control, but at least you have to also check the input operation that follows. I've written a lot of programs in my time; I've hardly ever used feof() (I found two places in my own code with it; in both, it was correctly used to distinguish between EOF and an error after an input had failed.)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// def BST node struct
typedef struct node_struct
{
int data;
struct node_struct* left;
struct node_struct* right;
} Node;
// prototypes
Node *createNode(int data);
Node *bstInsert(Node *root, int data);
// helper function prototypes
void padding(char ch, int n);
void displayTree(Node *root, int depth);
int main(int argc, char **argv)
{
FILE *in = NULL;
int num_read, count=0, array_size = 0;
if (argc != 2)
{
printf("hw3 <input-file>\n");
return 1;
}
in = fopen(argv[1], "r");
if (in == NULL)
{
printf("File can not be opened.\n");
return 2;
}
// read in the first line to get the array size
fscanf(in, "%d", &array_size);
// declare the array
int array[array_size];
// read from the second line to get each element of the array
while (count < array_size && fscanf(in, "%d", &num_read) == 1)
array[count++] = num_read;
fclose(in);
if (array_size != count)
{
printf("data error. Make sure the first line specifies the correct number of elements.");
return 3;
}
for (int i = 0; i < array_size; i++)
printf("%d: %d\n", i, array[i]);
Node *root1 = NULL;
// task1: construct a bst from the unsorted array
printf("=== task1: construct a bst from the unsorted array ===\n");
for (int i = 0; i < array_size; i++)
{
root1 = bstInsert(root1, array[i]);
displayTree(root1, 0);
}
displayTree(root1, 0);
return 0;
}
Node *bstInsert(Node *root, int data)
{
if (root == NULL)
{
root = createNode(data);
if (root == NULL)
printf("%d not inserted, no memory available.\n", data);
}
else if (data < root->data)
root->left = bstInsert(root->left, data);
else
root->right = bstInsert(root->right, data);
return root;
}
Node *createNode(int data)
{
Node *aRoot;
aRoot = malloc(sizeof(Node));
if (!aRoot)
{
printf("Unable to allocate memory for node.\n");
return NULL;
}
aRoot->data = data;
aRoot->left = NULL;
aRoot->right = NULL;
return aRoot;
}
/* helper functions to print a bst; You just need to call displayTree when visualizing a bst */
void padding(char ch, int n)
{
for (int i = 0; i < n; i++)
printf("%c%c%c%c", ch, ch, ch, ch);
}
void displayTree(Node *root, int depth)
{
if (root == NULL) {
padding (' ', depth);
printf("-\n");
}
else {
displayTree(root->right, depth+1);
padding(' ', depth);
printf ( "%d\n", root->data);
displayTree(root->left, depth+1);
}
}
Ok, think about what you want to do in the different tree configurations:
when the tree is empty -> create a root node
when the tree isn't empty -> how do the value to be inserted and the value of the root compare?
above -> insert in the right subtree
below -> insert in the left subtree
equal -> do nothing (this actually depends on how your assignment tells you to treat duplicates)
From this basic algorithm, you should be able to figure out all the corner cases.
A simplified solution (naive insertion with recursion, data input noise removed):
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
static int nums[] = { 6, 8, 4, 1, 3, 7, 14, 10, 13 }; // instead of the user input
typedef struct _node {
int value;
struct _node *left;
struct _node *right;
} node;
node *node_new(int v)
{
node *n = malloc(sizeof(*n));
assert(n);
n->value = v;
n->left = NULL;
n->right = NULL;
return n;
}
void insert(node **tree, node *leaf)
{
if (*tree == NULL) {
*tree = leaf;
} else if (leaf->value > (*tree)->value) {
insert(&((*tree)->right), leaf);
} else {
insert(&((*tree)->left), leaf);
}
}
void dump(node *tree, int level)
{
static const char *pad = "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t";
if (tree != NULL) {
printf("%sSelf: %d\n", pad + 16 - level, tree->value);
if (tree->left) {
printf("%sLeft node:\n", pad + 16 - level);
dump(tree->left, level + 1);
}
if (tree->right) {
printf("%sRight node:\n", pad + 16 - level);
dump(tree->right, level + 1);
}
} else {
printf("%sEmpty\n", pad + 16 - level);
}
}
int main()
{
size_t n = sizeof(nums) / sizeof(*nums);
int i;
node *tree = NULL;
for (i = 0; i < n; i++) {
insert(&tree, node_new(nums[i]));
}
dump(tree, 0);
// give some work to the kernel
return 0;
}
You should consider doing this recursively. Remember that each node is a tree in itself:
#include <stdio.h>
#include <stdlib.h>
typedef struct tree_struct {
int value;
struct tree_struct* left;
struct tree_struct* right;
} Tree;
Tree* addToTree(int value, Tree* tree)
{
if (tree == NULL) {
tree = malloc(sizeof(Tree));
tree->value = value;
tree->left = NULL;
tree->right = NULL;
} else {
if (value < tree->value) {
tree->left = addToTree(value, tree->left);
} else {
tree->right = addToTree(value, tree->right);
}
}
return tree;
}
int main(int argc, char** argv)
{
Tree* tree = NULL;
int in;
while (scanf("%d", &in) != EOF) {
tree = addToTree(in, tree);
}
return 0;
}