转换数组大小

时间:2016-03-04 10:19:32

标签: c arrays algorithm multidimensional-array

以下代码从文件中获取输入并将其存储在一维数组中。我想要一个矩阵类型的输入,如:

1,2,4
3,4,5
5,6,7

(或)

2,3,4,5
4,5,6,7
7,6,5,4
3,4,5,6

其中矩阵的大小变化并且用逗号分隔,以存储在2D阵列中。我应该对以下代码做出哪些更改?

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

int main(){
    char file[51];
    int data, row, col, c, count, inc;
    int *array, capacity=50;
    char ch;
    array = (int*)malloc(sizeof(int) * capacity);
    printf("\nEnter the name of the file with its extention\n");
    scanf("%s", file);
    FILE *fp = fopen(file, "r"); 
    row = col = c = count = 0;
    while (EOF != (inc = fscanf(fp,"%d%c", &data, &ch)) && inc == 2){
        ++c; //COLUMN count
        if (capacity == count)
            array = (int*)realloc(array, sizeof(int) * (capacity *= 2));
        array[count++] = data;
        if(ch == '\n'){
            ++row;
            if (col == 0){
                col = c;
            } else if (col != c){
                fprintf(stderr, "format error of different Column of Row at %d\n", row);
                goto exit;
            }
            c = 0;
        } else if (ch != ',') {
            fprintf(stderr, "format error of different separator(%c) of Row at %d \n", ch, row);
            goto exit;
        }
    }
    {   //check print
        int i, j;
        //int (*matrix)[col] = array;
        for(i = 0; i < row; ++i){
            for(j = 0; j < col; ++j)
                printf("%d ", array[i * col + j]);//matrix[i][j]
            printf("\n");
        }
    }
exit:
    fclose(fp);
    free(array);
    return 0;
}

3 个答案:

答案 0 :(得分:1)

这使用fgets来读取每一行,使用strtol来解析一行中的整数。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <limits.h>

int get_int_range ( char *line, char **next, char *term, int *value, int min, int max);
int get_int_series ( int cols, int dest[][cols], int inputrow, int min, int max, char *line, char *delim);
int get_int_count ( int min, int max, char *line, char *delim);

int main( int argc, char *argv[])
{
    char line[900] = {'\0'};
    char file[100] = {'\0'};
    int valid = 0;
    int rows = 0;
    int cols = 0;
    int eachrow = 0;
    int eachcol = 0;
    FILE *fp = NULL;

    printf ( "Enter the name of the file with it's extension\n");
    fgets ( file, sizeof ( file), stdin);
    file[strcspn ( file, "\n")] = '\0';//remove trailing newline

    if ( ( fp = fopen ( file, "r")) != NULL) {

        fgets ( line, sizeof ( line), fp);//read a line
        rows = get_int_count ( INT_MIN, INT_MAX, line, ",\n");
        rewind ( fp);
        if ( rows) {
            cols = rows;
            //once the size is obtained, the array can be declared
            int array[rows][cols];

            for(eachrow = 0; eachrow < rows; eachrow++) {
                if ( ( fgets ( line, sizeof ( line), fp)) == NULL) {//read a line
                    fclose ( fp);
                    printf ( "Problem! not enough lines in file\n");
                    return 1;
                }
                valid = get_int_series ( cols, array, eachrow, INT_MIN, INT_MAX, line, ", \n");
                if ( !valid) {
                    fclose ( fp);
                    printf ( "Problem!\n");
                    return 1;
                }
            }
            if ( ( fgets ( line, sizeof ( line), fp)) != NULL) {//read a line
                fclose ( fp);
                printf ( "Problem! too many lines in file\n");
                return 1;
            }
            for(eachrow = 0; eachrow < rows; eachrow++) {
                for(eachcol = 0; eachcol < cols; eachcol++) {
                    printf("[%d] ", array[eachrow][eachcol]);
                }
                printf("\n");
            }
            printf("\nDone\n");
        }
        fclose ( fp);
    }
    return 0;
}

int get_int_range ( char *line, char **next, char *term, int *value, int min, int max)
{
    long int input = 0;
    char *end = NULL;

    errno = 0;
    input = strtol ( line, &end, 10);//get the integer from the line
    if ( end == line) {
        printf ( "input MUST be a number\n");
        return 0;
    }
    if ( *end != '\0' && ( strchr ( term, *end) == NULL)) {
        printf ( "problem with input: [%s] \n", line);
        return 0;
    }
    if ( ( errno == ERANGE && ( input == LONG_MAX || input == LONG_MIN))
    || ( errno != 0 && input == 0)){
        perror ( "input");
        return 0;
    }
    if ( input < min || input > max) {
        printf ( "input out of range %d to %d\n", min, max);
        return 0;
    }

    if ( next != NULL) {
        *next = end;
    }
    *value = input;//set the value
    return 1;
}

int get_int_series ( int cols, int dest[][cols], int inputrow, int min, int max, char *line, char *delim)
{
    char *end = NULL;
    char *each = NULL;
    int valid = 0;
    int input = 0;
    int count = 0;
    int temp[cols];

    each = line;
    do {
        valid = get_int_range ( each, &end, delim, &input, INT_MIN, INT_MAX);
        if ( !valid) {
            printf ( "input MUST be a number\n");
            return 0;
        }
        if ( valid) {
            temp[count] = input;
            count++;
            if ( count > cols) {
                printf ( "too many integers. %d entered. only enter %d\n", count, cols);
                return 0;
            }
        }
        while ( *end && strchr ( delim, *end)) {//skip any number of delimitors
            end++;
        }
        each = end;
    } while ( end && *end);

    if ( count < cols) {
        printf ( "too few integers. need %d entered. only entered %d\n", cols, count);
        return 0;
    }
    while ( count) {
        count--;
        dest[inputrow][count] = temp[count];//set the value
    }
    return 1;
}

