以下代码从文件中获取输入并将其存储在一维数组中。我想要一个矩阵类型的输入,如:
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;
}
答案 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年)不接受它。