【问题标题】:initialize to dynamically allocated char array from a struct从结构初始化为动态分配的字符数组
【发布时间】:2019-07-06 19:21:21
【问题描述】:

我正在尝试将动态分配的 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) 我应该将指针分配到什么大小? (我现在在 if 语句的第一个块中使用 sizeof(term->coefficient)

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

预期的结果应该是

x
2x
3x^2

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

【问题讨论】:

  • str 未初始化。
  • 我删除了 str 并返回了 ptr 但它仍然给我同样的错误
  • 这完全是不可挽回的错误。报废它。字符串不能以这种方式工作。使用snprintf 格式化您的术语(并再次调用snprintf 以确定您需要分配多少空间)。

标签: c


【解决方案1】:

你有四个问题:

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

  • 您希望插入整数值的外部表示的方式是错误的,例如要执行*ptr = term->coefficient,只需将一个具有term->coefficient 代码的字符强制转换(截断)为字符

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

    给出的
  • 您的结构初始化错误,第二个值 ('x') 明显是字符,但您用它初始化 系数,您需要尊重字段的顺序。

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

【讨论】:

    猜你喜欢
    • 2015-07-23
    • 2021-01-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-10
    • 1970-01-01
    • 2022-12-03
    • 2020-05-04
    相关资源
    最近更新 更多