我正在尝试为恰好是指针的嵌套结构动态分配内存。我在下面编写了一些虚构的代码来尝试说明我的问题。
这两个结构位于两个单独的头文件中,代码也位于一个名称空间下。
Tiles.h
struct Tiles
{
int* m_noOfSections;
int* m_noOfTilesInSecs;
char* m_TileName;
};
// functions omitted
Flooring.h
struct Flooring
{
Tiles* m_Tiles;
int m_noOfTiles;
char* m_FlooringName;
};
void read(Tiles&);
我正在为 Flooring.h 设计一个函数定义,在该函数中,我必须动态分配Tiles
数组,该数组的大小是在此函数中由用户确定的输入。
我尝试使用以下代码,但遇到了问题:
Flooring.cpp
void read(Flooring&Flr)
{
Tiles* tiles;
tiles = new Tiles[Flr.m_noOfTiles];
for (int i = 0; i < Flr.m_noOfTiles; i++) {
cout << i + 1 << ": ";
read(tiles[i]);
}
}
注意:read(tiles[i]);
[声明:void read(Tiles&)
]函数将值分配给Tiles
的数据成员。我已经测试了Tiles
文件中的功能,它们按预期工作。因此,我没有包含这些代码。我认为问题出在我的 Flooring.cpp 实施文件中。
我的期望是,上述读取功能会将值分配给:
tiles[i].m_noOfSections
,tiles[i].m_noOfTilesinSecs
,tiles[i].m_tileName
问题之一是我没有机会输入tileName
,在运行代码时,它跳过了我通常会输入tileName
的部分。
输出如下:
Enter the number of sets of tiles: Enter number of sections: [user is able
to input value here, but not before when asked to enter the number of the set of tiles]
Tiles.cpp
void read(char* tileName)
{
cout << "Enter tile name: ";
read(tileName, 15, "error message") ;
}
带有三个参数的read
函数的函数定义可以在下面找到。此功能已在此分配中预定义。我也检查了该功能,但没有发现任何问题,但是无论是否有帮助,我都会将其发布。
void read(char* str, int len, const char* errorMessage)
{
bool ok;
do
{
ok = true;
cin.getline(str, len+1, '\n');
if (cin.fail()) {
cin.clear();
cin.ignore(1000, '\n');
ok = false;
}
}while(!ok && cout << errorMessage);
}
我希望能提供足够的信息,如果我的格式不正确,或者如果我的术语不适当,我深表歉意,对于各种编程我还是很陌生的。如果忘记了某些信息,请告诉我。
答案 0 :(得分:2)
我建议使用std::vector
和std::string
,通过它们可以自动管理元素的存储,从而可以避免手动分配内存,您可以专注于实现。
这意味着,请从以下几个方面入手:
#include <iostream>
#include <vector> // std::vector
#include <string> // std::string
struct Tiles
{
std::vector<int> m_noOfSections;
std::vector<int> m_noOfTilesInSecs;
std::string m_TileName;
};
struct Flooring
{
std::vector<Tiles> m_Tiles;
// int m_noOfTiles; // --> obsolete, as you can get the size by calling `m_Tiles.size()`
std::string m_FlooringName;
};
作为旁注,在Flooring
(也许也在Tiles
)中,您确实想将Tiles
的名称映射到一组{{1} }。根据需求查看其他数据结构,例如std::pair
,std::map
,std::multimap
,std::unordered_map
,std::unordered_multimap
标准库为这种情况提供了什么。
答案 1 :(得分:2)
新表达式不分配任何内容,仅在您提供这些值时对其进行值初始化,或者调用构造函数并将参数传递给它。
#include <iostream>
#include <string>
#include <vector>
#include <regex>
#include <sstream>
#include <iterator>
#include <algorithm>
std::istringstream csvFile{R"(animal1,hair,feathers,eggs,milk,airborne,aquatic,predator1,toothed,backbone,breathes,venomous,fins,legs,tail,domestic1,catsize,class_type,aardvark,1,0,0,1,0,0,1,1,1,1,0,0,4,0,0,1,1,antelope,1,0,0,1,0,0,0,1,1,1,0,0,4,1,0,1,1
animal2,hair,feathers,eggs,milk,airborne,aquatic,predator2,toothed,backbone,breathes,venomous,fins,legs,tail,domestic2,catsize,class_type,aardvark,1,0,0,1,0,0,1,1,1,1,0,0,4,0,0,1,1,antelope,1,0,0,1,0,0,0,1,1,1,0,0,4,1,0,1,1
animal3,hair,feathers,eggs,milk,airborne,aquatic,predator3,toothed,backbone,breathes,venomous,fins,legs,tail,domestic3,catsize,class_type,aardvark,1,0,0,1,0,0,1,1,1,1,0,0,4,0,0,1,1,antelope,1,0,0,1,0,0,0,1,1,1,0,0,4,1,0,1,1)"};
class LineAsVector { // Proxy for the input Iterator
public:
// Overload extractor. Read a complete line
friend std::istream& operator>>(std::istream& is, LineAsVector& lv) {
// Read a line
std::string line; lv.completeLine.clear();
std::getline(is, line);
// The delimiter
const std::regex re(",");
// Split values and copy into resulting vector
std::copy(std::sregex_token_iterator(line.begin(), line.end(), re, -1),
std::sregex_token_iterator(),
std::back_inserter(lv.completeLine));
return is;
}
// Cast the type 'CompleteLine' to std::string
operator std::vector<std::string>() const { return completeLine; }
protected:
// Temporary to hold the read vector
std::vector<std::string> completeLine{};
};
int main()
{
// Read the complete csv file and split it
// Please note: instead of the istringstream csvFile, you can of course use any other open file stream
std::vector<std::vector<std::string>> csv{ std::istream_iterator<LineAsVector>(csvFile), std::istream_iterator<LineAsVector>() };
// Go through all lines of the csv data
// And print the 0th, 7th, 15th value in each line
std::for_each(csv.begin(), csv.end(), [](std::vector<std::string> & vs) {
std::copy_if(vs.begin(), vs.end(), std::ostream_iterator<std::string>(std::cout, " "), [ui = -1](std::string & s) mutable {
++ui; return (ui == 0) || (ui == 7) || (ui == 15);
});
std::cout << "\n";
});
return 0;
}
创建一个tiles = new Tiles[Flr.m_noOfTiles];
类Flr.m_noOfTiles
的数组,其中包含垃圾非nullptr指针和值。下层内存未初始化。可以通过提供初始化程序列表来完成。
Tiles
您必须为每个指针分配内存。而且,当不需要它时,请按适当的顺序将其从大多数嵌套结构分配到较少嵌套的结构。
根据您需要的操作,这可能不是一件容易的事,并且会导致代码麻烦。这就是C ++具有构造函数和析构函数的原因。所以: