我已将以下内容编写为程序,以便将带有整数序列的指针转换为整数:
#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”消息。我怎样才能解决这个问题?该消息的正确定义是什么?
答案 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
是一种未定义的行为。
同样receber
是recepcao
的局部变量,当它变为不存在时
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;
}