我必须从一个文件中读取一个数组,并且我最后一列的事实是没有被复制。数组的大小和内容在文件中。这是代码(只是问题所在的部分):
#include<stdio.h>
#include<stdlib>
int main(int argc, char * argv[]){
char **laberinto;
char aux;
fent = fopen(argv[1], "r");
if
fprintf(stderr,"Couldn't open.\n");
else
{
laberinto = (char **) calloc(columnas, sizeof(char *));
for (i = 0; (NULL != laberinto) && (i < columnas); i++)
{
laberinto[i] = (char *) calloc(filas, sizeof(char));
if (NULL == laberinto[i])
{
for ( j = i - 1; j >= 0; j-- )
free(laberinto[j]);
free(laberinto);
laberinto = NULL;
}
}
for(i = 0, j = 0; i < filas+1; i++)
for(j = 0; j < columnas+1; j++)
{
if(!feof(fent))
{
aux = fgetc(fent);
if(aux == '\n')
aux = 0;
}}
Edit 1(full code) it generates a core by the way:
#include<stdio.h>
#include<stdlib.h>
#include"encruta1.h"//Just funcion definitions(not used yet)
#define ERRORCOMANDO "ERROR: linea de comandos incorrecta. Utilice:\n"
#define ERRORCOMAND2 "leelabfich fichero_de_entrada columna_inicio fila_inicio\n"
//Both are error messages
int main(int argc, char *argv[])
{
char **laberinto;
char aux;
int i = 0;//Indice para imprimir la tabla
int j = 0;//Indice para imprimir la tabla
int columnas = 0;
int filas = 0;
int flag1;//Para saber si fscanf ha funcionado bien
FILE *fent;
//Si son cuatro argumentos es correcto
if(argc == 4)
{
//Apertura de archivo
fent = fopen(argv[1], "r");
if(fent == NULL)
fprintf(stderr,"No se puede abrir el fichero de entrada.\n");
else
{
flag1 = fscanf(fent,"%d%d", &columnas, &filas);
if(flag1 == 2)
{
if(filas < 0 || columnas < 0)
fprintf(stderr,"Las dimensiones han de ser dos numeros enteros.\n");
else
{
//Reserva de memoria
laberinto = (char **) calloc(columnas, sizeof(char *));
for (i = 0; (NULL != laberinto) && (i < columnas); i++)
{
laberinto[i] = (char *) calloc(filas, sizeof(char));
if (NULL == laberinto[i])
{
for ( j = i - 1; j >= 0; j-- )
free(laberinto[j]);
free(laberinto);
laberinto = NULL;
}
}
//Pasamos el laberinto del archivo a la tabla
for(i = 0, j = 0; i < filas+1; i++)
for(j = 0; j < columnas+1; j++)
{
if(!feof(fent))
{
aux = fgetc(fent);
if(aux == '\n')
aux = 0;
else
laberinto[i][j] = aux;
}
}
for(i = 0; i < filas; i++)
{
for(j = 0; j < columnas; j++)
{//Eliminamos los intentos fallidos
if(laberinto[i][j] == 'o')//Just ignore the o
laberinto[i][j] = '.';
printf("%c", laberinto[i][j]);
}
printf("\n");
}
//Sustituir por donde se libere memoria abajo
for(i = 0; i < columnas+1; i++)
free(laberinto[i]);
laberinto = NULL;
答案 0 :(得分:1)
使用面向行的输入将文件中的所有行读取到动态分配的数组中会更好。标准库中提供的面向行的函数为fgets
和getline
。
在这种情况下,如果您不知道每行中的最大字符数是多少,则最好使用getline
来读取每一行,因为getline
将动态分配行缓冲区足够大的。
如果您使用fgets
(这很好),您必须添加代码以检查每行的简短或不完整读取和{ {1}}和realloc
该行直到完成读取。 strcat
让这里的生活更简单。
你的基本方案是声明一个指向指针的类型指针(即一个双指针),分配一个合理数量的指针来处理文件,如果达到初始限制,getline
realloc
当前指针的数量并继续。
完成后,释放分配的行,然后释放数组。一个简单的例子:
2X
使用内存错误检查程序(如Linux上的#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NMAX 128 /* initial number of pointers */
int main (int argc, char **argv) {
char **array = NULL; /* array to hold lines read */
char *ln = NULL; /* NULL forces getline to allocate */
size_t n = 0; /* initial ln size, getline decides */
ssize_t nchr = 0; /* number of chars actually read */
size_t idx = 0; /* array index counter */
size_t nmax = NMAX; /* check for reallocation */
size_t i = 0; /* general loop variable */
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin; /* open stream */
if (!fp) { /* validate stream open for reading */
fprintf (stderr, "error: file open failed '%s',\n", argv[1]);
return 1;
}
/* allocate NMAX pointers to char* */
if (!(array = calloc (NMAX, sizeof *array))) {
fprintf (stderr, "error: memory allocation failed.");
return 1;
}
/* read each line from fp */
while ((nchr = getline (&ln, &n, fp)) != -1)
{
/* strip newline or carriage rtn */
while (nchr && (ln[nchr-1] == '\n' || ln[nchr-1] == '\r'))
ln[--nchr] = 0;
array[idx++] = strdup (ln); /* allocate/copy ln to array */
if (idx == nmax) { /* if idx reaches nmax, reallocate */
char **tmp = realloc (array, nmax * 2 * sizeof *tmp);
if (!tmp) {
fprintf (stderr, "error: memory exhausted.\n");
break;
}
array = tmp; /* set new pointers NULL */
memset (array + nmax, 0, nmax * sizeof tmp);
nmax *= 2;
}
}
if (ln) free (ln); /* free memory allocated by getline */
if (fp != stdin) fclose (fp); /* close open file if not default */
/* print array */
printf ("\n lines read from '%s'\n\n", argc > 1 ? argv[1] : "stdin");
for (i = 0; i < idx; i++)
printf (" line[%3zu] %s\n", i, array[i]);
for (i = 0; i < idx; i++)
free (array[i]); /* free each line */
free (array); /* free pointers */
return 0;
}
)确认内存的正确使用,并在不再需要时正确释放所有内存。仔细看看,如果您有其他问题,请告诉我。
数字数组
对于数值数组,您的方法完全相同。但是,不是将valgrind
存储在指向char的指针数组中,而是使用ln
或者sscanf
等方式根据需要解析行...所需的更改很少。 e.g:
strtol
你的阅读循环如下:
...
#include <limits.h>
#include <errno.h>
...
long *array = NULL; /* pointer to long */
int base = argc > 2 ? atoi (argv[2]) : 10; /* base (default: 10) */
...
验证转化为/* read each line from file - separate into array */
while ((nchr = getline (&ln, &n, fp)) != -1)
{
char *p = ln; /* pointer to ln read by getline */
char *ep = NULL; /* endpointer for strtol */
while (errno == 0)
{ /* parse/convert each number in line into array */
array[idx++] = xstrtol (p, &ep, base);
if (idx == nmax) /* check NMAX / realloc */
array = realloc_long (array, &nmax);
/* skip delimiters/move pointer to next digit */
while (*ep && *ep != '-' && (*ep < '0' || *ep > '9')) ep++;
if (*ep)
p = ep;
else
break;
}
}
和long
的辅助函数可以写成:
realloc
注意:您可以调整是否在内存耗尽时返回/* reallocate long pointer memory */
long *realloc_long (long *lp, unsigned long *n)
{
long *tmp = realloc (lp, 2 * *n * sizeof *lp);
if (!tmp) {
fprintf (stderr, "%s() error: reallocation failed.\n", __func__);
// return NULL;
exit (EXIT_FAILURE);
}
lp = tmp;
memset (lp + *n, 0, *n * sizeof *lp); /* memset new ptrs 0 */
*n *= 2;
return lp;
}
或NULL
以满足您的需求。对于转换,您可以使用exit
进行简单的错误检查,如下所示。
strtol
我已经提供了一个完整的示例,说明如何在pastbin中将文件读取为动态分配的2D数组:C - read file into dynamically allocated 2D array