简体   繁体   English

C程序。 从输入文件中获取最高编号,创建二维数组,然后从文件中读取网格

[英]C program. Taking top number from input file, creating 2d array, then reading grid from file

Sorry if this question has been askked I've been looking on this site for a couple hours and haven't seen anything yet. 抱歉,如果有人提出这个问题,我已经在这个网站上搜索了两个小时,还没有看到任何东西。

So I'm reading an input file that looks like this. 所以我正在读取一个看起来像这样的输入文件。 The top line being an 8x8 2d array, then the remaining lines the grid I have to sort through. 第一行是8x8 2d数组,其余的行是我必须排序的网格。 Basically I'm replacing each * with a letter +1, so a,b,c...etc but that's not my question. 基本上,我用字母+1代替每个*,所以a,b,c ...等,但这不是我的问题。

8   <---- The size of the array 8X8
**......       
**..*..*
..**.**.
..**..*.
.*..*..*
..**.**.
..**.**.
.*..*..*

my question is, how can I read just the top line of the input file to find the size of the array then store that as the row and columns of my array, then read the remainder of the file (the grid) and store the characters into the rows and columns of the array? 我的问题是,如何读取输入文件的第一行以查找数组的大小,然后将其存储为数组的行和列,然后读取文件的其余部分(网格)并存储字符进入数组的行和列?

This is what I have so far. 到目前为止,这就是我所拥有的。

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#define N 9

void blobchecker(char[][N]);

main()
{
    FILE *fp;
    fp = fopen("blobfile.txt", "r");
    if ((fp = fopen("blobfile.txt", "r")) == NULL) 
        printf("File not read \n");

    int c;
    char myarray[N][N];
    int i, j;

    fscanf(fp, "%d", &c);
    fclose(fp);
    fp = fopen("blobfile.txt", "r");
    for (i = 0; i < N; i++)
        for (j = 0; j < N; j++)
            fscanf(fp, "%c", &myarray[i][j]);

    for (i = 0; i < N; i++)
        for (j = 0; j < N; j++)
            printf("%c", myarray[i][j]);

    printf("\n Now checking for blobs \n");

    // blobchecker(myarray);

    fclose(fp);
}

Try this: 尝试这个:

int c;
char** myarray;
int i;
fscanf(fp, "%d", &c);
myarray = malloc(c*sizeof(char*));
for (i=0; i<c; i++)
    myarray[i] = malloc(c);

And don't forget to free the allocated memory at a later point in the execution of your program: 并且不要忘记在程序执行的稍后时间释放分配的内存:

for (i=0; i<c; i++)
    free(myarray[i]);
free(myarray);

Here is a solution without using heap allocated memory. 这是不使用堆分配的内存的解决方案。 Note: This solution works only with the C99 standard and onward versions. 注意:此解决方案仅适用于C99标准及更高版本。

int main()
{
    FILE *fp;
    fp = fopen("blobfile.txt", "r");
    if ((fp = fopen("blobfile.txt", "r")) == NULL) {
        printf("File not read \n");
        return 1; // end the program when the file can't be opened
    }

    int c;
    int i, j;

    fscanf(fp, "%d", &c);

    char myarray[c][c]; // variable length array using the read size

    for (i = 0; i < c; i++) // use c as upper limit
        for (j = 0; j < c; j++)
            fscanf(fp, " %c", &myarray[i][j]);

    for (i = 0; i < c; i++)
    {
        for (j = 0; j < c; j++)
            printf("%c", myarray[i][j]);
        printf("\n");
    }
    printf("\n Now checking for blobs \n");

    //blobchecker(myarray);

    fclose(fp);

}

Your problem was opening and reopening the file once you've read the array size. 一旦读取数组大小,您的问题就是打开并重新打开文件。 By opening the file again you reset the 'cursor' ( stream position indicator ) to the beginning of the file. 通过再次打开文件,可以将“游标”( 流位置指示器 )重置为文件的开头。 So the first charactar you've read was the size of your array. 因此,您阅读的第一个字符是数组的大小。

This has been pretty much answered, but couple of additional notes: It might be easier to use fscanf(fp,"%s", myarray[i][]) . 这已经得到了很好的回答,但是还有一些附加说明:使用fscanf(fp,"%s", myarray[i][])可能会更容易。 The fscanf will take care of the newline chararter, and this way you can assign a whole string to a desired array in 2d matrix. fscanf将处理换行符,通过这种方式,您可以将整个字符串分配给2d矩阵中的所需数组。 Makes reading and handling way easier and you can still refer to a specific member of an array using both of his indexes. 使读取和处理方式更容易,您仍然可以使用两个索引来引用数组的特定成员。 Make sure to allocate the memory correctly and take care: fscanf which takes care of the \\n will add it to your string! 确保正确分配内存并保重:负责\\n fscanf会将其添加到您的字符串中! But overall it's a simpler solution. 但总体而言,这是一个更简单的解决方案。 Also, as it has been said, avoid closing and reopening the file. 同样,如前所述,避免关闭并重新打开文件。 If you do this, you're losing an offset pointer so you're basically reading a file all over again from the top, which is neither necessary or needed. 如果这样做,则会丢失偏移指针,因此基本上是从头开始重新读取文件,这既不必要也不是必需的。

