我必须从文件中读取数组,而事实上我是最后一列,只是没有被复制。数组的大小及其内容在文件中。这是代码(仅是问题所在的部分):

#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;

最佳答案

使用面向行的输入将文件中的所有行读入动态分配的数组中,可以为您提供更好的服务。标准库中可用的面向行的函数是fgetsgetline

在这种情况下,如果您不知道每行的最大字符数,最好使用getline读取每行,因为getline将为您动态分配足够大小的行缓冲区。

如果使用fgets(很好),则必须添加代码以检查每行以及reallocstrcat行的短读或不完整读,直到完全读完为止。 getline只是使生活更简单。

您的基本方案是声明一个指向类型的指针(即双指针),分配合理数量的指针来处理文件,如果达到初始限制,则realloc 2X该数字当前指针并继续。

完成后,释放分配的行,然后释放数组。一个简单的例子:

#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;
}


使用内存错误检查器(如Linux上的valgrind)确认内存的正确使用,并在不再需要时正确释放了所有内存。查看一下,如果您还有其他问题,请与我们联系。

数值数组

对于数字数组,您采用的方法完全相同。但是,不是将ln存储在指向char的指针数组中,而是只需根据需要使用sscanf或最好是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;
    }
}


用于验证到longrealloc的转换的辅助函数可以写为:

/* 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;
}


注意:您可以调整是否在内存耗尽时返回NULLexit以满足您的需要。对于转换,可以通过strtol使用简单的错误检查,如下所示。

/* simple strtol wrapper with error checking */
long xstrtol (char *p, char **ep, int base)
{
    errno = 0;

    long tmp = strtol (p, ep, base);

    /* Check for various possible errors */
    if ((errno == ERANGE && (tmp == LONG_MIN || tmp == LONG_MAX)) ||
        (errno != 0 && tmp == 0)) {
        perror ("strtol");
        exit (EXIT_FAILURE);
    }

    if (*ep == p) {
        fprintf (stderr, "No digits were found\n");
        exit (EXIT_FAILURE);
    }

    return tmp;
}


我已经放置了一个完整的示例,说明如何在pastbin中将文件读取到动态分配的long的2D数组中:C - read file into dynamically allocated 2D array

关于c - 如何从文件复制到数组,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/34688545/

10-12 16:15
查看更多