int get_int_count ( int min, int max, char *line, char *delim)
{
    char *end = NULL;
    char *each = NULL;
    int valid = 0;
    int input = 0;
    int count = 0;

    each = line;
    do {
        valid = get_int_range ( each, &end, delim, &input, INT_MIN, INT_MAX);
        if ( !valid) {
            return count;
        }
        if ( valid) {
            count++;
        }
        while ( *end && strchr ( delim, *end)) {//skip any number of delimitors
            end++;
        }
        each = end;
    } while ( end && *end);

    return count;
}

答案 1 :(得分:0)

简单地保存并读取数组总是一个单一维度字符串,其长度是所有维度的乘积与类型的大小。然后返回一个指向void的指针,该指针将分配给指向所需尺寸数组的指针 即。

void *MyReadFnc(char *filename, size_t size)
{
    char *p = malloc(size);
    //open file and load the data
    return (void *)p;
}
...
//Call the function to read in our array.
//For who don't see it we want assign to an array of 5 dimensions
//array[10][2][3][4][5]
//Note that the first dimension is omitted, but we have to use it in array size calcullation
int (*array)[2][3][4][5] = MyReadFnc("Filename.ext", 2*3*4*5*10*sizeof(int));
...
printf("element[9][1][2][3][4] = %d\n", array[9][1][2][3][4]);
...
//Again an array of 3 dimensions:
//array2[10][20][30]
int (*array2)[20][30] = MyReadFnc("Filename.ext", 20*30*10*sizeof(int));
...
printf("element[9][19][29] = %d\n", array[9][19][29]);

我们使用void *作为输出,因为该例程是通用的,可以处理任何数组(任意数量的维度)。使用void *只是用于处理此类杂色类型的标准且自然的C语言方式。这是 C语言的工作方式。如果你想要更强的类型检查,你应该改变语言 以下是用于读取数组的更通用的代码。

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

//Because we read whole data as single stream like a 1 dimension array, totElems
//is the total number of elements expressed as the product of all dimensions of
//the final array
void *ReadArray(char *fname, size_t totElems, size_t ElemSize)
{
    FILE *fp = fopen(fname, "r");
    if (!fp)
    {
        fprintf(stderr, "Can't open file <%s>\n", fname);
        exit(-1);
    }

    int *p = calloc(totElems, ElemSize);
    if (!p)
    {
        fprintf(stderr, "Can't allocate memory\n");
        exit(-1);
    }

    for (size_t i=0; ; i++)
    {
        int a;

        if (EOF==fscanf(fp, "%d,", &a))
            break;
        p[i] = a;
    }

    fclose(fp);
    return (void *)p;
}

int main(void)
{
    char file[51];
    printf("\nEnter the name of the file with its extention\n");
    scanf("%s", file);

    printf("Array 4x4\n");
    //First sample: declare a pointer to a 2 dimension array 4x4 elements
    int (*array)[4];
    array = ReadArray(file, 16, sizeof(int));
    for (int i=0; i<4; i++)
    {
        for(int j=0; j<4; j++)
            printf("%d,", array[i][j]);
        printf("\n");
    }

    printf("Array 2x8\n");
    //Second sample: declare a pointer to a 2 dimension array 2x8 elements
    int (*array2)[8];
    array2 = ReadArray(file, 16, sizeof(int));
    for (int i=0; i<2; i++)
    {
        for(int j=0; j<8; j++)
            printf("%d,", array2[i][j]);
        printf("\n");
    }

    printf("Array 2x2x4\n");
    //Third sample: declare a pointer to a 3 dimension array 2x2x4 elements
    int (*array3)[2][4];
    array3 = ReadArray(file, 16, sizeof(int));
    for (int i=0; i<2; i++)
    {
        for(int j=0; j<2; j++)
        {
            if(j) printf (" - ");
            for (int k=0; k<4; k++)
                printf("%d,", array3[i][j][k]);
        }
        printf("\n");
    }

    return 0;
}

您可以将结果分配给任何维度的数组;)。不需要强制转换,因为数组对象以void *形式返回,以实现最大的灵活性。另请注意,因为任何C数组都是数组数组等,所以它实际上与维度无关。该函数返回的是一个数组,它可以适合任何关于2个声明的定义:1。数组的类型具有ElemSize中指定的相同大小(为了简单起见,这里是硬连线到{{1 }}),2。整个维度的乘积是int 这当然只是作为开发更复杂版本的基础的一个示例,良好的开发可以使其能够处理任何类型的数据(不仅仅是int)。我相信这对初学者来说是一个很好的练习,需要一个起点来提高自己,扩大他们的创造力 最后,只需考虑在符合C99-C11标准的编译器上,您可以编写: printf(“Array 2x2x4 using variables \ n”);

<=totElems

答案 2 :(得分:0)

好的,您现在的代码已经知道如何确定第一行末尾的cols数量,并控制所有行具有相同数量的cols。

您可以在第一行的末尾分配2D数组:

capacity = cols * cols;
int (* arr)[cols] = malloc(sizeof(int) * capacity); // array is a 2D array cols x cols

(当然,您必须将第一行存储在另一个数组中,并且必须在新分配的arr中复制这些数据...)

然后你这样指定:

arr[row][c] = data;

唯一的要求是编译器接受可变长度数组。它在C99中指定,但是一些旧的MS编译器(至少到2008年)不接受它。