Dynamically allocate memory using malloc and free it after its use. 使用malloc动态分配内存,并在使用后free内存。

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
/* `#define N 9` Not needed */

void blobchecker(char**); /* Note the change here */

int main(void) /* Always use a standard signature of main */
{

    /* Indent your code properly always */

    FILE *fp;
    fp = fopen("blobfile.txt", "r");
    if ((fp = fopen("blobfile.txt", "r")) == NULL) 
    {
        /* `printf("File not read \n");` Better to print in stderr */
        fputs("Failed to open file 'blobfile.txt'", stderr);
        return EXIT_FAILURE; /* Exit the program (main) */
    }


    int c;
    /* char myarray[N][N]; */
    char **myarray; /* Note the change here */
    int i, j;

    fscanf(fp, "%d", &c);

    /*
    `fclose(fp);`
    `fp = fopen("blobfile.txt", "r");` Don't close and reopen
    */

    myarray = malloc(c * sizeof *myarray); /* Allocate `c` rows */
    if(NULL == myarray) /* If `malloc` failed */
    {
        fputs("Failed to malloc 'myarray'", stderr);
        return EXIT_FAILURE; /* Exit the program (main) */
    }
    for (i = 0; i < c; i++)
    {
        myarray[i] = malloc(c); /* For each row, allocate `c` columns */
        if(NULL == myarray[i]) /* If `malloc` failed */
        {
            for(j = i - 1; j >= 0; j--) /* `free` all previously allocated memory */
                free(myarray[j]);
            free(myarray);
            fputs("Failed to malloc 'myarray[i]'", stderr);
            return EXIT_FAILURE; /* Exit the program (main) */
        }
    }

    for (i = 0; i < c; i++)
        for (j = 0; j < c; j++)
            fscanf(fp, " %c", &myarray[i][j]); /* Space before `%c` gets rid of whitespaces */

    for (i = 0; i < c; i++)
        for (j = 0; j < c; j++)
            printf("%c", myarray[i][j]);

    printf("\n Now checking for blobs \n");

    //blobchecker(myarray);

    fclose(fp);

    /* `free` whatever you've allocated after its use: */

    for (i = 0; i < c; i++)
        free(myarray[i]);
    free(myarray);

    return EXIT_SUCCESS; /* Exit main */

}

WARNING: Untested code 警告:未经测试的代码


Note that in the above code,each call to malloc may allocate memory non-contiguously and this would result in heap fragmentation and reduced efficiency of the program. 请注意,在上面的代码中,对malloc每次调用都可能不连续地分配内存,这将导致堆碎片化并降低程序的效率。 @Lundin's comments mention more about this. @Lundin的评论提到了更多有关此的内容。

If the dimension is only known in run-time, you can use a VLA: 如果该维仅在运行时已知,则可以使用VLA:

int c;
fscanf(fp, "%d", &c);

char myarray[c][c];

for (i = 0; i < c; i++)
    for (j = 0; j < c; j++)
        fscanf(fp, "%c", &myarray[i][j]);

If the amount of memory to read is wast, it might be better to allocate the 2D array dynamically, to ensure that the memory ends up on the heap: 如果浪费了要读取的内存量,则最好动态分配2D数组,以确保内存最终出现在堆上:

char (*myarray)[c] = malloc( sizeof(char[c][c]) );
...
free(myarray);

There should never be any need of obscure char** -based look-up tables in your case. 在您的情况下,永远不需要模糊的基于char**的查找表。 All they will do is to segment your array all over the heap and make your program slower. 他们要做的就是在整个堆中对数组进行分段,并使程序变慢。


EDIT 编辑

If you need to be backwards-compatible with the 27 years old, obsolete C89 standard, you could write portable code like this: 如果您需要向后兼容27岁的过时的C89标准,则可以编写如下可移植代码:

#ifndef __STDC_VERSION__
  #define OLD_JUNK
#elif __STDC_VERSION__ < 199901L
  #define OLD_JUNK
#endif

#ifdef OLD_JUNK
  #define get_item(arr, x, y) (arr [(x) * (y)] )
#else
  #define get_item(arr, x, y) (arr[x][y])
#endif

int c;
fscanf(fp, "%d", &c);

#ifdef OLD_JUNK
  char* myarray = malloc(c * c);
#else
  char (*myarray)[c] = malloc ( sizeof(char[c][c]) );
#endif

int i, j;
for (i = 0; i < c; i++)
    for (j = 0; j < c; j++)
        fscanf(fp, "%c", &get_item(myarray,i,j) );

free(myarray);

I would however strongly recommend to upgrade to a compiler which is not using 1980s technology. 但是,我强烈建议升级到不使用1980年代技术的编译器。 Then you would not have to write ugly solutions like this. 然后,您将不必编写像这样的丑陋解决方案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM