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

Segmentation fault at base converting in C

正在尝试将 dec 转换为 32 进制,然后将其打印到文件中。

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) 错误。

这里发生了几件事:

  • 首先,一个未初始化的本地指针有一个不确定的值;它没有特别指向任何地方。 NULL 指针也不指向任何地方,但至少您可以轻松地测试 NULL 指针。养成初始化指针的习惯,使其指向有效的内存或使其明确为空。
  • 指针应该指向一个字符缓冲区。您的函数看起来像这样,您必须使用 malloc 为堆上的缓冲区分配内存。 (您不能使用本地存储,因为它会立即失效。)
  • 不要以 10 为底数作为特例。 (您甚至将以 10 为底的数字打印为十六进制,这也是错误的。)
  • 你的打印方式没问题,但是你把数字打印反了。所以先确定需要的klength,再把你打印的位置减1。
  • 在这里,您处理原始字符。使用 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] = '[=10=]';
        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 有手动内存管理,跟踪分配的东西很乏味。例如,您不能从 printf 内部调用 baseConverter,因为您会丢失已分配字符串的句柄。

另一种流行的变体是让调用代码分配内存,然后将缓冲区及其大小传递给函数以填充它。原型可能如下所示:

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是一个自动变量,所以不需要freeing。 (如何实施 thins 以及如何正确强制不超过缓冲区大小留作练习。:)

主要错误已经指出。 这是另一个建议的例程(它不需要 malloc) 该函数将指针的值设置为转换后的位数,以便于打印出所需的位数。

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