需要帮助调试C代码

时间:2013-08-10 13:59:52

标签: c debugging

本周刚刚学会了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++;
    }
}

5 个答案:

答案 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 */
};

我在这里做了一些改变:

  1. 您只在阵列中为每个元素存储一个基数为10的数字,因此char足够大
  2. 每个数组元素中存储整数的符号是​​没有用的,所以我使用unsigned char并在外部保留符号
  3. 使你的数组​​固定大小是不灵活的,而不是真正的大整数的精神。如果你要动态地增长它,那么为每个数字做这件事会很快变得昂贵,所以我每次使用摊销的常量时间技巧将其容量加倍填写
  4. 现在,在我们开始使用整数之前,我们需要分配它。让我们现在做最简单的事情,并以零大小开始:

    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_integerappend_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代码值有任何实际好处对你而言。