本周刚刚学会了C.我的任务是从用户获取一个大的整数输入,将其存储到struct Integer中,并创建一个函数来将相应的struct integer打印到标准输出。该程序可以这样工作,但只要它给出输出,它就会停止响应。我没有在编译器中得到任何直接错误,也无法弄清楚出了什么问题。任何其他改进编程风格的建议/提示也将非常感激:)
// Header Files Go Here
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// Function Declarations Go Here
struct integer * convert_integer(char * stringInt);
void printer(struct integer * p);
struct integer {
int * arr;
int length;
};
// Main Program
int main() {
char * x;
x = (char *) malloc(sizeof(char) * 10000);
printf("Enter a small string\n");
scanf("%s",x);
int j = 0;
struct integer * book1;
book1 = convert_integer(x);
printer(book1);
return 0;
}
// Function Definitions Go Here
struct integer * convert_integer(char * stringInt) {
struct integer * x = malloc(sizeof(int) * 100);
int j = 0;
while (stringInt[j] != '\0') {
if (stringInt[j] < 48 || stringInt[j] >= 57) {
printf("Invalid input. Enter a number ");
return;
}
x->arr[j] = stringInt[j] - 48;
j++;
}
x->length = j;
printf("\n the length is %d\n", x->length);
return x;
}
void printer(struct integer * p) {
int j = 0;
while (j < p->length) {
printf("%d", p->arr[j]);
j++;
}
}
答案 0 :(得分:2)
我正在添加这个答案,因为NPE不够明确。
这个程序中有一些错误,但我会说紧迫的是函数convert_integer
。您正在执行以下操作:
struct integer* x= malloc(sizeof(int) * 100);
......但这是不正确的。考虑到它的数据类型( ),你要求x
太多字节的内存,但是你没有请求arr
的内存块。它需要如下:
struct integer *x = malloc( sizeof( struct integer ) );
x->arr = malloc( sizeof( int ) * c );
...其中c
是一些常数(在你的情况下是100?)。确保在free
此结构时,首先free
arr
然后free
结构,否则您将发生内存泄漏。
我注意到你没有做的其他事情,总是检查系统调用的结果。您没有检查malloc
是否返回了无效的内存块。
答案 1 :(得分:0)
您需要在顶部添加printer
的原型。验证号码的if
语句应为
if(stringInt[j]<48 || stringInt[j]>57) // > instead of >=
将其写为
会更有意义if ( stringInt[j] < '0' || stringInt[j] > '9' )
如果您了解isdigit
功能,也可以使用它。
您正在为具有10000个字符的字符串分配内存。这似乎有点矫枉过正。你可以分配256个字符的内存,这应该是充足的。在使用语句return
free (x);
之前,您还应该释放内存
您需要在arr
函数内为convert_integer
分配空间。您的分配应该是:
struct integer* x= malloc(sizeof(integer)); x->arr = malloc ( sizeof(int) * 256 );
答案 2 :(得分:0)
下面:
struct integer* x= malloc(sizeof(int) * 100);;
您正在为结构(即指针和int)分配内存,但不为数组分配内存。
您尝试分配到x->arr[j]
时,您有undefined behaviour。
答案 3 :(得分:0)
你的代码在线上失败了
x->arr[j]=stringInt[j]-48;
原因是你分配内存片的方式:
struct integer* x= malloc(sizeof(int) * 100);
这会分配n*100
个字节的片段,并在x
中存储指向该片的指针。你想要做的是以下内容:
struct integer *x = malloc(sizeof(*x));
x->arr = malloc(sizeof(int)*100);
分配存储integer
结构x
所需的内存,并分配内存以存储100个整数并将其分配给x->arr
。使用您的代码,x->arr
未初始化,因此其中包含随机值(更准确地说:值是之前存储在该内存位置的值)。
使用完分配的内存后,您还应该释放它:
free(x->arr);
free(x);
答案 4 :(得分:0)
既然你也提出了建议,我会展示一个风格更好的解决方案。
struct Integer {
unsigned char *array; /* no point storing sign info on each element */
size_t capacity; /* how many we have space for */
size_t count; /* how many we've actually used */
char sign; /* +1 or -1 */
};
我在这里做了一些改变:
char
足够大unsigned char
并在外部保留符号现在,在我们开始使用整数之前,我们需要分配它。让我们现在做最简单的事情,并以零大小开始:
struct Integer *alloc_integer() {
struct Integer *i = malloc(sizeof(*i));
/* this integer is empty until we use it ... */
i->array = NULL;
i->capacity = 0;
i->count = 0;
i->sign = 1;
return i;
}
当然,如果它保持零大小是没用的,所以我们需要一些方法来扩大它:
void grow_integer(struct Integer *i, size_t min_size) {
/* this check is redundant if we're only called from append_integer */
if (min_size <= i->capacity) return;
/* jump to the next power of 2 (ie, we usually double the capacity) */
size_t new_size = i->capacity * 2;
while (new_size < min_size) new_size *= 2;
unsigned char *new_array = malloc(new_size * sizeof(*new_array));
/* figure out how to cope if we run out of memory */
memcpy(new_array, i->array, i->count * sizeof(*new_array));
free(i->array);
i->array = new_array;
i->capacity = new_size;
}
现在我们可以看到如何附加一个整数:
void append_integer(struct Integer *i, char digit) {
if (i->count == i->capacity)
grow_integer(i, i->capacity + 1);
i->array[ i->count++ ] = (unsigned char)digit;
}
(请注意grow_integer
和append_integer
中的检查重叠一点:我可以删除一个,但我还没有确定grow_integer
是否还是一个公共接口
最后,读取字符串应该很简单:
struct Integer *str_to_Integer(const char *str) {
struct Integer *i = alloc_integer();
for (; *str; ++str) {
if (!isdigit(*str)) {
free_integer(i);
return NULL;
}
append_integer(i, *str - '0');
}
return i;
}
请注意,我使用isdigit
并且更喜欢'0'
到48
,因为我不认为在编译器可以执行此操作时强制人们记住ASCII代码值有任何实际好处对你而言。