C中基址转换时的分段错误

时间:2016-03-14 19:20:26

标签: c compilation segmentation-fault base

尝试将dec转换为32-base,然后将其打印到文件中。

const char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUV";

    char* baseConverter(int num, int base)                                                          
    {   char* res;
        int i=0;
        if (num == 0 || base == 10)
        {
            snprintf(res,"%03x",num);
            return *res;    
        }
        while( num > 0 )
        {
            *(res+i) = digits[num%base];
            num=num/base;
        }
        return *res;
    }

然后输出代码:

sprintf(line, "%03s", baseConverter(i, 32);

但我在运行时遇到Segmentation fault (core dumped)错误。

2 个答案:

答案 0 :(得分:2)

这里有几件事情发生了:

  • 首先,未初始化的本地指针具有不确定的值;它并不特别指向任何地方。 NULL指针也没有指向任何地方,但至少可以轻松地测试NULL指针。养成使指针初始化以使其指向有效内存或使其显式为空的习惯。
  • 指针应该指向char缓冲区。您的函数的样子,您必须使用malloc为堆上的缓冲区分配内存。 (您无法使用本地存储,因为这会立即失效。)
  • 不要让基地10成为特例。 (你甚至通过将十进制数字打印为十六进制来做错。)
  • 您的打印方法没问题,但您可以向后打印数字。因此,首先确定所需的klength,然后减小打印位置。
  • 在这里,您处理原始字符。使用res[i]而不是使用标准库函数执行复杂的操作。特别是,不要通过将字符串连接或打印到自身来构建字符串。这很可能是未定义的行为。

您的功能的可能实现可能如下所示:

int ndigits(int num, int base)
{
    int n = 0;

    while (num) {
        n++;
        num /= base;
    }

    if (n == 0) n++;
    return n;
}

char* baseConverter(int num, int base)                                                          
{
    if (num >= 0 && base > 1 && base <= 36) {
        int n = ndigits(num, base);
        char *res = malloc(n + 1);
        int i = n;

        res[n] = '\0';
        if (num == 0) res[--i] = '0';

        while (num) {
            res[--i] = digits[num % base];
            num /= base;    
        }

        return res;
    }

    return NULL;
}

注意如何使用辅助函数来确定字符串的长度。然后向后填充字符串,用空终止符进行凝视。另请注意返回NULL如何处理无效案例。

您的调用代码在使用后必须明确释放字符串:

    int n = rand() % 100000 + 1;
    int m = rand() % 10 + 2;
    char *p = baseConverter(n, m);

    if (p) printf("%d#%d == %s\n", n, m, p);
    free(p);

C具有手动内存管理功能,跟踪分配的内容非常繁琐。例如,您无法从baseConverter内拨打printf,因为您将丢失已分配字符串的句柄。

另一个流行的变体是让调用代码分配内存,然后将缓冲区及其大小传递给函数来填充它。原型可能看起来像这样:

void sbase(char buf, size_t buflen, int num, int base);

然后会这样调用:

    char buf[33];     // Maximum, when base 2 is printed

    sbase(buf, sizeof(buf), 5000, 13);
    puts(buf);

由于buf是自动变量,因此不需要free。 (如何实现这些以及如何正确执行不超出缓冲区大小的问题留作练习。:)

答案 1 :(得分:1)

The main errors have already been pointed out. Here is another suggested routine (it doesn't require malloc) The function sets the value of a pointer to the number of converted digits, to make it easy to print out the required digits.

#include <stdio.h>

/* function takes pointer to array, size of array + number/base 
   and pointer for number of digits in conversion */
void make32(int *res32, int len, int num, int base, int *rln);

int main()
{
  int digits32[20]; // size according to max conversion number in base 32
  int len32 = sizeof(digits32)/sizeof(digits32[0]);
  int in32, resln, n;

  /* convert this number */
  in32 = 10000;
  /* call function with pointer + size & number/base & ptr to # converted digits*/
  make32(digits32, len32, in32, 32, &resln);
  /* print out result - reverse order - use number of digits */
  for(n = resln; n >= 0;  n--) {
     printf("%d  ", digits32[n]);
  }
  printf("\n");
  return (0);
}

void make32(int *res32, int len, int num, int base, int *rln)
{
    int i = 0;
    while( num > 0 && i <= len ) {
        res32[i] = num % base;
        num = num / base;
        i++;
    }
    /* set the number of converted digits */
    *rln = i - 1;
}