从结构

时间:2019-07-06 19:21:21

标签: c

我正在尝试将动态分配的char数组初始化为称为term的结构中的不同类型,该结构包含多项式(系数,var,指数)的一部分。该函数是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)我应该将指针分配给什么大小? (我现在在{if1语句的第一块中使用sizeof(term->coefficient)

2)是否正确初始化了指针? (我在if语句的第一段中使用了memset,但我真的认为我根本没有使用它)

预期结果应该是

x
2x
3x^2

任何帮助将不胜感激!!!

1 个答案:

答案 0 :(得分:2)

您有四个问题:

  • term_to_string返回的字符串没有被代码为0的字符终止,因此每个写入结果的 printf 都以未定义的行为退出分配的数组

  • 您期望插入整数值的外部表示的方式是错误的,例如,将*ptr = term->coefficient的一个字符设置为term->coefficient强制转换(截断)为一个字符字符

  • 计算分配的字符串大小的方法是错误的, int 的外部表示形式的大小不是 sizeof

    给出的
  • 您对结构的初始化是错误的,第二个值('x')显然是char,但是您使用它初始化 coefficient 时,需要注意字段的顺序。

如果{3, 'x', 2};必须产生3x^2,这意味着 struct 的第一个字段必须是 coefficient (而不是 exponent < / em>),第二个必须是 var (而不是 coefficient ),而第三个必须是指数(而不是 var < / em>)。或者不更改 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 $