инициализировать динамически размещаемый массив символов из структуры - PullRequest
0 голосов
/ 06 июля 2019

Я пытаюсь инициализировать динамически распределенный массив char для различных типов в структуре, называемой term, которая представляет собой структуру, содержащую части полинома (factor, var, exponent). Функция представляет собой функцию to_string, которая возвращает структурный термин в виде строки формы, "cx ^ e" или "c", если у показателя есть показатель степени 0.

Я полагаю, что у меня правильный мыслительный процесс для создания строки, однако я не знаю, правильно ли я инициализирую char *ptr.

Вот соответствующий код:

Функция to_string

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

Структура "термин"

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

Тестирование строки 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));

Я продолжаю получать ошибку ошибки сегментации, и я знаю, что это как-то связано с попыткой инициализировать указатель NULL. Тем не менее, я смущен относительно:

1) На какой размер я должен выделить указатель? (Я использую sizeof(term->coefficient) прямо сейчас в первом блоке моего оператора if)

2) Если я правильно инициализирую свой указатель? (Я использовал memset в первом блоке оператора if, но я действительно не думаю, что я использую его правильно)

Ожидаемый результат должен быть

x
2x
3x^2

Любая помощь будет принята с благодарностью !!!

1 Ответ

2 голосов
/ 06 июля 2019

У вас есть четыре проблемы:

  • строка, возвращаемая term_to_string, не заканчивается символом с кодом 0, поэтому каждый printf для записи результата выходит из выделенного массива с неопределенным поведением

  • неправильный способ вставки внешнего представления целочисленного значения, например, для выполнения *ptr = term->coefficient просто установите один символ с кодом term->coefficient cast (усеченный) на char

  • неправильные способы вычисления размера выделенной строки, размер внешнего представления int не задается sizeof

  • ваша инициализация структуры неверна, второе значение ('x') является явно символом, но вы инициализируете коэффициент с ним, вам нужно соблюдать порядок полей.

Если {3, 'x', 2}; должен выдать 3x^2, это означает, что первое поле struct должно быть коэффициент (вместо показатель ), второе должно быть var (вместо коэффициент ), а третье должно быть показатель (вместо var ). Или, не изменяя определение struct , вы должны изменить порядок инициализации, чтобы иметь term_t testterm3 = {2, 3, 'x'};.

Также {1, 'x', 0} не может выдавать «x», оно должно выдавать «1» или «0»


Без изменения определения struct и добавления особых случаев, которыми вы не управляли, предложение может быть:

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

Компиляция и исполнение:

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 $ 

Исполнение под 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 $ 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...