0

So I'm confident that this c implementation of a linked list is flawed in a few areas. My question is primarily this, though any other help is appreciated; I know that the code will run to completion and print the output properly. However, upon adding another function accessed later in the code, the code will lock up before that point is even reached. I was wondering why this is, and how to fix it. I will include the text from all the files below, but for this assignment in particular I can only edit printandcombine.c and its headerfile.

printandcombine.h:

//Riley Branting
#ifndef PRINTANDCOMBINE_H
#define PRINTANDCOMBINE_H

//Returns a string representation of the struct term_t
char * term_to_string(term_t * term);

//Prints a linkedlist in no specific order
void print_linklist(node_t * curr);

//Returns a new linkedlist that is the result of combining the like terms
node_t * combine_like_terms(const node_t * current_node_ptr);

#endif

printandcombine.c:

// Riley Branting
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "common.h"

// Returns a string representation of the struct term_t
char *term_to_string(term_t *term) {
    // printf("term_to_string 1");

    char *str = malloc((sizeof(int)) * 4);
    // printf("term_to_string 2");

    sprintf(str, "%d%c%d ", term->coefficient, term->var, term->exponent);
    printf("%s", str);

    // printf("term_to_string 3");

    return str;
}

// Prints a linkedlist in no specific order
void print_linklist(node_t *curr) {
    // printf("print_linkedlist 1");
    printf("%s", term_to_string(curr->term));
    // printf("print_linkedlist 2");
    if (!(curr->next_node == NULL)) {
        print_linklist(curr->next_node);
    }
    // printf("print_linkedlist 3");
}

// Returns a new linkedlist that is the result of combining the like terms
node_t *combine_like_terms(const node_t *current_node_ptr) {
    node_t *temp = (node_t *)current_node_ptr;

    node_t *out = malloc(sizeof(node_t));
    node_t *move = out;

    int x = 0;

    while (!(temp == NULL)) {
        if (temp->term->exponent > x) {
            x = temp->term->exponent;
            temp = temp->next_node;
        }
    }
    for (; x >= 0; x--) {
        temp = (node_t *)current_node_ptr;
        int a = 0;
        while (!(temp == NULL)) {
            if (temp->term->exponent == x) {
                a = a + temp->term->coefficient;
            }

            move->term->coefficient = a;
            move->term->var = 'x';
            move->term->exponent = x;
            if (x > 0) {
                move->next_node = (node_t *)malloc(sizeof(node_t));
                move = move->next_node;
            }

        }  // end while loop

    }  // end for loop

    return out;
}

project.c:

/* This is your main file */
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include"common.h"
#include"buildlinklist.h"
#include"printandcombine.h"

int main() {
    node_t * node_ptr = NULL;
    node_t * new_node_ptr=NULL;

    printf("NAME: Riley Branting\n");
    
    /* Build linklist */
    read_objects(&node_ptr);

    
    /* Print the link list */
    printf("Original: ");
    print_linklist(node_ptr);
    
    /* Combine like terms in the link list and craeate a new link list */
    new_node_ptr=combine_like_terms(node_ptr);
    printf("\nCombined: : ");
    /* Print new combine linklist */
    print_linklist(new_node_ptr);

    printf("\nRiley Branting\n");
    free(node_ptr);
    free(new_node_ptr);
    return 0;


}

sidenote: It is very unlikely these last files are too important, but i'm adding them just in case

buildlist.h:

#ifndef BUILDLINKLIST_H
#define BUILDLINKLIST_H

#include"common.h"


/* Read from a text file and put in to a term_t structure. Then create a linklist of node (each node has an element of term struct.)*/
void read_objects(node_t ** pointer_to_node_ptr);

/* Assign value to term_t object elements */
term_t * term_from_string(char * buff);

/* Add a node to the link list */
int add_node(node_t ** pointer_to_node_ptr, void * term);

#endif

buildlist.c:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include"common.h"



/* Assign value to term_t object elements */
term_t * term_from_string(char * buff) {
    term_t * ret = malloc(sizeof(term_t));
    ret->coefficient=atoi(strtok(buff, " "));
    ret->var=*strtok(NULL, " ");
    ret->exponent=atoi(strtok(NULL, " "));
    return ret;
}


/* Add a node to the link list */
int add_node(node_t ** pointer_to_node_ptr, void * term) {
  int ret = 0;
  node_t * newnode_ptr = (node_t *) malloc(sizeof(node_t));
  if (newnode_ptr == NULL) {
    ret = -1;
  }
  else {
    newnode_ptr->term = term;
    newnode_ptr->next_node = *pointer_to_node_ptr;
    *pointer_to_node_ptr = newnode_ptr;
  }
  return ret;
}


/* Read from a text file and put in to a term_t structure. Then create a linklist of node (each node has an element of term struct.)*/
void read_objects(node_t ** pointer_to_node_ptr) {

    FILE *fp;
    char buffer[BUFFERLEN];
    fp = fopen("terms.txt", "r");

    while (fgets(buffer, BUFFERLEN,fp)) {
        term_t * this_term;
        this_term =  term_from_string(buffer);
        add_node(pointer_to_node_ptr, this_term);
    }
    fclose(fp);
}

common.h:

#ifndef COMMON_H
#define COMMON_H

#define BUFFERLEN 40

typedef struct{           /* struct to hold elements like: 3x4 */
    int coefficient;
    char var;
    int exponent;
} term_t;

typedef struct node {
  term_t * term;            /* pointer to term */
  struct node * next_node;  /* pointer to next node */
} node_t;

#endif

And finally, this is the make file i'm using:

CC=gcc 
CFLAGS=-std=c11 -Wall -pedantic 

all: project1.c buildlinklist.o printandcombine.o
    $(CC) $(CFLAGS) project1.c buildlinklist.o printandcombine.o -o project1

buildlinklist.o: buildlinklist.c
    $(CC) $(CFLAGS) -c buildlinklist.c

printandcombine.o: printandcombine.c
    $(CC) $(CFLAGS) -c printandcombine.c
clean:
    rm -f *.o *~ project1.exe
Oka
  • 23,367
  • 6
  • 42
  • 53

1 Answers1

0

I built some test data attempting to structure the data to conform to your structure. When I added in some debugging points and ran the code, it seemed to get stuck in an endless loop if the subsequent terms record had an exponent value that was less than the previously read terms record. The endless looping occurred in the "combine_like_terms" function.

while (!(temp == NULL)) {
    if (temp->term->exponent > x) {
        x = temp->term->exponent;
        temp = temp->next_node;
    }
}

I don't know if this keeps with the spirit of what you are doing, but I moved the "next node" update outside of the "if" statement as noted in the following code snippet.

if (temp->term->exponent > x)
{
    x = temp->term->exponent;
}
temp = temp->next_node;

That at least got past the endless loop behavior. You might try that out. Also, if you have some test data to build a more valid "terms.txt" file, that would be useful if other troubleshooting needs to be done. But, you might start at this bit of code.

Hope that helps.

Regards.

NoDakker
  • 3,390
  • 1
  • 10
  • 11