c - (C) 尝试将 .txt 文件读入二维数组(请注意,失败了!)

标签 c windows memory memory-management multidimensional-array

我用过不少 PHP 工作,也用过一些 C++,但对 C 来说还是个新手,你可以从我困惑的代码中看出这一点。基本上,我希望将 .txt 文件(网格,在本例中是为我和我的 friend 制作游戏)的内容读取到二维数组中,处理文件的内容,并将处理后的内容输出到单独的文件中.txt 文件。

void grab_input(char *infile, int *rows, int *cols, char *buffer);
void send_output(char *outfile, int rows, int cols, char buffer);
int process_input(char *buffer);

int main(int argc, char *argv[])
{
    int rows;
    int cols;
    int i;
    char **buffer;
    if (argc != 2)
    {
        printf("Usage: %s filename\n", argv[0]);
        exit(EXIT_FAILURE);
    }
    buffer = (char**)malloc((rows + 2) * sizeof(char *));
    for (i = 0; i < rows; i++)
        buffer[i] = (char *)malloc(cols*sizeof(char));
    grab_input(argv[1], &rows, &cols, &buffer);
    process_input(&buffer);
    send_output(argv[2], rows, cols, *buffer);
    printf("\n%s\n", argv[2]);
    printf("%d\n", cols);

    return 0;
}

void grab_input(char *infile, int *rows, int *cols, char *buffer)
{
    FILE *input;
    input = fopen(infile, "r");
    if (input != 0)
        printf("The file exists.\n");
    else
        printf("No file.\n");
    fscanf(input, "%d %d", rows, cols);
    printf("Unprocessed grid:");
    while (fgets(buffer, (*rows+2) * (*cols+2) * sizeof(char)+1, input) != NULL)  {

        printf("%s", buffer);
    }
    fclose(input);
    printf("\nRows: %d\nColumns: %d\n", *rows, *cols);
}

为此,我收到几个控制台错误和“调试错误...变量 cols 周围的堆栈已损坏”。我在各个网站上阅读了大量有关动态内存分配的内容,但显然我不太清楚如何将其付诸实践并从文件中创建动态分配的二维数组。如果您能帮助我,我将不胜感激。

Here's a picture of my console window.

And here's one of the contents of my input.txt file.

非常感谢您的帮助。

最佳答案

应用所有注释并清理逻辑并执行适当的错误检查结果如下。

以下内容可以顺利编译。

以下内容未经测试。

#include <stdio.h>  // fgets(), fopen(), fclose(), 
                    // sscanf(), fprintf(), printf()
#include <stdlib.h> // exit(), EXIT_FAILURE
#include <string.h> // memset()

void grab_sizeInfo( FILE *input, size_t *pRow, size_t *pCols );
void grab_input( FILE* fp_in, size_t rows, size_t cols, char **buffer);
void send_output(char *outfile, size_t rows, size_t cols, char **buffer);
void process_input(size_t rows, size_t columns, char **buffer);

int main(int argc, char *argv[])
{
    size_t rows = 0;
    size_t cols = 0;
    char **buffer = NULL;

    if (argc != 3)
    {
        fprintf(stderr, "Usage: %s InputFilename OutputFilename\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    FILE *fp_in = NULL;
    if( NULL == (fp_in = fopen( argv[1], "r") ) )
    { // then fopen failed
        perror( "fopen for input file failed" );
        exit( EXIT_FAILURE );
    }

    // implied else, fopen successful

    grab_sizeInfo( fp_in, &rows, &cols );
    printf("\nRows: %lu\nColumns: %lu\n", rows, cols);

    rows+=2;  // adjust for actual size
    cols+=2;  // adjust for actual size
    cols+=1;  // +1 to allow for NUL terminator byte

    if( NULL == ( buffer = malloc(rows * sizeof(char *)) ) )
    { // then malloc failed
        perror( "malloc for array of pointers to rows failed");
        fclose( fp_in );
        exit( EXIT_FAILURE );
    }

    // implied else, malloc for array of pointers to rows successful

    // prep array of pointers, to make cleanup easy
    memset( buffer, '\0', rows * sizeof(char *) );

    for ( size_t i = 0; i < rows; i++ )
    {
        if( NULL == (buffer[i] = malloc(cols) ) ) 
        { // malloc failed
            perror( "malloc for row failed" );
            // cleanup
            for( size_t j=0; j < rows; j++ )
            {
                free( buffer[j] );
            }
            free( buffer );
            fclose( fp_in );
            exit( EXIT_FAILURE );
        }

        // implied else, malloc for array of char in row successful

    } // end for each row

    grab_input( fp_in, rows, cols, buffer);
    fclose( fp_in );

    process_input(rows, cols, buffer);
    send_output(argv[2], rows, cols, buffer);

    printf("\n%s\n", argv[2]);
    printf("%lu\n", cols);

    return 0;
} // end function: main


void grab_sizeInfo( FILE *fp, size_t *pRow, size_t *pCols )
{
    char firstLine[20] = {'\0'};

    if( fgets( firstLine, sizeof firstLine, fp ) )
    { // successful read
        if( 2 != sscanf( firstLine, "%lu %lu", pRow, pCols) )
        { // then sscanf failed
            perror( "sscanf for rows and columns failed" );
            fclose( fp );
            exit(EXIT_FAILURE);
        }
    }
} // end function: grab_sizeInfo


void grab_input(FILE *fp, size_t rows, size_t cols, char **buffer)
{
    size_t rowNum = 0;
    while ( rowNum < rows && fgets( buffer[rowNum], (int)cols, fp ) )
    {
        printf("%s", buffer[rowNum]);
        rowNum++;
    }

    if( rowNum != rows )
    { // then failed to read complete file
        fprintf( stderr, "number of rows read: %lu Not equal Number expected rows: %lu\n", rowNum, rows );
        for( size_t i=0; i<rows; i++ )
        {
            free( buffer[i] );
        }
        free( buffer );
        fclose( fp );
        exit( EXIT_FAILURE );
    }
} // end function: grab_input

关于c - (C) 尝试将 .txt 文件读入二维数组(请注意,失败了!),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35643278/

相关文章:

在源文件中一致地使用类型

c++ - 多个 DLLMain 函数

c# - Windows 文件系统?

c++ - 将大文件加载到内存中并在程序的所有运行时间中保留它是否错误?

c++ - 如何修复内存访问错误

c++ - c变量在内存中的存储

c - 指针无限地接受输入

c - 如何检查符号链接(symbolic link)是否指向目录

c# - Windows GUI 控件 ID 是如何创建的?

windows - docker 警告 : failed to get default registry endpoint from daemon