如何让我的代码从文件中读取任意数量的浮点数输入?
How to make my code read input from a file for an arbitrary number of floats?
我用 c 语言编写了一段代码,它从文本文件中读取数字并将它们放入数组中的矩阵格式。问题是我已经使我的代码适用于确定大小为 3x3 的矩阵。如果我必须增加大小,我必须直接在代码中更改它。我怎样才能改变我的代码,以便它自动创建一个所需大小的数组并读取文件而不考虑它的长度(假设输入文件将包含足够的数字来形成一个方阵)?例如,我可以给它一个输入文件,其中包含一个 nxn 矩阵的逗号分隔的数字,我的代码应该给我一个包含这些数字的 nxn 矩阵。
这是我的代码,
#include <stdio.h>
#include <stdlib.h>
//Declaring Matrices
float A[3][3];
//Function to read the matrices from a file
int ReadMatrix(void){
FILE * f_pointer;
f_pointer = fopen("Input Matrix.txt","r");
if(f_pointer==NULL){
printf("Error 404:- File not found");
return 1;
}
fscanf(f_pointer,"%f, %f, %f\n%f, %f, %f\n%f, %f, %f", &A[0][0], &A[0][1], &A[0][2], &A[1][0], &A[1][1], &A[1][2], &A[2][0], &A[2][1], &A[2][2]);
return 0;
}
可能最简单的 single-pass 方法很简单,就是将文件中的浮点数读取到分配的内存块中,可以根据需要使用 realloc
扩展该内存块,直到读取所有值。然后您可以简单地循环并确定读取的值的数量是否会形成一个方阵——如果它们不会,则处理错误。然后,您将拥有一个有效存储的浮点数块,可以通过简单的算术将其作为二维数组进行操作。例如,如果您读取 9 个值,并且您的正方形大小为 3x3,则您可以访问 i, j
行和列值作为:
array [i * 3 + j];
(注意: 另一种选择——您可以分配 n
指针和 n
额外的 n
块 - 如果需要,可以浮动真正的二维索引,例如 array [i][j]
-- 由你决定)
一个简单的实现可以是:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NELEM 16 /* initial number of floats to allocate */
/** realloc 'ptr' of 'nelem' of 'psz' to 'nelem * 2' of 'psz'.
* if *nelem == 0, initial allocation of NELEM psz block,
* returns pointer to reallocated block of memory with new
* memory initialized to 0/NULL. return must be assigned to
* original pointer in caller.
*/
void *xrealloc2 (void *ptr, size_t psz, size_t *nelem)
{
void *memptr = NULL;
if (!*nelem)
*nelem = NELEM < 2 ? 2 : NELEM / 2;
memptr = realloc (ptr, *nelem * 2 * psz);
if (!memptr) {
perror ("realloc(): virtual memory exhausted.");
exit (EXIT_FAILURE);
/* return NULL; */
} /* zero new memory (optional) */
memset ((char *)memptr + *nelem * psz, 0, *nelem * psz);
*nelem *= 2;
return memptr;
}
int main (int argc, char **argv) {
float *arr = NULL; /* pointer to allocate block of floats */
size_t n = 0, /* number of floats read */
nelem = 0, /* number allocated */
sqsize = 0; /* square size of 2D matrix */
/* use filename provided as 1st argument (stdin by default) */
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
perror ("file open failed");
return 1;
}
for (;;) { /* loop continually reading float from file */
if (n == nelem) /* is realloc needed? */
arr = xrealloc2 (arr, sizeof *arr, &nelem); /* realloc 2x current */
if (fscanf (fp, "%f", &arr[n]) != 1) { /* read/validate float */
if (n) /* if values stored, break loop */
break;
else /* otherwise, error or EOF before values read */
exit (EXIT_FAILURE);
}
n++;
}
if (fp != stdin) /* close file if not stdin */
fclose (fp);
while (sqsize * sqsize < n) /* determine size of square matrix */
sqsize++;
if (sqsize * sqsize != n) { /* validate only that number read */
fputs ("error: n not a square.\n", stderr);
exit (EXIT_FAILURE);
}
for (size_t i = 0; i < sqsize; i++) { /* output matrix */
for (size_t j = 0; j < sqsize; j++)
printf (" %2g", arr[i * sqsize + j]);
putchar ('\n');
}
free (arr); /* free allocated memory */
}
由于您一次阅读一个 float
,因此数字是否全部排成一行、一个 per-line 或以 square-matrix 形式排列并不重要, fscanf()
跳过 whitespace 无论是 space 还是换行符。
例子Use/Output
2x2:
$ echo "1.1 2.2 3.3 4.4" | ./bin/array_1d2d_square_float
1.1 2.2
3.3 4.4
non-square:
$ echo "1.1 2.2 3.3 4.4 5.5" | ./bin/array_1d2d_square_float
error: n not a square.
3x3:
$ echo "1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8 9.9" | ./bin/array_1d2d_square_float
1.1 2.2 3.3
4.4 5.5 6.6
7.7 8.8 9.9
9x9 来自文件 1-81:
$ ./bin/array_1d2d_square_float dat/81int.txt
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18
19 20 21 22 23 24 25 26 27
28 29 30 31 32 33 34 35 36
37 38 39 40 41 42 43 44 45
46 47 48 49 50 51 52 53 54
55 56 57 58 59 60 61 62 63
64 65 66 67 68 69 70 71 72
73 74 75 76 77 78 79 80 81
我也玩得很开心,也创建了一个程序,它可能更容易理解一些。 :-)
#include <stdio.h>
#include <string.h>
/* Program to read a square matrix from a file */
/* Syntax: <programname> <filename> */
int main(int argc, char *argv[])
{
FILE *f_pointer = NULL;
f_pointer = fopen(argv[1],"r");
if(f_pointer==NULL)
{
printf("File not found\n");
return 1;
}
else
{
char floatbuffer[32] = "";
float matrix_member[256]; /* supports up to a 16x16 square matrix */
int matrix_entries = 0;
int matrix_columns_n_rows = 0;
for(int i = 0; !feof(f_pointer); i = fgetc(f_pointer))
{
if(i=='\n'||i==' ')
{
/* do nothing */
}
else if(i==',')
{
/* read matrix member */
sscanf(floatbuffer, "%f", &matrix_member[matrix_entries]);
matrix_entries++;
floatbuffer[0] = '[=10=]'; /* reset floatbuffer */
}
else
{
char c[2] = {i&0b11111111, '[=10=]'}; /* transform unsigned char to string */
strcat(floatbuffer, c);
}
}
/* read last matrix member too */
sscanf(floatbuffer, "%f", &matrix_member[matrix_entries]);
matrix_entries++;
/* close file */
fclose(f_pointer);
printf("total matrix entries %i\n", matrix_entries);
for(int i = 0; i<matrix_entries; i++)
{
printf("entry #%i: %f\n", i+1, matrix_member[i]);
}
/* check for plausbility */
for(int i = 1; i<17; i++)
{
if(i*i==matrix_entries)
{
matrix_columns_n_rows=i;
}
}
if(matrix_columns_n_rows)
{
printf("this is a valid square matrix with %i columns and %i rows\n", matrix_columns_n_rows, matrix_columns_n_rows);
return 0;
}
else
{
printf("this isn't a valid square matrix\n");
return 2;
}
}
}
输出
total matrix entries 9
entry #1: 0.100009
entry #2: 0.200008
entry #3: 0.300007
entry #4: 0.400006
entry #5: 0.500005
entry #6: 0.600004
entry #7: 0.700003
entry #8: 0.800002
entry #9: 0.900001
this is a valid square matrix with 3 columns and 3 rows
我用 c 语言编写了一段代码,它从文本文件中读取数字并将它们放入数组中的矩阵格式。问题是我已经使我的代码适用于确定大小为 3x3 的矩阵。如果我必须增加大小,我必须直接在代码中更改它。我怎样才能改变我的代码,以便它自动创建一个所需大小的数组并读取文件而不考虑它的长度(假设输入文件将包含足够的数字来形成一个方阵)?例如,我可以给它一个输入文件,其中包含一个 nxn 矩阵的逗号分隔的数字,我的代码应该给我一个包含这些数字的 nxn 矩阵。 这是我的代码,
#include <stdio.h>
#include <stdlib.h>
//Declaring Matrices
float A[3][3];
//Function to read the matrices from a file
int ReadMatrix(void){
FILE * f_pointer;
f_pointer = fopen("Input Matrix.txt","r");
if(f_pointer==NULL){
printf("Error 404:- File not found");
return 1;
}
fscanf(f_pointer,"%f, %f, %f\n%f, %f, %f\n%f, %f, %f", &A[0][0], &A[0][1], &A[0][2], &A[1][0], &A[1][1], &A[1][2], &A[2][0], &A[2][1], &A[2][2]);
return 0;
}
可能最简单的 single-pass 方法很简单,就是将文件中的浮点数读取到分配的内存块中,可以根据需要使用 realloc
扩展该内存块,直到读取所有值。然后您可以简单地循环并确定读取的值的数量是否会形成一个方阵——如果它们不会,则处理错误。然后,您将拥有一个有效存储的浮点数块,可以通过简单的算术将其作为二维数组进行操作。例如,如果您读取 9 个值,并且您的正方形大小为 3x3,则您可以访问 i, j
行和列值作为:
array [i * 3 + j];
(注意: 另一种选择——您可以分配 n
指针和 n
额外的 n
块 - 如果需要,可以浮动真正的二维索引,例如 array [i][j]
-- 由你决定)
一个简单的实现可以是:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NELEM 16 /* initial number of floats to allocate */
/** realloc 'ptr' of 'nelem' of 'psz' to 'nelem * 2' of 'psz'.
* if *nelem == 0, initial allocation of NELEM psz block,
* returns pointer to reallocated block of memory with new
* memory initialized to 0/NULL. return must be assigned to
* original pointer in caller.
*/
void *xrealloc2 (void *ptr, size_t psz, size_t *nelem)
{
void *memptr = NULL;
if (!*nelem)
*nelem = NELEM < 2 ? 2 : NELEM / 2;
memptr = realloc (ptr, *nelem * 2 * psz);
if (!memptr) {
perror ("realloc(): virtual memory exhausted.");
exit (EXIT_FAILURE);
/* return NULL; */
} /* zero new memory (optional) */
memset ((char *)memptr + *nelem * psz, 0, *nelem * psz);
*nelem *= 2;
return memptr;
}
int main (int argc, char **argv) {
float *arr = NULL; /* pointer to allocate block of floats */
size_t n = 0, /* number of floats read */
nelem = 0, /* number allocated */
sqsize = 0; /* square size of 2D matrix */
/* use filename provided as 1st argument (stdin by default) */
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
perror ("file open failed");
return 1;
}
for (;;) { /* loop continually reading float from file */
if (n == nelem) /* is realloc needed? */
arr = xrealloc2 (arr, sizeof *arr, &nelem); /* realloc 2x current */
if (fscanf (fp, "%f", &arr[n]) != 1) { /* read/validate float */
if (n) /* if values stored, break loop */
break;
else /* otherwise, error or EOF before values read */
exit (EXIT_FAILURE);
}
n++;
}
if (fp != stdin) /* close file if not stdin */
fclose (fp);
while (sqsize * sqsize < n) /* determine size of square matrix */
sqsize++;
if (sqsize * sqsize != n) { /* validate only that number read */
fputs ("error: n not a square.\n", stderr);
exit (EXIT_FAILURE);
}
for (size_t i = 0; i < sqsize; i++) { /* output matrix */
for (size_t j = 0; j < sqsize; j++)
printf (" %2g", arr[i * sqsize + j]);
putchar ('\n');
}
free (arr); /* free allocated memory */
}
由于您一次阅读一个 float
,因此数字是否全部排成一行、一个 per-line 或以 square-matrix 形式排列并不重要, fscanf()
跳过 whitespace 无论是 space 还是换行符。
例子Use/Output
2x2:
$ echo "1.1 2.2 3.3 4.4" | ./bin/array_1d2d_square_float
1.1 2.2
3.3 4.4
non-square:
$ echo "1.1 2.2 3.3 4.4 5.5" | ./bin/array_1d2d_square_float
error: n not a square.
3x3:
$ echo "1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8 9.9" | ./bin/array_1d2d_square_float
1.1 2.2 3.3
4.4 5.5 6.6
7.7 8.8 9.9
9x9 来自文件 1-81:
$ ./bin/array_1d2d_square_float dat/81int.txt
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18
19 20 21 22 23 24 25 26 27
28 29 30 31 32 33 34 35 36
37 38 39 40 41 42 43 44 45
46 47 48 49 50 51 52 53 54
55 56 57 58 59 60 61 62 63
64 65 66 67 68 69 70 71 72
73 74 75 76 77 78 79 80 81
我也玩得很开心,也创建了一个程序,它可能更容易理解一些。 :-)
#include <stdio.h>
#include <string.h>
/* Program to read a square matrix from a file */
/* Syntax: <programname> <filename> */
int main(int argc, char *argv[])
{
FILE *f_pointer = NULL;
f_pointer = fopen(argv[1],"r");
if(f_pointer==NULL)
{
printf("File not found\n");
return 1;
}
else
{
char floatbuffer[32] = "";
float matrix_member[256]; /* supports up to a 16x16 square matrix */
int matrix_entries = 0;
int matrix_columns_n_rows = 0;
for(int i = 0; !feof(f_pointer); i = fgetc(f_pointer))
{
if(i=='\n'||i==' ')
{
/* do nothing */
}
else if(i==',')
{
/* read matrix member */
sscanf(floatbuffer, "%f", &matrix_member[matrix_entries]);
matrix_entries++;
floatbuffer[0] = '[=10=]'; /* reset floatbuffer */
}
else
{
char c[2] = {i&0b11111111, '[=10=]'}; /* transform unsigned char to string */
strcat(floatbuffer, c);
}
}
/* read last matrix member too */
sscanf(floatbuffer, "%f", &matrix_member[matrix_entries]);
matrix_entries++;
/* close file */
fclose(f_pointer);
printf("total matrix entries %i\n", matrix_entries);
for(int i = 0; i<matrix_entries; i++)
{
printf("entry #%i: %f\n", i+1, matrix_member[i]);
}
/* check for plausbility */
for(int i = 1; i<17; i++)
{
if(i*i==matrix_entries)
{
matrix_columns_n_rows=i;
}
}
if(matrix_columns_n_rows)
{
printf("this is a valid square matrix with %i columns and %i rows\n", matrix_columns_n_rows, matrix_columns_n_rows);
return 0;
}
else
{
printf("this isn't a valid square matrix\n");
return 2;
}
}
}
输出
total matrix entries 9
entry #1: 0.100009
entry #2: 0.200008
entry #3: 0.300007
entry #4: 0.400006
entry #5: 0.500005
entry #6: 0.600004
entry #7: 0.700003
entry #8: 0.800002
entry #9: 0.900001
this is a valid square matrix with 3 columns and 3 rows