0

I am trying to initialize dynamically allocated char array to different types within a struct called term, which is a struct that holds parts of a polynomial, (coefficient, var, exponent). The function is a to_string function which returns the struct term as a string of form, "cx^e", or "c" if the term has an exponent of 0.

I believe I have the overall thought process correct for creating the string however I don't know if I'm initializing my char *ptr correctly.

Here's the related code:

The to_string function

char *term_to_string(const term_t *term)
{
  char *ptr;
  if (term->exponent == 0)
  {
    ptr = (char *) malloc(sizeof(term->coefficient));
    memset(ptr, 'x', sizeof(term->coefficient));
    *ptr = term->coefficient;
  }
  else if (term->coefficient == 1)
  {
    ptr = (char *) malloc(sizeof (term->var) + sizeof (term->exponent) + sizeof (char));
    *ptr = term->var;
    *(ptr + 1) = '^';
    *(ptr + 2) = term->exponent;
  }
  else
  {
    ptr = (char *) malloc(sizeof(term->coefficient) +
                          sizeof(term->var) +
                          sizeof(term->exponent) +
                          sizeof(char));
    *ptr = term->coefficient;
    *(ptr + 1) = term->var;
    *(ptr + 2) = '^';
    *(ptr + 3) = term->exponent;                      
  }


  return ptr;
}

The struct "term"

typedef struct term 
{
  int exponent, coefficient;
  char var;
} term_t;

Testing the to_string

term_t testterm1 = {1, 'x', 0};
term_t testterm2 = {2, 'x', 1};
term_t testterm3 = {3, 'x', 2};


printf("Testing term.c/h:\n");
printf("testterm1: %s\n", term_to_string(&testterm1));
printf("testterm2: %s\n", term_to_string(&testterm2));
printf("testterm3: %s\n", term_to_string(&testterm3));

I keep getting a segmentation fault error, and I know it has something to do with trying to initialize a NULL pointer. However, I'm confused as to:

1) What size I should allocate the pointer to? (I'm using sizeof(term->coefficient) right now in the first block of my if statement)

2) If I'm properly initializing my pointer? (I used memset in the first block of the if statement but I really don't think I'm using it right at all)

The expected outcome should be

x
2x
3x^2

Any help would be much appreciated!!!

3
  • str is uninitialized. Commented Jul 6, 2019 at 19:24
  • I removed str and just returned ptr but it still gives me the same error Commented Jul 6, 2019 at 19:52
  • This is all totally, irrecoverably wrong. Scrap it. Strings don't work this way. Use snprintf to format your term (and another call to snprintf to determine how much space you need to allocate). Commented Jul 6, 2019 at 20:30

1 Answer 1

2

You have four problems :

  • the string returned by term_to_string is not terminated by the character having the code 0, so each printf to write the result goes out of the allocated array with an undefined behavior

  • the way you expect to insert the external representation of the integer value is wrong, for instance to do *ptr = term->coefficient just set one character having the code of term->coefficient casted (truncated) to a char

  • the ways you compute the size of the allocated string are wrong, the size of external representation of an int is not given by sizeof

  • your initializations of the struct are wrong, the second value ('x') is visibly the char but you initialize coefficient with it, you need to respect the order of the fields.

If {3, 'x', 2}; has to produce 3x^2 that means the first field of the struct must be coefficient (rather than exponent), the second must be var (rather than coefficient) and the third must be exponent (rather than var). Or without changing the definition of the struct you have to modify the initialization order to have term_t testterm3 = {2, 3, 'x'};.

Also {1, 'x', 0} cannot produce "x", it has to produce "1" or "0"


Without changing the definition of the struct and adding special cases you do not managed a proposal can be :

#include <stdio.h>
#include <malloc.h>

typedef struct term 
{
  int exponent, coefficient;
  char var;
} term_t;

int snprintf(char *str, size_t size, const char *format, ...);

