C singly linked list using Queue - c

#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.

Related

Memory access violations when trying to read from structs inside of other structs

I am having trouble figuring out how to do this correctly. I have a linked list of nodes then those nodes have pointers put into an array contained in that node. These nodes make up a sort of one-way graph between the nodes. I must then traverse the nodes randomly until the node "Home" is reached.
The main issue I'm having is assigning the graph nodes into the list nodes. I want the function to take in the head of the list, the names of the nodes and the weight (cost to travel between nodes). I'm not sure how to do this correctly and I don't know what I did but I think there's an infinite loop somehow. Any help is greatly appreciated.
The input file is structured as such:
Applebees
GroundRound
BlueMoose
DrunkenNoodle
Home
STOP
Applebees BlueMoose 10
Applebees DrunkenNoodle 13
GroundRound Applebees 2
GroundRound DrunkenNoodle 7
GroundRound Home 52
STOP STOP 0
GroundRound
Ignore the print statements in graphInsert() those are me trying to debug the loops.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
struct graphNode {
char name[100]; // Establishment name
int arcCnt; // Number of outgoing arc from this node
int weights[10]; // Weights of each outgoing arc from this node
struct graphNode* arcs[10]; // Holds other graph nodes that are connected to this node (this node is source)
};
struct listNode {
char name[100]; // Establishment name
struct listNode* next;
struct graphNode* graph; // Pointer into graph
};
void listInsert(struct listNode **head, char name[100]) {
// setup new nodes
struct graphNode* newGraph = (struct graphNode*)malloc(sizeof(struct graphNode));
for (int i = 0; i < 100; i++) {
newGraph->name[i] = name[i];
}
for (int i = 0; i < 10; i++) {
newGraph->arcs[i] = NULL;
}
newGraph->arcCnt = 0;
struct listNode* newNode = (struct listNode*)malloc(sizeof(struct listNode));
for (int i = 0; i < 100; i++) {
newNode->name[i] = name[i];
}
newNode->next = NULL;
newNode->graph = newGraph;
// check if head is NULL
if (*head == NULL) {
*head = newNode;
return;
}
// if the list is populated then add the node to the end
struct listNode* current = *head;
while (current->next != NULL) {
current = current->next;
}
current->next = newNode;
}
void graphInsert(struct listNode** head, char src[100], char dst[100], int weight) {
struct listNode* srcNode = *head;
printf("CALL:");
while (srcNode->next != NULL) { // loop through list to find src
printf("%s %s", srcNode->name, src);
if (strcmp(srcNode->name, src) == 0) { // when it finds the name, find the dst update the graph node data
printf("FOUND");
struct listNode* dstNode = *head;
while (dstNode->next != NULL) { // this loop is to find the pointer to the dst node
printf(" %s %s", dstNode->name, dst);
if (strcmp(dstNode->name, src) == 0) { // when it finds name finally update all the info
printf("FOUND");
// assign the new arc to the right spot based on arcCnt (how many arcs there are), then return to exit the loops
srcNode->graph->arcs[srcNode->graph->arcCnt] = dstNode->graph;
srcNode->graph->weights[srcNode->graph->arcCnt] = weight;
srcNode->graph->arcCnt++;
return;
}
dstNode = dstNode->next;
}
}
srcNode = srcNode->next;
}
}
int main(){
srand(2021);
// setup variables
struct listNode* head = NULL;
struct graphNode* sourceNode = NULL;
FILE* data = fopen("./hw10.data", "r");
int i = 0;
int section = 1; // flag to read the file correctly
// this loop reads the file
while (1) {
char name[100];
char name2[100];
int weight = 0;
if (section == 1) { // reads the first section
fscanf(data, "%100s", name);
if (strcmp(name, "STOP") == 0) { // if end of section then increment section counter
section++;
} else { // if its not the end of the section then add the name to the linked list
listInsert(&head, name);
}
} else if (section == 2) { // reads the first section and builds the graph
fscanf(data, "%100s %100s %d", name, name2, &weight);
if (strcmp(name, "STOP") == 0) { // if end of section then increment section counter
section++;
} else {
//graphInsert(&head, name, name2, weight);
}
} else if (section == 3) { // this section only reads one line and gets the
char tmp[100];
fscanf(data, "%100s", tmp);
struct listNode* current = head;
while (current->next != NULL) { // loop through to find the right node for the name
if (strcmp(current->name, tmp) == 0) { // if names are equal update the node
sourceNode = current->graph;
break;
}
current = current->next;
}
}
if (feof(data)) break;
i++;
}
// debug print data
printf("\n");
struct listNode* current = head;
while (current != NULL) {
printf("%s\n", current->name);
current = current->next;
}
printf("\n");
// starting node
printf("%s ", sourceNode->name);
// now walk through the graph from sourceNode until we reach the node "Home"
int totalWeight = 0;
i = 0;
while (i < 100) {
char* tmp = sourceNode->name;
if (strcmp(tmp, "Home") == 0) { // if were home then exit program
// ending node and cost
printf("%s %d", sourceNode->name, totalWeight);
return 0;
} else { // if were not home then keep looping
int index = (rand() % sourceNode->arcCnt); // Generates random number between 0 and sourceNode->arcCnt
sourceNode = sourceNode->arcs[index];
//printf("Going to: %s, Index: %d", sourceNode->name, totalWeight);
}
i++;
}
return 0;
}

