【问题标题】:Reading a file into a 2d array将文件读入二维数组
【发布时间】:2014-08-09 15:28:26
【问题描述】:

从 c 中读取文件(本质上是某种字符的网格图)并将其放入某种二维数组中时,最好的方法是什么,字符可以通过它的坐标访问?

示例输入文件类似于:

ffflli
ffsdfg
fl979p
kl8dfj

每个字符都可以通过坐标访问,具体取决于它们的位置。即左下角坐标为 (0,3)

【问题讨论】:

  • 你试过什么?你有任何代码吗?我们可以看到一个示例输入文件吗?您所说的“最佳”方法是什么意思?你没有给我们太多的帮助。
  • 您是否有给定的文件格式,或者您可以自己选择或创建一个?
  • 先向我们展示您的方法,然后再寻找最佳方法。
  • 最好的方法取决于你的理解水平
  • 示例输入文件:a76dhk aaaufg ffklsi sklify

标签: c multidimensional-array


【解决方案1】:

你可以这样做:

FILE *f;
    f = fopen("sample.txt","r");
    char ch, strr[100], *str;
    int row = 0, column = 0, i = 0, j = 0;
    while(fgets(strr, sizeof strr, f)) {
        row++;
        if(column < strlen(strr) )
            column = strlen(strr);
    }
    rewind(f);
    char arr[row][column];
    while(i < row) {
        ch = fgetc(f);
        while( ch != EOF || ch != '\n') {
            arr[i][j] = ch;
            j++;
        }
        i++;
    }
    fclose(f);

如果文件非常大,您也可以避免对文件进行第一次迭代。这是为了避免通过不必要地为数组分配大尺寸来浪费内存。

【讨论】:

    【解决方案2】:

    我会建议你一种方法

    while not end of file
        if character pointed by file pointer is not '\n' or EOF
           push chracter into array 
    

    【讨论】:

      【解决方案3】:

      这对我来说效果很好。它像提供的那样遍历 infile,填充提供的 2D 数组,并以空值终止未使用的插槽。

      #include <stdio.h>
      #include <stdlib.h>
      #include <assert.h>
      #include <memory.h>
      
      int main(int argc, char* argv[])
      {
          FILE* infile;
          char* file_path = "C:\\Your\\File\\Path\\Here.txt";
          char grid[10][10];
          unsigned int num_rows = 10;
      
          // Open infile for reading.
          if (0 == fopen_s(&infile, file_path, "r"))
          {
              char character;
              unsigned int row = 0;
              unsigned int column = 0;
      
              // Iterate through entire infile.
              while (!feof(infile))
              {
                  // Scan in next character.
                  fscanf_s(infile, "%c", &character, 1);
      
                  // Check for newline, moving to next grid row when necessary.
                  if (character == '\n')
                  {
                      // Null-terminate/zero rest of row.
                      grid[row][column] = '\0';
      
                      // Move to beginning of next row.
                      ++row;
                      column = 0;
      
                      continue;
                  }
      
                  // Set appropriate cell to next character.
                  grid[row][column] = character;
                  ++column;
              }
      
              // Null-terminate to sever junk in unused slots.
              for (; row < num_rows; ++row)
              {
                  grid[row][column] = '\0';
                  column = 0;
              }
      
              // Close file.
              fclose(infile);
          }
      
          return 0;
      }
      

      一些注意事项:

      1. 我认为 10x10 的网格就足够了。如果这对您不起作用,请务必更改尺寸。算法应该进行微调(对于合理的尺寸值)。

      2. 连续的多个换行可能会导致完全为空的行。如果您想以不同的方式处理此问题,请在读取输入时检查这种情况。

      3. 我认为空终止行是可取的行为。如果我错了,请随意。

      4. 这是我在 Visual Studio 中编写的,使用 MSVC 编译,因此使用了 fopen_s() 和 fscanf_s()。如果不希望这样做,分别更改 fopen() 和 fscanf() 应该相对简单(主要是更改几个语句和函数参数)。

      我希望这对你有帮助。如果您有任何问题,请告诉我。

      【讨论】:

        【解决方案4】:

        在 C 中,您可以通过将指针转换为正确的类型来访问存储在 1D 缓冲区(如文件)中的任何 2D 数组。像这样:

        int buffer1D[20] = {
            0, 1, 2, 3, 4,
            1, 2, 3, 4, 5,
            2, 3, 4, 5, 6,
            3, 4, 5, 6, 7
        };
        int* bufferPtr = buffer1D;
        
        int (*twoDPtr)[5];    //a pointer of the correct type
        twoDPtr = (int (*)[5])bufferPtr;    //the interesting part: the cast
        

        现在您可以将缓冲区作为二维数组访问:

        assert(twoDPtr[2][3] == 5);
        

        诀窍在于,twoDPtr 是指向二维数据线数组的指针。因此,当您使用twoDPtr[2] 对其执行指针运算时,它将跳过二维数据的前两行。

        【讨论】:

          猜你喜欢
          • 2014-04-06
          • 2014-09-13
          • 1970-01-01
          • 1970-01-01
          • 2013-03-11
          • 2011-08-12
          相关资源
          最近更新 更多