【问题标题】:How to create dynamic 2D array of different size strings如何创建不同大小字符串的动态二维数组
【发布时间】:2016-08-25 07:26:03
【问题描述】:

我想读取一个 .txt 文件。

.txt 文件将有 N 行和 M 列。

txt 文件中的每个单词都有不同的长度。

示例 txt 文件:

Suppose N = 4 rows

Suppose M = 5 cols

txt 文件内容:

aa bbb cc dddddddd eeee

aa bbbbbbbbbbbb cc ddddddddddd eeee

aaaaaaaaaa bb cc d e

a b c d eeee

我必须做什么:

我必须将这些字符串存储到一个二维字符串数组中,使其看起来像这样:

arr[4][5] =  

[aa             bbb              cc     dddddddd        eeee]

[aa             bbbbbbbbbbbb     cc     ddddddddddd     eeee]

[aaaaaaaaaa     bb               cc     d               e   ]

[a              b                c      d               eeee]

我知道如何创建整数的动态二维数组及其工作正常:

int** arr;
int* temp;

arr = (int**)malloc(row*sizeof(int*));
temp = (int*)malloc(row * col * sizeof(int));
for (int i = 0; i < row; i++)
{
    arr[i] = temp + (i * col);
}
int count = 0;
//setting values in 2-D array
for (int i = 0; i < row; i++)
{
    for (int j = 0; j < col; j++)
    {
        arr[i][j] = count++;
    }
}

但是,当我尝试对字符串做同样的事情时,它会崩溃。

string** arr;
string* temp;

arr = (string**)malloc(row*sizeof(string*));
temp = (string*)malloc(row * col * sizeof(string));
for (int i = 0; i < row; i++)
{
    arr[i] = temp + (i * col);
}

//setting values in 2-D array
for (int i = 0; i < row; i++)
{
    for (int j = 0; j < col; j++)
    {
        arr[i][j].append("hello"); // CRASH here !!
    }
}

如何将每个单词存储在一个数组中??

这是我写的:

#include "stdafx.h"
#include <cstdlib>
#include <iostream>
#include <vector>
#include <map>
#include <fstream>
#include <string>
#include <algorithm>
#include <assert.h>     /* assert */
using namespace std;

vector<string> readFile(const string file, int& row, int& col)
{
    vector<string> buffer;

    ifstream read(file);
    string line;
    char * writable = NULL;

    if (read.is_open())
    {
        int temp_counter = 0;
        while (!read.eof())
        {
            std::getline(read, line);
            writable = new char[line.size() + 1];
            std::copy(line.begin(), line.end(), writable);
            writable[line.size()] = '\0'; // don't forget the terminating 0
            if (temp_counter == 0)//
            {
                row = std::stoi(line);
                ++temp_counter;
            }
            else if (temp_counter == 1)
            {
                col = std::stoi(line);
                ++temp_counter;
            }
            else
            {
                buffer.push_back(line);
            }       
        }
    }
    // don't forget to free the string after finished using it
    delete[] writable;
    return buffer;
}

void create2DDynamicArray(std::vector<string>&v, int row, int col)
{
    string** arr;
    string* temp;

    arr = (string**)malloc(row*sizeof(string*));
    temp = (string*)malloc(row * col * sizeof(string));
    for (int i = 0; i < row; i++)
    {
        arr[i] = temp + (i * col);
    }


    //setting values in 2-D array
    for (int i = 0; i < row; i++)
    {
        for (int j = 0; j < col; j++)
        {
            arr[i][j].append("hello");
        }
    }
}
int main()
{
    vector<string> myvector;
    int row=0;
    int col=0;

    myvector = readFile("D:\\input.txt", row, col);
    create2DDynamicArray(myvector, row, col);

    getchar();
    return 0;
}

txt 文件的样子:

4

5

aa bbb cc dddddddd eeee

aa bbbbbbbbbbbb cc dddddddddd eeee

aaaaaaaaaa bb cc d e

a b c d eeee

【问题讨论】:

  • 您将 int 更改为 char。您为字符串分配空间,而不是为 int。
  • 添加为每个字符串的空字符分配一个额外的条目。
  • 为什么不选择一个 C和C++?如果你打算使用 C,他们会说you shouldn't cast the result of malloc() in C。如果你打算使用 C++,为什么不使用new[] 而不是malloc()
  • “但是,当我尝试对字符串做同样的事情时,它会崩溃。”如何?为什么不发布Minimal, Complete, and Verifiable example
  • 如果你打算使用 C++,为什么还要关心这样的分配。

标签: c++ c c++11


【解决方案1】:

不要在 C++ 中使用malloc。它不运行字符串的构造函数,因此不为存储在其中的动态字符数组分配空间。请改用new[] 运算符或智能指针。

string **arr;
arr = new string*[height];
for (int i = 0; i < height; i++)
    arr[i] = new string[width];

c++ string 只是动态 char 数组的一种包装器,它必须被初始化(它应该有内存分配给它)。通过使用malloc,您不会调用构造函数,从而导致访问未分配的内存区域。