Segmentation fault when using advance function

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;
}

Using getchar() to read text with no trailing newline

I'm working on a program with the goal of reading parentheses/brackets and figuring out if they are balanced on each side, but am running into trouble when reading the last line of text. This may be a little confusing, but I'll attach the input:
3 <-- The number of lines I'll scan
([]) <-- Problem
(([{}])))
([()[]()])()
My program works perfectly when faced with manual input; that is when I input each line myself and press enter. When I copy a block of text though, the program fails to print the final answer (yes or no) unless I press enter. This is my code :
#include <stdio.h>
#include <stdlib.h>
#ifndef status_h
#define status_h
enum status { SUCCESS, FAILURE };
typedef enum status Status;
enum boolean { TRUE, FALSE };
typedef enum boolean Boolean;
#endif
typedef void* NODE;
struct node {
char data;
struct node* next;
} *head;
typedef struct node Node;
void stack_init_default(Node* hStack);
int stack_empty(void);
char stack_top(Node* hStack);
NODE stack_pop(Node* hStack);
NODE stack_push(Node* hStack, char item);
void stack_destroy(void);
int main(int charc, char* argv[])
{
char x;
int num, error = 0, i;
Node* stack;
stack_init_default(stack);
scanf("%d ", &num);
for (i = 0; i < num; i++)
{
stack_destroy();
error = 0;
while ((x = getchar()) != '\n' )
{
if (x == ' ')
continue;
if ((x == '(')||(x == '[')||(x == '{'))
{
stack_push(stack, x);
}
else if ((x == ')')&&(stack_top(stack)=='('))
{
stack_pop(stack);
}
else if ((x == ']')&&(stack_top(stack)=='['))
{
stack_pop(stack);
}
else if ((x == '}')&&(stack_top(stack)=='{'))
{
stack_pop(stack);
}
else
{
error = 1;
}
}
putchar('\n');
if (stack_empty() == 0 || error == 1)
{
printf("No");
}
else
{
printf("Yes");
}
}
printf("\n");
return 0;
}
void stack_init_default(Node* hStack)
{
head = NULL;
}
NODE stack_push(Node* hStack, char item)
{
Node* tmp = (Node*)malloc(sizeof(Node));
if(tmp == NULL)
{
exit(0);
}
tmp->data = item;
tmp->next = head;
head = tmp;
return head;
}
NODE stack_pop(Node* hStack)
{
Node* tmp = head;
head = head->next;
free(tmp);
return head;
}
char stack_top(Node* hStack)
{
if (head == NULL)
{
return '\0';
}
return head->data;
}
int stack_empty(void)
{
return (head == NULL);
}
void stack_destroy(void)
{
Node* phStack = head;
while (head != NULL)
{
phStack = head->next;
free(head);
head = phStack;
}
free(phStack);
head = NULL;
}
My issue looks like this:
3
([])
(([{}])))
([()[]()])()
Yes
No
Yes
So my program outputs yes or no, but freezes on the last problem, waiting for me to press newline to finish the loop. I assume that the issue lies somewhere with the while loop, and that because the pasted text doesn't have a final newline the loop never ends, but I'm unsure how to fix this. Thanks for any help.

