【问题标题】:Create a 2D Dynamic String Array [duplicate]创建一个 2D 动态字符串数组 [重复]
【发布时间】:2017-05-25 10:27:11
【问题描述】:

谁能向我解释动态创建具有稳定第二维的二维字符串数组的最简单方法?我有一个包含一些字符串的 txt 文件,我想将此 txt 传输到一个数组。所以我想将 txt 行号与第一维相关联,将字符串本身与第二维相关联。第二个维度是每一行的字符数(这是稳定的,因为txt中的每一行都有一定的语法)所以如果我的txt中有:

hello how (newline)
are youuu

*(我写了youuu,因为正如我所说,每一行都有相同数量的字符)。

我想要类似的东西:

array[0]["hello how"],
array[1]["are youuu"]

【问题讨论】:

  • 您是否只是想知道如何动态分配一个二维数组,或者如何调整一个数组的大小?可能是char (*arr)[CHARS_PER_LINE] = malloc(sizeof(*arr) * NUM_LINES); 之类的?
  • 在您的示例中,第一行有一个“(换行符)”,但第二行没有。这是故意的、疏忽还是什么?
  • “第二维是字符数”和“字符串数组”略有矛盾。要在 C 中存储 字符串,数组的大小需要为“字符数”+1。

标签: c


【解决方案1】:

在 C 中不允许使用非数字键。您正试图用一种仅适用于数字的语言来做一些 PHP 和 JavaScript 废话。

但是,C 语言总是有两条通往地狱的路。

char *lookup_key(int index, char *key) { ... }


printf(lookup_key(0, "hello how"));

【讨论】:

    【解决方案2】:

    如果你知道字符串的长度和你有多少,你可以像这样配置数组

    char strings[numLines][strLen+1];
    

    然后你可以像这样访问数组

    strcpy(strings[1], "test2");
    

    如果你事先什么都不知道,你需要一个指向指针数组的指针,然后随着数组的增长使用 malloc 分配空间,完成后释放。

    【讨论】:

    • 当然,我的错
    • 也许是size_t strLen = foo(); char (*strings)[strLen + 1] = malloc(sizeof *arr * numLines);?
    【解决方案3】:
    C 中的

    dynamic 意味着您将需要使用 [c][m]alloc 之一来为您的字符串创建内存。而 2D 意味着一个由char 数组组成的数组。假设您知道 strings 的数量和所需的最长字符串,以下将创建内存来包含它们:

    char ** Create2DStr(ssize_t numStrings, ssize_t maxStrLen)
    {
        int i;
        char **a = {0};
        a = calloc(numStrings, sizeof(char *));
        for(i=0;i<numStrings; i++)
        {
          a[i] = calloc(maxStrLen + 1, 1);
        }
        return a;
    }
    

    以下将释放上面创建的内存:

    void free2DStr(char ** a, ssize_t numStrings)
    {
        int i;
        for(i=0;i<numStrings; i++)
        {
            if(a[i]) free(a[i]);
        }
        free(a);
    }
    

    这些可以这样调用:

    ...
    char **strArray = {0};
    strArray = Create2DStr(10, 20);
    //Use strArray...
    free2DStr(10);
    

    给出 10 个数组,每个数组可以包含 20 个字符,外加一个 NULL。 (maxStrLen 之后的+ 1 为 NULL 提供了额外的空间。

    【讨论】:

    • 从技术上讲,这不是二维数组或数组数组......它是一个一维指针数组,每个指针指向一个单独分配的一维数组char。实际的二维数组也是可以的,但不同。
    • char (*arr)[21] = calloc(10, sizeof(*arr)); 呢?
    • @Dmitri - 是的,只要 21 在运行时已知,它就可以正常工作。我用过类似的东西。但如果不是,则需要 malloc 或 calloc。粗略地说,有来自 C99 及以后的 variable length arrays
    【解决方案4】:

    如果要将文件的每一行保存为数组中的一行,请使用char 的二维数组:

    char fileContents[NUM_LINES][LINE_LENGTH + 1]; // +1 for zero terminator
    

    如果您不知道前面有多少行,则需要进行一些内存管理。首先,您需要分配一个初始范围:

    #define INITIAL_EXTENT 20 // or some good starting point
    
    char (*fileContents)[LINE_LENGTH + 1] = malloc( sizeof *fileContents * INITIAL_EXTENT );
    if ( !fileContents )
    {
      // malloc failed; fatal error
      fprintf( stderr, "FATAL: could not allocate memory for array\n" );
      exit( EXIT_FAILURE );
    }
    size_t numRows = INITIAL_EXTENT; // number of rows in array
    size_t rowsRead = 0;             // number of rows containing data
    

    当您从文件中读取数据时,您将检查以确保数组中有空间;如果不这样做,则需要使用 realloc 调用来扩展数组,这可能是一项昂贵的操作。一种常见的技术是每次扩展数组时都将数组的大小加倍——这可以最大限度地减少realloc 调用的总数。如果您将数组大小加倍,则风险是一些内部碎片,因为您只需要多行,但这可能是您可以分析的东西:

    char tmpBuf[LINE_LENGTH + 2]; // account for newline in input buffer
    
    while ( fgets( tmpBuf, sizeof tmpBuf, inputFile ) )
    {
      /**
       * Check to see if you have any room left in your array; if not, 
       * you'll need to extend it.  You'll probably want to factor this 
       * into its own function.
       */
      if ( rowsRead == numRows ) 
      {
        /**
         * Use a temporary variable for the result of realloc in case of failure
         */
        char (*tmp)[LINE_LENGTH + 1] = 
          realloc( fileContents, sizeof *fileContents * ( 2 * numRows ) );
    
        if ( !tmp )
        {
          /**
           * realloc failed - we couldn't extend the array any more.  
           * Break out of the loop. 
           */
          fprintf( stderr, "ERROR: could not extend fileContents array - breaking out of loop\n" );
          break;
        }
        /**
         * Otherwise, set fileContents to point to the new, extended buffer
         * and update the number of rows.  
         */
        fileContents = tmp;
        numRows *= 2;
      }
    
      // strip the newline from the input buffer
      char *newline = strchr( tmpBuf, '\n' );
      if ( newline )
        *newline = 0;
    
      strcpy( fileContents[rowsRead++], tmpBuf );
    }
    

    【讨论】:

      猜你喜欢
      • 2022-11-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-12
      • 2017-03-29
      • 2012-02-15
      • 1970-01-01
      相关资源
      最近更新 更多