【讨论】:

    【解决方案2】:

    我建议避免碎片并使用真正的二维数组。

    在 C 中,从 C99 开始,您可以使用 VLA(可变长度数组):

    #include <stdio.h>
    #include <stdlib.h>
    
    int main(void)
    {
        int rows = 4, cols = 5;
        char *(*arr)[cols];
        int i, j;
    
        arr = malloc(sizeof(*arr) * rows);
        for (i = 0; i < rows; i++) {
            for (j = 0; j < cols; j++) {
                arr[i][j] = "hello"; /* For read only, to be writable use strdup */
            }
        }
        for (i = 0; i < rows; i++) {
            for (j = 0; j < cols; j++) {
                printf("%s\t", arr[i][j]);
            }
            printf("\n");
        }
        free(arr);
        return 0;
    }
    

    输出:

    hello   hello   hello   hello   hello   
    hello   hello   hello   hello   hello   
    hello   hello   hello   hello   hello   
    hello   hello   hello   hello   hello   
    

    arr[i][j].append("hello"); // CRASH here !!
    

    C 中没有方法,这不会编译,为什么要混合 C 和 C++?选择其中之一。

    【讨论】:

    • 即使 C99 不可用,只要 rows 和 cols 是编译时常量,此方法甚至适用于古老的 C 编译器或 C++ 编译器。我个人更喜欢使用 arr = malloc(sizeof(char*[rows][cols])); 样式,因为它使意图更清晰,它是自记录代码。
    • @Lundin 你确定吗? gcc -std=c89 : ISO C90 forbids variable length array ‘arr’
    • cols 被定义为enum {cols = 5};#define cols 5 时警告消失,但即使使用int cols = 5; 仍然存在const:相关问题:stackoverflow.com/q/436300/1606345
    • 是的,这就是我的意思,你必须让它成为一个编译时常量。不幸的是,C 不会将 const 变量视为编译时常量(但这可能在 C++ 中有效)。
    • @Lundin 啊,好的;)
    【解决方案3】:

    不要使用malloc,避免使用new/new[]并使用RAII容器:

    std::vector<std::vector<std::string>> readFile(const std::string& filename)
    {
        std::ifstream file(filename);
        int row;
        int col;
        file >> row >> col;
    
        std::vector<std::vector<std::string>> words(row, std::vector<std::string>(col));
    
        for (auto& rows : words) {
            for (auto& word : rows) {
                file >> word;
            }
        }
        return words;
    }
    

    【讨论】:

      【解决方案4】:

      向量也是动态数组,但跟踪指针的所有工作对用户隐藏。

      如果您决定改用向量,那么编写二维动态数组就像这样简单:

      #include <iostream>
      #include <vector>
      #include <string>
      #include <fstream>       
      using namespace std;
      
      
      int main () {
      
          cout<<"\nDynamic 2D Array.\n\n";
      
          // create string vector
          vector<string> vArray;
      
          // create one line string
          string line;
      
          // open file for reading
          ifstream fileToRead("d2d.txt");
          while (getline(fileToRead, line)){
      
              //  fuse (store) line from file in vector
              vArray.push_back(line);
          }
          fileToRead.close();
      
          // display results
          for (int i=0; i< vArray.size();i++){
              cout<<" [ "<< vArray[i] <<" ] \n";
          }
      
      cout<<"\nPress ANY key to close.\n\n";
      cin.ignore(); cin.get();
      return 0;
      } 
      

      【讨论】:

        【解决方案5】:

        如果您真的想使用分配有malloc 内存的二维数组,我的建议是从string ** 转换为string *** 类型,例如:

            ifstream f(your_file_name);
        
            string*** arr;
        
            arr = (string***)malloc(row*sizeof(string**));
        
            for (int i = 0; i < row; i++)
            {
                arr[i] = (string**)malloc(col * sizeof(string*));
            }
        
            //setting values in 2-D array
            for (int i = 0; i < row; i++)
            {
                for (int j = 0; j < col; j++)
                {
                    arr[i][j] = new string();
                    f >> *arr[i][j]; // or arr[i][j] -> append("hello");
                }
            }
        

        但如果真的是 C++ 项目,请考虑使用vector&lt;vector&lt;string&gt;&gt; 甚至使用new 而不是malloc,例如:

            ifstream f("tmp.txt");
        
            string** arr;
        
            arr = new string*[row];
        
            for (int i = 0; i < row; i++)
            {
                arr[i] = new string[col];
            }
        
            //reading 2-D array from file
            for (int i = 0; i < row; i++)
            {
                for (int j = 0; j < col; j++)
                {
                    f >> arr[i][j];
                }
            }
            // show file content
            for (int i = 0; i < row; i++)
            {
                for (int j = 0; j < col; j++)
                {
                    cout << arr[i][j] << " ";
                }
                cout << endl;
            }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2022-11-18
          • 1970-01-01
          • 2016-02-22
          • 1970-01-01
          • 1970-01-01
          • 2015-07-15
          • 1970-01-01
          相关资源
          最近更新 更多