分配动态2D阵列

时间:2014-05-05 17:11:37

标签: c arrays

动态创建数组时,一切似乎都能正常工作 但是当试图向后打印时,核心被抛弃了。 它设法只打印最后一个字符串然后分段错误。

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>

void init_array(void ***pt, int *ptlen) {
    *pt=NULL;
    *ptlen=0;
}

void trim_array(void ***pt, int *ptlen, int len) {
    *pt=(void**)realloc(*pt, len*sizeof(void*));
    *ptlen=len;
}

void write_array(void ***pt, int *ptlen, int pos, void *v) {
    if (pos >= *ptlen)
        trim_array(pt, ptlen, pos+1);

    *pt[pos]=v;
}

void *read_array(void ***pt, int *ptlen, int pos) {
    return(*pt[pos]);
}

void destroy_array(void ***pt, int *ptlen) {
    trim_array(pt, ptlen, 0);
    *pt=NULL;
}

int main(int argc, char *argv[]) {
    void **t;
    int tlen;

    void ***pt = &t;
    int *ptlen = &tlen;

    char s[256],*p; int i;

    init_array(pt, ptlen); 

    i = 0;
    do {
        printf("give name:\n");
        scanf("%255s",s);
        write_array(pt, ptlen, i, (void*)strdup(s));
        i++;
    } while (strcmp(s,"end"));

    for (--i; i>=0; i--) {
        p = (char*)read_array(pt, ptlen, i);
        printf("%s\n",p);
        free(p);
    }

    destroy_array(pt, ptlen);
    return(0);
}

1 个答案:

答案 0 :(得分:1)

[]运算符的优先级高于*运算符。你需要改变:

*pt[pos]

为:

(*pt)[pos]

在两个地方发生。

这个错误是编写几乎故意混淆代码与失控间接的直接结果。如果你在struct中包含了很多这些东西并为它创建了一些合适的接口函数,那么你可以省去很多麻烦并使事情变得更容易。

这样的事情会有一些更好的形式(尽管&#34;数组&#34;并不是这个数据结构的真正名称):

main.c

#define _POSIX_C_SOURCE 200809L

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include "array.h"

#define MAX_BUFFER_LEN 255

int main(void) {
    Array myarray = array_init(10, true);

    /*  Loop for input until user enters "end"  */

    char buffer[MAX_BUFFER_LEN];
    while ( true ) {
        printf("Give name: ");
        fflush(stdout);

        /*  Get input and remove trailing '\n' if necessary  */

        fgets(buffer, MAX_BUFFER_LEN, stdin);
        size_t last = strlen(buffer) - 1;
        if ( buffer[last] == '\n' ) {
            buffer[last] = '\0';
        }

        /*  Terminate loop on "end" without adding to array...  */

        if ( !strcmp(buffer, "end") ) {
            break;
        }

        /*  ...or append input to array and continue loop  */

        array_append(myarray, strdup(buffer));
    };

    /*  Output contents of array  */

    size_t n = array_size(myarray);
    for ( size_t i = 0; i < n; ++i ) {
        char * data = array_getdata(myarray, i);
        printf("%zu: %s\n", i + 1, data);
    }

    /*  Clean up and exit  */

    array_destroy(myarray);

    return EXIT_SUCCESS;
}

array.h

#ifndef ARRAY_TYPE_H
#define ARRAY_TYPE_H

#include <stdbool.h>

typedef struct array_type * Array;  /*  Opaque type for user  */

Array array_init(const size_t capacity, const bool free_on_delete);
void array_append(Array array, void * data);
size_t array_size(const Array array);
void * array_getdata(Array array, const size_t index);
void array_deletetop(Array array);
void array_destroy(Array array);

#endif      /*  ARRAY_TYPE_H  */

array.c

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include "array.h"

/*  Struct definition is visible only to implementation  */

struct array_type {
    void ** elements;
    size_t capacity;
    size_t top;
    bool free_on_delete;
};

/*  Static functions used by the implementation  */

static bool array_isfull(Array array) {
    return (array->top + 1) == array->capacity;
}

static void array_resize(Array array, const size_t new_capacity) {
    array->capacity = new_capacity;
    array->elements = realloc(array->elements,
                              array->capacity * sizeof (*array->elements));
    if ( array->elements == NULL ) {
        fputs("Error allocating memory.", stderr);
        exit(EXIT_FAILURE);
    }
}

/*  Interface functions  */

Array array_init(const size_t capacity, const bool free_on_delete) {
    struct array_type * new_array = malloc(sizeof *new_array);
    if ( new_array == NULL ) {
        fputs("Error allocating memory.", stderr);
        exit(EXIT_FAILURE);
    }

    new_array->elements = malloc(capacity * sizeof (*new_array->elements));
    if ( new_array->elements == NULL ) {
        fputs("Error allocating memory.", stderr);
        exit(EXIT_FAILURE);
    }

    new_array->capacity = capacity;
    new_array->top = 0;
    new_array->free_on_delete = free_on_delete;

    return new_array;
}

void array_append(Array array, void * data) {
    if ( array_isfull(array) ) {
        array_resize(array, array->capacity * 2);
    }
    array->elements[array->top++] = data;
}

size_t array_size(const Array array) {
    return array->top;
}

void * array_getdata(Array array, const size_t index) {
    return array->elements[index];
}

void array_deletetop(Array array) {
    if ( array->free_on_delete ) {
        free(array->elements[array->top - 1]);
    }
    array->elements[--array->top] = NULL;
}

void array_destroy(Array array) {
    while ( array->top > 0 ) {
        array_deletetop(array);
    }
    free(array->elements);
    free(array);
}

示例输出:

paul@local:~/src/c/scratch/array$ ./array
Give name: Dave Dee
Give name: Dozy
Give name: Beaky
Give name: Mick
Give name: Titch
Give name: end
1: Dave Dee
2: Dozy
3: Beaky
4: Mick
5: Titch
paul@local:~/src/c/scratch/array$