如何使用char *到int转换来纠正分段错误

时间:2018-02-25 18:41:00

标签: c loops fault

我已将以下内容编写为程序,以便将带有整数序列的指针转换为整数:

#include <math.h>
#include <stdio.h>

char *recepcao() { char *receber;
    scanf("%s", receber);
    return receber;
}
int conversao(char *string) { int i, j;
    for(i=0; string[i]!='\0'; ++i) {
        continue;
    }
    int *var;
    int contagem=0;
    for(j=0; j<i-1; ++j) {
        var[j]=(string[j]-'0');
        contagem+=var[j]*pow(10, (i-j-1));
    }

    return contagem;
}
int main() {
    printf("%i", conversao(recepcao())); return 0;
}

我已经尝试了大约一千次来纠正所有循环,但仍然在收到scanf值之后程序会崩溃,如某些IDE所述,并且会在其他IDE上显示“Segmentation Fault:11”消息。我怎样才能解决这个问题?该消息的正确定义是什么?

3 个答案:

答案 0 :(得分:1)

receber是一个未初始化的指针。 scanf需要char*,其中将记下读取的字符。但在你的情况下,它指向一些你不应该访问的内存。试图访问它是未定义的行为。在您的情况下,它会导致分段错误。

在许多解决方案中,使用char receber[MAXLEN+1]char * receber = malloc(MAXLEN+1)。现在有一个案例。第一个解决方案将导致一个具有自动存储持续时间的数组 - 长话短说,当函数结束时它会指向一些无效的内存 - 所以你不能返回它(如果你使用第一个解决方案)。

第二个解决方案将动态分配内存,其存储持续时间超出此功能的范围。 在这种情况下,这将是正确的。

对于其他功能中的var,您可以使用动态内存分配或VLA支持(如果有)。您应该分配大小等于字符串长度的内存。在这里它不会停止分配 - 你需要用值初始化它,这样你就可以像算术一样在算术运算中使用它。 (再次使用它未初始化是未定义的行为)

为了您的信息,有一个名为strlen的函数,它给出了字符串的长度(nul终止的char数组) - 在这里使用它。

另外,如果您查看参考手册或手册页,您会看到pow返回两倍 - 所以这里以防您遇到一些精确问题。为了计算积分功率使用自定义函数 - 在精度和避免令人讨厌的精度误差的情况下更好。

答案 1 :(得分:0)

您将指针与数组混淆。指针只是指向;声明指针不会保留内存,它只是创建一个指向某个未定义位置的指针变量。

更正程序:

char *recepcao(char *receber) {
    scanf("%s", receber);
    return receber;
}
int conversao(char *string) { int i, j;
    for(i=0; string[i]!='\0'; ++i) {
        continue;
    }
    int var[100];
    int contagem=0;
    for(j=0; j<i-1; ++j) {
        var[j]=(string[j]-'0');
        contagem+=var[j]*pow(10, (i-j-1));
    }

    return contagem;
}
int main() {
    char receber[100];
    printf("%i", conversao(recepcao(receber))); return 0;
}

更新

在C中以非常类似的方式使用数组和指针,但它们不相同。声明数组时,编译器会保留所需的内存:

int a[10], b[10];
a[1] = 1;  // OK
a = b;     // Error!

数组元素是可变的,但数组名称不是。数组名称是标签的一种,您不能更改其值以使其指向另一个数组。

指针变量。声明指针时,编译器使用未定义的内容创建它(与任何其他变量一样)。

int *p, *q;
p = q;      // OK but useless because both the pointers contain junk addresses
a[0] = *p;  // Depending on where p points you will get either junk in a[0] or memory access violation
. . . 
p = a;                 // Now you can use p as a synonym for array a declared above
if (*(p + 1) == a[1])  // Always true
if (p[2] == *(a + 2))  // Always true
. . .
b = p;   // This won't work; can't assign a new value to array name b
. . .
q = (int*)malloc(sizeof(int) * 10); // Another way of creating int array of 10 elements
q = p;  // Array created with malloc is lost because nothing points to it now

基本上,指针和数组之间的唯一区别是指针是变量而数组名不是。你不能完全写“a = p”,因为你不能写“2 = i”。

还有一个相当令人困惑的怪癖,数组作为一个正式的论点:

   void xyz(int a[10]) {
       . . .
   }

   void main() {
       int b[20];
       . . .
       xyz(b);
   }

看起来我们将b分配给a,并更改数组大小,对吗?不,“int a [10]”被视为“int * a”,sizeof(a)将返回指针的大小,而不是数组的大小。

答案 2 :(得分:0)

这里有几个问题

char *recepcao() { 
    char *receber;
    scanf("%s", receber);
    return receber;
}

有两个错误:receber是一个未初始化的指针,它指向无处 特别是,所以传递给scanf是一种未定义的行为。

同样receberrecepcao的局部变量,当它变为不存在时 recepcao返回,因此您返回一个指向无效内存位置的指针。

最好在main中声明一个数组,并将该数组(及其大小)传递给函数。我也会使用fgets代替scanf,更容易控制fgets

您可以使用strlen(string)代替

for(i=0; string[i]!='\0'; ++i) {
        continue;
}

但如果您不允许在作业中使用strlen,那就没问题。

此处使用pow也是过度的,不需要包含浮点数 当你可以使用初始化为1并且乘法的变量pow时,算术(double返回exp) 它在每个循环中都是10(参见下面的代码)。

另外

int *var;
...
for(j=0; j<i-1; ++j) {
    var[j]=(string[j]-'0');
    ...

不起作用,因为var未初始化。没有必要使用 无论如何这里的指针,甚至不是数组,你没有做任何事情 保存的值。最好使用一个char变量:

char var;
...
for(j=0; j<i-1; ++j) {
    var = string[j] - '0';
    ...

因此,您可以使用以下信息重写您的程序:

#include <ctype.h>

char *recepcao(char *receber, size_t len) {
    if(fgets(receber, len, stdin) == NULL)
    {
        fprintf(stderr, "Could not read from user\n");
        return NULL;
    }

    // removing newline
    receber[strcspn(receber, "\n")] = 0;

    return receber;
}

int conversao(const char *string) { 
    if(string == NULL)
        return 0;

    size_t len = strlen(string);

    int res = 0, pow = 1;

    for(size_t i = len - 1; i >= 0; --i)
    {
        if(isdigit(string[i]))
        {
            res += (string[i] - '0') * pow;
            pow *= 10;
        } else {
            fprintf(stderr, "'%s' contains non-digits\n", string);
            return 0;
        }
    }

    return res;
}

int main(void)
{
    char line[100];

    if(recepcao(line, sizeof line) == NULL)
        return 1;

    printf("%d\n", conversao(line));

    return 0;
}