Creating a binary search tree in C99

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;
}

Linked List problems with process sync

This program is a work in progress. It is going to simulate a multiprocessor and I am programming it with producer-consumer sync.
Few problems here:
- My pending_request counter starts 1 lower than it should and goes down to -1. It should stop at 0.
- My remove_queue function also keeps removing one over. It will remove until the list is blank, but it doesn't recognize the list is empty. Then if I run remove_queue one more time, then it recognizes the list empty. SAMPLE OUTPUT AT THE BOTTOM at http://tinyurl.com/3ftytol
#include <stdio.h>
#include <pthread.h>
#include <time.h>
#include <stdlib.h>
typedef struct pr_struct{
int owner;
int burst_time;
struct pr_struct *next_prcmd;
} prcmd_t;
static prcmd_t *pr_head = NULL;
static prcmd_t *pr_tail = NULL;
static int pending_request = 0;
static pthread_mutex_t prmutex = PTHREAD_MUTEX_INITIALIZER;
int add_queue(prcmd_t *node)
{ pthread_mutex_lock(&prmutex);
//code
prcmd_t *curNode = pr_head;
if(pr_head == NULL) { pr_head = node; return;}
while(curNode->next_prcmd)
{
curNode = curNode->next_prcmd;
}
curNode->next_prcmd = node;
//
pending_request++;
pthread_mutex_unlock(&prmutex);
return(0);
}
int remove_queue(prcmd_t **node)
{
pthread_mutex_lock(&prmutex);
if(pr_head == NULL)
{
//your code
printf("Queue is empty\n");
//
pthread_mutex_unlock(&prmutex);
return(-1);
}
else
{
//your code
prcmd_t *tempNode; tempNode = (prcmd_t*)malloc(sizeof(prcmd_t));
tempNode = *node;
*node = tempNode->next_prcmd;
free(tempNode);
//
pending_request--;
pthread_mutex_unlock(&prmutex);
return(0);
}
}
int get_number_request(void)
{ return pending_request; }
void display_list(prcmd_t *node)
{
if (pr_head == NULL)
{
printf("List is empty!\n\n");
}
printf("-----------\n");
while(node)
{
printf("%i %i\n", node->owner,node->burst_time);
node = node->next_prcmd;
}
int r = get_number_request();
printf("Pending requests: %i\n", r);
}
int main()
{
int i=0;
int length = 4;
prcmd_t *pr[length];
for(i =0;i<length;i++)
{
pr[i] = (prcmd_t*)malloc(sizeof(prcmd_t));
pr[i]->owner = i+1;
pr[i]->burst_time = i + 2;
add_queue(pr[i]);
}
display_list(pr_head);
remove_queue(&pr_head);
display_list(pr_head);
remove_queue(&pr_head);
display_list(pr_head);
remove_queue(&pr_head);
display_list(pr_head);
remove_queue(&pr_head);
display_list(pr_head);
remove_queue(&pr_head);
display_list(pr_head);
}
some things (although maybe not all):
There is no need for a tail pointer if the list is not doubly linked, because there is no way to go from tail to head (no previous pointer)
Why do you malloc in your remove queue?
*node = prHead;
prHead = prHead->next_prcmd;
--pending_request;
in add_queue you have to node->next_prcmd = NULL; otherwwise you will never know the end.
again, some things, but maybe not all...
Mario

Resources