#include<iostream>
using namespace std;
class Text{
public:
~Text(){
delete data;
}
char* data{};
int mSize{};
void fill(char* stringInput) {
mSize = strlen(stringInput);
data = new char [mSize];
for (int i = 0; i < mSize; i++){
data[i] = stringInput[i];
}
}
};
class myString{
public:
explicit myString(int size){ // constructor
strAmount = size;
strings = new Text [size];
}
~myString(){ // destructor
delete[] strings;
}
void addString(char* input){
strings[filledAmount].fill(input);
filledAmount++;
}
void delString(int pos){
for ( int i = pos; i < filledAmount; i++){
swap(strings[i], strings[i+1]);
}
strings[filledAmount].data = nullptr;
strings[filledAmount].mSize = 0;
filledAmount--;
}
void eraseEverything(){
for ( int i = 0; i < filledAmount; i++){
strings[i].data = {};
strings[i].mSize = 0;
}
filledAmount = 0;
}
int maxString() const {
int index{};
for ( int i = 0 ; i < filledAmount; i++){
if (strings[i].mSize > strings[index].mSize){
index = i;
}
}
return index;
}
int charAmount(){
int counter{};
for(int i = 0 ; i < filledAmount; i++){
counter+=strings[i].mSize;
}
return counter;
}
double digitPercentage(){
int digitsAmount{};
for(int i = 0; i < filledAmount; i++){
for ( int j = 0; j < strings[i].mSize; j++){
if (isdigit(strings[i].data[j])){
digitsAmount++;
}
}
}
double digitPercent = (digitsAmount/(double)charAmount())*100;
return digitPercent;
}
int filledAmount{};
int strAmount{};
Text* strings;
};
void render_text(myString& obj) {
for (int k = 0; k < obj.filledAmount; k++) {
for (int i = 0; i < obj.strings[k].mSize; i++)
cout << obj.strings[k].data[i];
cout << endl;
}
cout << endl;
}
int main(){
myString a(5);
a.addString((char *) "zxc 1v1 forever shadow fiend");
a.addString((char *) "This is a string");
a.addString((char *) "12345");
a.addString((char *) "Hello");
a.addString((char *) "A1oha Dance");
render_text(a);
a.delString(1);
render_text(a);
int maxInd = a.maxString();
cout << "Max string :\n";
for (int i = 0; i < a.strings[maxInd].mSize; i++) {
cout << a.strings[maxInd].data[i];
}
cout << "\n\n";
}
Please help me find the crash point. I suppose it crashes in the destructor pole, but I still can't figure it out.
This is something like a self-written string class, the problem is that I can't find the place where the problems start.
I also have a thought that the destructor tries to delete too much memory from the heap so the compiler prevents it from doing that. Can I somehow change the size of the strings array?
I have fixed all your memory errors, with the help of address sanitizers
The main change here is:
Add copy constructors and copy assignment operators
Manually delete the last element in the function delString
Though that the code now works, it's not a true modern c++ style code. I highly recommend that your using std::string to replace your Text class. Use std::vector to replace the dynamic array. Then you will stay away from the pain of memory errors. The delString should be replaced with vector::erase,which is much neat than your hand write algorithm.
https://en.cppreference.com/w/cpp/string/basic_string
https://en.cppreference.com/w/cpp/container/vector
I strongly recommend rewriting the code with std::string and std::vector
#include <cstring>
#include <iostream>
using namespace std;
class Text {
public:
~Text() { delete[] data; }
char* data{};
int mSize{};
Text() = default;
Text(const Text& oth) {
mSize = oth.mSize;
data = new char[mSize];
std::copy(oth.data, oth.data + oth.mSize, data);
}
Text& operator=(const Text& oth) {
delete[] data;
mSize = oth.mSize;
data = new char[mSize];
std::copy(oth.data, oth.data + oth.mSize, data);
return *this;
}
void fill(char* stringInput) {
mSize = strlen(stringInput) + 1;
data = new char[mSize];
for (int i = 0; i < mSize; i++) {
data[i] = stringInput[i];
}
}
};
class myString {
public:
explicit myString(int size) { // constructor
strAmount = size;
strings = new Text[size];
}
myString(const myString& oth) {
strAmount = oth.strAmount;
strings = new Text[oth.strAmount];
for (size_t i = 0; i < strAmount; ++i) {
strings[i] = oth.strings[i];
}
}
myString& operator=(const myString& oth) {
delete[] strings;
strAmount = oth.strAmount;
strings = new Text[oth.strAmount];
for (size_t i = 0; i < strAmount; ++i) {
strings[i] = oth.strings[i];
}
return *this;
}
~myString() { // destructor
delete[] strings;
}
void addString(char* input) {
strings[filledAmount].fill(input);
filledAmount++;
}
void delString(int pos) {
for (int i = pos; i < filledAmount; i++) {
swap(strings[i], strings[i + 1]);
}
delete[] strings[filledAmount].data;
strings[filledAmount].data = nullptr;
strings[filledAmount].mSize = 0;
filledAmount--;
}
void eraseEverything() {
for (int i = 0; i < filledAmount; i++) {
strings[i].data = {};
strings[i].mSize = 0;
}
filledAmount = 0;
}
int maxString() const {
int index{};
for (int i = 0; i < filledAmount; i++) {
if (strings[i].mSize > strings[index].mSize) {
index = i;
}
}
return index;
}
int charAmount() {
int counter{};
for (int i = 0; i < filledAmount; i++) {
counter += strings[i].mSize;
}
return counter;
}
double digitPercentage() {
int digitsAmount{};
for (int i = 0; i < filledAmount; i++) {
for (int j = 0; j < strings[i].mSize; j++) {
if (isdigit(strings[i].data[j])) {
digitsAmount++;
}
}
}
double digitPercent = (digitsAmount / (double)charAmount()) * 100;
return digitPercent;
}
int filledAmount{};
int strAmount{};
Text* strings = nullptr;
};
void render_text(myString& obj) {
for (int k = 0; k < obj.filledAmount; k++) {
for (int i = 0; i < obj.strings[k].mSize; i++)
cout << obj.strings[k].data[i];
cout << endl;
}
cout << endl;
}
int main() {
myString a(6);
a.addString((char*)"zxc 1v1 forever shadow fiend");
a.addString((char*)"This is a string");
a.addString((char*)"12345");
a.addString((char*)"Hello");
a.addString((char*)"A1oha Dance");
render_text(a);
a.delString(1);
render_text(a);
int maxInd = a.maxString();
cout << "Max string :\n";
for (int i = 0; i < a.strings[maxInd].mSize; i++) {
cout << a.strings[maxInd].data[i];
}
cout << "\n\n";
return 0;
}
So I am trying to figure out how to create a function that Returns an Array of all integers that are in common with self and ary and returns an empty Array if there are no intersections. This is what I have so far:
IntArray* findIntersections(IntArray &ary) {
int length1 = ary.getLength(); // Getting the length of &ary.
int length2 = getLength([//Right here, there's something to do with "this" because I've created a mArray already and defined it, but I'm not sure how to re-call it here.]); // Getting the length of self.
int length4 = 0; // Because anarchy
if (length1 > length2){ // An if statement to match length4 with the longest array.
length4 = length2;
} else {
length4 = length1;
}
IntArray* newArray; // New IntArray on the heap.
newArray = new* int[length4];
int k = 0;
for (int j = 0; j < length1; j++){ // Two for loops getting the iterator on the same page.
for (int i = 0; i < length2; i++){
if (ary.get(j) == [//The this from earlier, whatever it is][i]){ // Checking to see if digits match each other.
newArray[k] = (ary[j]); // Writing the digit into the NewArray.
k++; // Adding one to the k count to progress the the iterator.
}
}
}
return newArray;
}
In the end, there I know there's gonna be three arrays. The one being passed in, the one being created and passing out, and then that this reference which I honestly don't even know what it is. I'm thinking it's an mArray I created earlier, but I'm not exactly sure. Any help on this would be absolutely fantastic!
Also, here's my .hpp file:
class IntArray {
private:
int *mArray;
int mSize;
public:
IntArray(int *array, int size);
int get(int index);
int getLength();
int indexOf(int value);
bool remove(int index);
IntArray* findIntersections(IntArray &ary);
bool isSubsequence(IntArray &ary);
~IntArray();
};
And my .cpp file:
#include "IntArray.hpp"
IntArray::IntArray(int *array, int size) {
int *newArray = new int [size];
for (int i = 0; i < size; i++){
newArray[i] = array[i];
}
}
int IntArray::get(int index) {
return mArray[index];
}
IntArray::~IntArray() {
delete[] mArray;
}
int IntArray::getLength() {
return mSize;
}
int getLength(int *array){
int length = (sizeof(array)/sizeof(array[0]));
return length;
}
int indexOf(int *array, int value){
int length = getLength(array);
for (int i = 0; i < length; i++){
if (value == array[i]){
return i;
}
}
return -1;
}
bool remove(int *array, int index){
int length = getLength(array);
if (0 <= index && index < length){
for (int i = index + 1; i < length; ++i){
array[i - 1] = array[i];
}
for (int i = 0; i < length; i++)
return true;
} else {
return false;
}
}
IntArray* findIntersections(IntArray &ary) {
int length1 = ary.getLength(); // Getting the length of &ary.
int length2 = getLength([//Right here, there's something to do with "this" because I've created a mArray already and defined it, but I'm not sure how to re-call it here.]); // Getting the length of self.
int length4 = 0; // Because anarchy
if (length1 > length2){ // An if statement to match length4 with the longest array.
length4 = length2;
} else {
length4 = length1;
}
IntArray* newArray; // New IntArray on the heap.
newArray = new* int[length4];
int k = 0;
for (int j = 0; j < length1; j++){ // Two for loops getting the iterator on the same page.
for (int i = 0; i < length2; i++){
if (ary.get(j) == [//The this from earlier, whatever it is][i]){ // Checking to see if digits match each other.
newArray[k] = (ary[j]); // Writing the digit into the NewArray.
k++; // Adding one to the k count to progress the the iterator.
}
}
}
return newArray;
}
bool isSubsequence(int *array) {
int length = getLength(array);
for (int i = 0; i < length - 1; i++) {
if (array[i] != array[i + 1])
return false;
}
return true;
}
Your implementation of findIntersection is not defined as a member function, you have defined it as a global function. The member function declaration named findIntersection is not defined. In short: you forgot IntArray:: before the function name
I am having trouble making a deep copy of a host_vector to device_vector. I think that I am having an issue modifying the value of an element stored in a device_vector. You can find a compilable version at the bottom but the code in question is the following (i put stars on the rows that trigger the segmentation fault):
thrust::host_vector<CharArr> hostToSort(size);
thrust::host_vector<long long> hostToSortRow(size);
for(int i =0; i < size; i++){
CharArr sortRow;
sortRow.value = arrayToSort[i];
sortRow.length = strlen(arrayToSort[i]);
hostToSort[i] = sortRow;
hostToSortRow[i] = arrayToSortRow[i];
}
thrust::device_vector<CharArr> deviceArrayToSort =hostToSort;
//thrust::copy(hostToSort.begin(),hostToSort.end(),deviceArrayToSort.begin());
// = ;// (arrayToSort,arrayToSort + size);
thrust::device_vector<long long> deviceArrayToSortRow = hostToSortRow;//(arrayToSortRow,arrayToSortRow + size);
// thrust::sort(deviceArrayToSort.begin(),deviceArrayToSort.end());
for(int i = 0; i < size; i++){
char * hostString = hostToSort[i].value;
int sizeString = strlen(hostString);
char * deviceString = 0;
CharArr * deviceCharArr = (&deviceArrayToSort[i]).get();
cudaMalloc((void **) deviceString,sizeString);
cudaMemcpy(deviceString,hostString,sizeString,cudaMemcpyHostToDevice);
**** deviceCharArr->length = sizeString;
**** deviceCharArr->value = deviceString;
}
What happens is that when we arrive at the actual assignment
deviceCharArr->value = deviceString
It throws a Segmentation Fault error. I am very new to CUDA and apologize if there is an obvious answer but I have not been able to find many examples of people allocating char * on devices.
Complete Compilable version is here
#include <thrust/device_vector.h>
#include <thrust/host_vector.h>
#include <thrust/reduce.h>
#include <thrust/device_vector.h>
#include <thrust/host_vector.h>
#include <thrust/sort.h>
#include <thrust/reduce.h>
typedef struct{
char * value;
int length;
} CharArr;
struct CharArrayCmp{
__host__ __device__
bool operator()(const CharArr & o1, const CharArr & o2) {
return this->compare(o1.value,o1.length,o2.value,o2.length);
}
__host__ __device__ bool compare (const char * src, int lenSrc, const char * dst, int lenDest)
{
int end;
if(lenSrc > lenDest){
end = lenDest;
}else{
end = lenSrc;
}
for(int i = 0; i < end; i++){
if(src[i] > dst[i]){
return false;
}else if(src[i] < dst[i]){
return true;
}
}
if(lenSrc >= lenDest){
return false;
}
return true;
}
};
void sortCharArrayHost(char ** arrayToSort, long long * arrayToSortRow,long long size){
std::cout <<"about to start LongIndex" <<std::endl;
thrust::host_vector<CharArr> hostToSort(size);
thrust::host_vector<long long> hostToSortRow(size);
for(int i =0; i < size; i++){
CharArr sortRow;
sortRow.value = arrayToSort[i];
sortRow.length = strlen(arrayToSort[i]);
hostToSort[i] = sortRow;
hostToSortRow[i] = arrayToSortRow[i];
}
/*thrust::device_vector<CharArr> deviceArrayToSort =hostToSort;
//thrust::copy(hostToSort.begin(),hostToSort.end(),deviceArrayToSort.begin());
// = ;// (arrayToSort,arrayToSort + size);
thrust::device_vector<long long> deviceArrayToSortRow = hostToSortRow;//(arrayToSortRow,arrayToSortRow + size);
// thrust::sort(deviceArrayToSort.begin(),deviceArrayToSort.end());
for(int i = 0; i < size; i++){
char * deviceString = 0;
char * hostString = hostToSort[i].value;
int size = strlen(hostString)*sizeof(char);
int cudaStatus;
CharArr * deviceCharArr = (&deviceArrayToSort[i]).get();
cudaStatus = cudaMalloc((void **) deviceString,size);
cudaStatus = cudaMemcpy(deviceString,hostString,size,cudaMemcpyHostToDevice);
(&deviceArrayToSort[i]).get()->value = "";
}
*/
// thrust::sort_by_key(deviceArrayToSort.begin(),deviceArrayToSort.end(),deviceArrayToSortRow.begin(),CharArrayCmp());
thrust::sort_by_key(hostToSort.begin(),hostToSort.end(),hostToSortRow.begin(),CharArrayCmp());
//copy the contents back into our original array to sort now sorted
// hostToSort = deviceArrayToSort;
for(int i =0; i < size; i++){
arrayToSort[i] = hostToSort[i].value;
}
// thrust::copy(deviceArrayToSortRow.begin(),deviceArrayToSortRow.end(),arrayToSortRow);
thrust::copy(hostToSortRow.begin(),hostToSortRow.end(),arrayToSortRow);
}
void sortCharArrayDevice(char ** arrayToSort, long long * arrayToSortRow,long long size){
std::cout <<"about to start LongIndex" <<std::endl;
thrust::host_vector<CharArr> hostToSort(size);
thrust::host_vector<long long> hostToSortRow(size);
for(int i =0; i < size; i++){
CharArr sortRow;
sortRow.value = arrayToSort[i];
sortRow.length = strlen(arrayToSort[i]);
hostToSort[i] = sortRow;
hostToSortRow[i] = arrayToSortRow[i];
}
thrust::device_vector<CharArr> deviceArrayToSort =hostToSort;
//thrust::copy(hostToSort.begin(),hostToSort.end(),deviceArrayToSort.begin());
// = ;// (arrayToSort,arrayToSort + size);
thrust::device_vector<long long> deviceArrayToSortRow = hostToSortRow;//(arrayToSortRow,arrayToSortRow + size);
// thrust::sort(deviceArrayToSort.begin(),deviceArrayToSort.end());
for(int i = 0; i < size; i++){
char * hostString = hostToSort[i].value;
int sizeString = strlen(hostString);
char * deviceString = 0;
CharArr * deviceCharArr = (&deviceArrayToSort[i]).get();
cudaMalloc((void **) deviceString,sizeString);
cudaMemcpy(deviceString,hostString,sizeString,cudaMemcpyHostToDevice);
deviceCharArr->length = sizeString;
deviceCharArr->value = deviceString;
}
thrust::sort_by_key(deviceArrayToSort.begin(),deviceArrayToSort.end(),deviceArrayToSortRow.begin(),CharArrayCmp());
//copy the contents back into our original array to sort now sorted
for(int i =0; i < size; i++){
arrayToSort[i] = (&deviceArrayToSort[i]).get()->value;
}
thrust::copy(deviceArrayToSortRow.begin(),deviceArrayToSortRow.end(),arrayToSortRow);
}
int main()
{
char ** charArr = new char*[10];
charArr[0] = "zyxw";
charArr[1] = "abcd";
charArr[2] = "defg";
charArr[3] = "werd";
charArr[4] = "aasd";
charArr[5] = "zwedew";
charArr[6] = "asde";
charArr[7] = "rurt";
charArr[8] = "ntddwe";
charArr[9] = "erbfde";
long long * rows = new long long[10];
for(int i = 0; i < 10;i++ ){
rows[i] = i;
}
sortCharArrayHost(charArr,rows,10);
for(int i = 0; i < 10; i++){
std::cout<<"Row is "<<rows[i]<<" String is "<<charArr[i]<<std::endl;
}
charArr[0] = "zyxw";
charArr[1] = "abcd";
charArr[2] = "defg";
charArr[3] = "werd";
charArr[4] = "aasd";
charArr[5] = "zwedew";
charArr[6] = "asde";
charArr[7] = "rurt";
charArr[8] = "ntddwe";
charArr[9] = "erbfde";
for(int i = 0; i < 10;i++ ){
rows[i] = i;
}
sortCharArrayDevice(charArr,rows,10);
for(int i = 0; i < 10; i++){
std::cout<<"Row is "<<rows[i]<<" String is "<<charArr[i]<<std::endl;
}
}
As JackOLantern has already pointed out, this is not acceptable:
// this creates an allocation on the device
thrust::device_vector<CharArr> deviceArrayToSort =hostToSort;
// this takes the (device) address an element and assigns it to a pointer variable
CharArr * deviceCharArr = (&deviceArrayToSort[i]).get();
// this then dereferences a device pointer in host code which is illegal
deviceCharArr->length = sizeString;
In CUDA you are not allowed to dereference a device pointer in host code or vice-versa.
It seems you have the following data sets:
The strings to be sorted
An array of string "handles" consisting of CharArr objects each containing pointer to start of string and length
An array of string indices (i.e. 0, 1, 2, ...)
You want to sort 2, and 3 above, based on 1. Thrust "likes" to have everything in one or 2 vectors, if possible. Let's try the following:
concatenate all strings together into a single char vector.
mark the start index of each string in another int vector. The difference in successive start indices will constitute the length of each string. We'll combine the start and the length of each string into a thrust::tuple for use in the comparator, by using a zip_iterator
sort the "tuple array" (i.e. sort index and length at the same time) using the desired comparison functor. Any necessary rearrangement of other data can be accomplished using the reordered index vector.
If you want a re-ordered string index also (i.e. 0, 1, 2, ...) you can create that vector easily enough and add it as a third element to the tuple to be sorted.
Note that the above approach entirely avoids the use of pointers, which as you've seen can be troublesome to manage between host and device copies of the same data.
Here's a fully worked example:
$ cat t439.cu
#include <thrust/device_vector.h>
#include <thrust/host_vector.h>
#include <thrust/sort.h>
#include <thrust/copy.h>
#define NUM_STRINGS 10
struct stringCmp{
const char * strings;
stringCmp(char * _strings) : strings(_strings) {}
template<typename myTuple>
__host__ __device__
bool operator()(const myTuple & o1, const myTuple & o2) {
int idxSrc = thrust::get<0>(o1);
int lenSrc = thrust::get<1>(o1);
int idxDst = thrust::get<0>(o2);
int lenDst = thrust::get<1>(o2);
int end;
if(lenSrc > lenDst){
end = lenDst;
}else{
end = lenSrc;
}
for(int i = 0; i < end; i++){
if(strings[idxSrc+i] > strings[idxDst+i]){
return false;
}else if(strings[idxSrc+i] < strings[idxDst+i]){
return true;
}
}
if(lenSrc >= lenDst){
return false;
}
return true;
}
};
void sortCharArrayDevice(char ** arr, int *rows, int num_str){
thrust::host_vector<char> h_strings;
thrust::host_vector<int> h_st_idx(num_str);
thrust::host_vector<int> h_len(num_str);
thrust::host_vector<int> h_rows(num_str);
// concatenate strings
// assume no zero length strings
h_st_idx[0] = 0;
for (int i = 0; i < num_str; i++){
int sidx = 0;
while (arr[i][sidx] != '\0'){
h_strings.push_back(arr[i][sidx]);
sidx++;}
h_len[i] = sidx;
if (i < num_str-1) h_st_idx[i+1] = h_st_idx[i] + sidx;
h_rows[i] = rows[i];
}
// copy data to device
thrust::device_vector<char> d_strings = h_strings;
thrust::device_vector<int> d_st_idx = h_st_idx;
thrust::device_vector<int> d_len = h_len;
thrust::device_vector<int> d_rows = h_rows;
// sort on device
thrust::sort(thrust::make_zip_iterator(thrust::make_tuple(d_st_idx.begin(), d_len.begin(), d_rows.begin())), thrust::make_zip_iterator(thrust::make_tuple(d_st_idx.end(), d_len.end(), d_rows.end())), stringCmp(thrust::raw_pointer_cast(d_strings.data())));
thrust::copy(d_rows.begin(), d_rows.end(), rows);
}
int main()
{
char ** charArr = new char*[NUM_STRINGS];
charArr[0] = "zyxw";
charArr[1] = "abcd";
charArr[2] = "defg";
charArr[3] = "werd";
charArr[4] = "aasd";
charArr[5] = "zwedew";
charArr[6] = "asde";
charArr[7] = "rurt";
charArr[8] = "ntddwe";
charArr[9] = "erbfde";
int * rows = new int[NUM_STRINGS];
for(int i = 0; i < NUM_STRINGS;i++ ){
rows[i] = i;
}
sortCharArrayDevice(charArr,rows,NUM_STRINGS);
for(int i = 0; i < NUM_STRINGS; i++){
std::cout<<"Row is "<<rows[i]<<" String is "<<charArr[rows[i]]<<std::endl;
}
}
$ nvcc -arch=sm_20 -o t439 t439.cu
$ ./t439
Row is 4 String is aasd
Row is 1 String is abcd
Row is 6 String is asde
Row is 2 String is defg
Row is 9 String is erbfde
Row is 8 String is ntddwe
Row is 7 String is rurt
Row is 3 String is werd
Row is 5 String is zwedew
Row is 0 String is zyxw
$
When my input looks like this:
11
Harry Kate Fred Carol
My adjacency matrix should put Harry at [7][7], Kate at [7][10], Fred at [7][5], and Carol at [7][2]. However, Carol & Kate get inserted at other locations within the adj. matrix as well. I am guessing this has something to do with stack and heap memory, but I am not sure how to find the bug. Using cout statements, there doesn't appear to be any issues.
Code below
#include <iostream>
#include <string>
#include <stdlib.h>
#include <iostream>
#include <sstream>
using namespace std;
class Element {
public:
string name;
int weight;
string color;
//default constructor
Element(void) {
name = "";
weight = 0;
color = "white";
}
//parameterized constructor
Element(string first) {
name = first;
weight = 0;
color = "white";
}
void setBlack() {
color = "black";
}
};
class AdjMatrix {
public:
int size;
Element ***adj_matrix;
AdjMatrix(void) {
size = 0;
adj_matrix = NULL;
}
AdjMatrix(int n) {
size = n; //sets the size to n
adj_matrix = new Element **[size];
for (int i = 0; i < size; i++) {
adj_matrix[i] = new Element *[i];
}
}
//Destructor class
~AdjMatrix(void) {
delete adj_matrix;
adj_matrix = NULL;
}
//initialize the array with empty elements
void initialize_matrix() {
Element *add_element = new Element("");
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++)
adj_matrix[i][j] = add_element;
}
}
};
int convertToASCII(string letter)
{
int x = letter.at(0);
int index = x - 65;
return index;
};
int main(int argc, char *argv[]) {
string table_size;
cout<<"";
getline(cin,table_size);
int size = atoi(table_size.c_str());
AdjMatrix *myGraph = new AdjMatrix(size);
myGraph->initialize_matrix();
string line;
getline(cin, line);
while (getline(cin,line))
{
if (line.empty())
break;
else {
int x = convertToASCII(line);
stringstream linestream(line);
string temp;
while (linestream >> temp) {
int z = convertToASCII(temp);
myGraph->adj_matrix[x][z] = new Element(temp);
}
}
}
//Print graph
for (int i = 0; i < myGraph->size; i++) {
for (int j = 0; j < myGraph->size; j++)
cout<<"["<<i<<"]["<<j<<"]: "<<myGraph->adj_matrix[i][j]->name<<endl;
}
return 0;
}
Your program has following problem which should be corrected.
//default constructor
Element(void)
Constructor should be defined as
//default constructor
Element()
You should start using the std::vector for your 2D array. This would eliminate the manual memory management. We should avoid to use raw pointer in modern c++. Please refer the following SO post which describes how to use vector for 2D array.
two dimensional array using vector in cpp
In your AdjMatrix(int) ctor, you are constructing your triangular matrix (if that's what you're going for) incorrectly. Try this:
AdjMatrix(int n) {
size = n; //sets the size to n
adj_matrix = new Element **[size];
for (int i = 0; i < size; i++) {
adj_matrix[i] = new Element *[i + 1]; // Or size for a square matrix
}
}
I need to read a txt file and store it into a matrix (we suppose that it'a a 2x2 matrix). I have a problem with the code below (I semplified it to be more cleat):
#include<stdexcept>
#include<string>
#include<fstream>
using namespace std;
class A{
private:
int **m;
void allocate_mem(int ***ptr){
*ptr = new int *[2];
(*ptr)[0] = new int[2*2];
for(unsigned i = 1; i < 2; i++)
(*ptr)[i] = (*ptr)[0] + i*2;
}
void read_file(string file_input){
ifstream fin(file_input.c_str());
allocate_mem(&m);
char a;
for(unsigned i = 0; i < 2; i++) {
for (unsigned j = 0; j < 2; j++) {
a = fin.get();
if(a=="X"){
//ISO C++ forbids comparison between pointer and integer [-fpermissive]
m[i][j] = 1;
}else{
m[i][j] = 0;
}
}
}
fin.close();
}
public:
A(){
throw logic_error("Error!");
}
A(string file_name){
read_file(file_name);
}
~A(){
delete[] m[0];
delete[] m;
}
};
input.txt
XX
X
I want to store a 2x2 matrix whose elemets are:
11
01
The solution is simple: Write C++ instead of C
Use standard containers instead of manual memory management.
Also, if you know the size of the data at compile-time, why do you use dynamic memory?
int m[2][2];
void read_file(const std::string& file_input) {
ifstream fin(file_input.c_str());
char a;
if( !fin ) throw;
for (std::size_t i = 0; i < 2; i++) {
for (std::size_t j = 0; j < 2; j++) {
a = fin.get();
if (a == 'X') { // '' is for characters, "" for strings. Thats why the compiler
m[i][j] = 1;// warns you (You are comparing the char[], which is decayed to
} else { // char*, with the integer value of the char variable)
m[i][j] = 0;
}
}
}
//Close not needed (RAII)
}