char *term_to_string(const term_t *term)
{
  char *ptr;

  if ((term->exponent == 0) || (term->coefficient == 0))
  {
    ptr = malloc(snprintf(NULL, 0, "%d", term->coefficient) + 1); /* +1 for char \0 */
    sprintf(ptr, "%d", term->coefficient);
  }
  else if (term->coefficient == 1)
  {
    if (term->exponent == 1)
    {
      ptr = malloc(2);
      ptr[0] = term->var;
      ptr[1] = 0;
    }
    else 
    {
      ptr = malloc(snprintf(NULL, 0, "%d", term->exponent) + 3); /* +3 for var and ^ and char \0 */
      sprintf(ptr, "%c^%d",  term->var, term->exponent);
    }
  }
  else if (term->coefficient == -1)
  {
    if (term->exponent == 1)
    {
      ptr = malloc(3);
      ptr[0] = '-';
      ptr[1] = term->var;
      ptr[2] = 0;
    }
    else 
    {
      ptr = malloc(snprintf(NULL, 0, "%d", term->exponent) + 4); /* +4 for - and var and ^ and char \0 */
      sprintf(ptr, "-%c^%d",  term->var, term->exponent);
    }
  }
  else if (term->exponent == 1)
  {
    ptr = malloc(snprintf(NULL, 0, "%d", term->coefficient) + 2); /* +2 for var and char \0 */
    sprintf(ptr, "%d%c", term->coefficient, term->var);
  }
  else
  {
    ptr = malloc(snprintf(NULL, 0, "%d%d", term->exponent, term->coefficient) + 3); /* +3 for var and ^ and char \0 */
    sprintf(ptr, "%d%c^%d", term->coefficient, term->var, term->exponent);
  }

  return ptr;
}

int main()
{
  term_t test[] = { 
    {0, 1, 'x'},
    {1, 0, 'x'},
    {1, 1, 'x'},
    {1, -1, 'x'},
    {1, 2, 'x'},
    {2, 1, 'x'},
    {2, -1, 'x'},
    {2, 3, 'x'}
  };

  for (int i = 0; i != sizeof(test)/sizeof(term_t); ++i) {
    char * s = term_to_string(&test[i]);

    printf("test {exp=%d, coef=%d, var='%c'} : %s\n", 
           test[i].exponent, test[i].coefficient, test[i].var, s);
    free(s);
  }

  return 0;
}

Compilation and execution :

pi@raspberrypi:/tmp $ gcc -pedantic -Wall -Wextra e.c
pi@raspberrypi:/tmp $ ./a.out
test {exp=0, coef=1, var='x'} : 1
test {exp=1, coef=0, var='x'} : 0
test {exp=1, coef=1, var='x'} : x
test {exp=1, coef=-1, var='x'} : -x
test {exp=1, coef=2, var='x'} : 2x
test {exp=2, coef=1, var='x'} : x^2
test {exp=2, coef=-1, var='x'} : -x^2
test {exp=2, coef=3, var='x'} : 3x^2
pi@raspberrypi:/tmp $ 

Execution under valgrind :

pi@raspberrypi:/tmp $ valgrind ./a.out
==4285== Memcheck, a memory error detector
==4285== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==4285== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==4285== Command: ./a.out
==4285== 
test {exp=0, coef=1, var='x'} : 1
test {exp=1, coef=0, var='x'} : 0
test {exp=1, coef=1, var='x'} : x
test {exp=1, coef=-1, var='x'} : -x
test {exp=1, coef=2, var='x'} : 2x
test {exp=2, coef=1, var='x'} : x^2
test {exp=2, coef=-1, var='x'} : -x^2
test {exp=2, coef=3, var='x'} : 3x^2
==4285== 
==4285== HEAP SUMMARY:
==4285==     in use at exit: 0 bytes in 0 blocks
==4285==   total heap usage: 9 allocs, 9 frees, 1,050 bytes allocated
==4285== 
==4285== All heap blocks were freed -- no leaks are possible
==4285== 
==4285== For counts of detected and suppressed errors, rerun with: -v
==4285== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 3)
pi@raspberrypi:/tmp $ 
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.