I'm trying to implement a program which is able to compute a matrix-product.
GOAL: Input v or m and the program automatically computes dot-product, matrix-vector product or matrix product.
The program is working for vectors, and quadratic-matrices but for non-quadratic-matrices the program crashes with.
terminate called after throwing an instance of 'std::out_of_range'
what(): vector::_M_range_check: __n (which is 1) >= this->size() (which is 1)
I'm not sure if the function matrix_input() really is the issue or if my way to enter 2D-Vektors is wrong.
When I input m 2 1 1 2 m 1 2 2 1 the program crashes in the function matrix_input() because it outputs error-2, error-3 not anymore.
I have noticed that the program crashes because in the second matrix the last row doesn't exist or something similar.
#include <iostream>
#include <vector>
#include <cassert>
using namespace std;
//Checks if input is a matrix or vector
//PRE: Char v or m
//POST: Returns number of the char 1 or 2 or 0 as error
int m_or_v(char m_v) {
if(m_v=='v')
return 1;
else if(m_v=='m')
return 2;
assert("error");
return 0;
}
//Inputs a vector if input was 'v'
//PRE: Takes vector
//POST: Checks length of the vector, inputs values into the vector
void vector_input(vector<int> &vector_v) {
int row = 0;
cin >> row;
int cache = 0;
for(int i = 0;i<row;i++) {
cin >> cache;
vector_v.push_back(cache);
}
}
//Inputs a matrix if input was 'm'
//PRE: Takes matrix
//POST: Checks number row, col and inputs the values into the matrix
void matrix_input(vector<vector<int>> &matrix_m) {
int row = 0;
int col = 0;
int cache_m = 0;
cin >> row;
cin >> col;
for(int r = 0;r<row;r++) {
vector<int> empty = {};
cout << "error-1";
for(int c = 0;c<col;c++) {
cin >> cache_m;
empty.push_back(cache_m);
cout << "error-2";
}
//I believe the program crashes in at this point, because the last row doesn't exist.
matrix_m.push_back(empty);
}
cout << "error-3";
}
//Computes the dot product if the input were two vectors
void scalar_product(const vector<int> &vector_1,const vector<int> &vector_2) {
int value = 0;
if(vector_1.size()==vector_2.size()) {
for(unsigned long i = 0;i<vector_1.size();i++) {
value += (vector_1.at(i)*vector_2.at(i));
}
cout << "s" << endl;
cout << value;
}
else
cout << "error";
}
//Checks if dot product, matrix-vector product or matrix product
int mult_mode(int mode1, int mode2) {
if(mode1==1&&mode2==2) {
cout << "error";
return 0;
}
else if(mode1==1&&mode2==1)
return 1;
else if((mode1==2&&mode2==1)||(mode1==1&&mode2==2))
return 2;
else if(mode1==2&&mode2==2)
return 3;
else {
cout << "error";
return 0;
}
}
//Check if Matrix-Vektor Product is possible
bool mvp_valid(const vector<vector<int>> &matrix_1,
const vector<int> &vector_2) {
if(matrix_1.at(0).size()==vector_2.size())
return true;
return false;
}
//Computes Vector-Matrix product
void mvp_result(const vector<vector<int>> &matrix_1,
const vector<int> &vector_2, vector<int> &result) {
int cache = 0;
for(unsigned long row = 0;row<matrix_1.size();row++) {
for(unsigned long col = 0;col<vector_2.size();col++) {
cache += matrix_1.at(row).at(col)*vector_2.at(col);
}
result.push_back(cache);
cache = 0;
}
}
//Outputs a vector
void output_v(vector<int> &vec) {
cout << "v " << vec.size() << endl;
for(unsigned long i = 0;i<vec.size();i++) {
cout << vec.at(i) << " ";
}
}
//Check if Matrix x Matrix is valid
bool mxm_valid(
const vector<vector<int>> &matrix_1,
const vector<vector<int>> &matrix_2) {
if(matrix_1.at(0).size()==matrix_2.size())
return true;
return false;
}
//Computes the matrix-matrix product
void mxm_result(
const vector<vector<int>> &matrix_1,
const vector<vector<int>> &matrix_2,
vector<vector<int>> &result_m) {
int cache = 0;
vector<int> empty;
for(unsigned long row = 0;row<matrix_1.size();row++) {
result_m.push_back(empty);
for(unsigned long col = 0;col<matrix_2.at(row).size();col++) {
for(unsigned long row_col = 0;row_col<matrix_2.size();row_col++) {
cache+=matrix_1.at(row).at(row_col)*matrix_2.at(row_col).at(col);
}
result_m.at(row).push_back(cache);
cache = 0;
}
}
}
//Outputs a matrix
void output_m(const vector<vector<int>> &matx) {
for(unsigned long col = 0;col<matx.size();col++) {
for(unsigned long row = 0;row<matx.size();row++) {
cout << matx.at(col).at(row) << " ";
}
cout << endl;
}
}
//Outputs the size of the matrix
void size_m(const vector<vector<int>> &matx) {
cout<<"m "<<matx.size()<<" "<<matx.at(0).size()<<endl;
}
int main() {
char mode_c = ' ';
int mode1 = 0;
int mode2 = 0;
vector<int> vector_1;
vector<vector<int>> matrix_1;
vector<int> vector_2;
vector<vector<int>> matrix_2;
//Vector or Matrix Number 1
cin >> mode_c;
mode1 = m_or_v(mode_c);
if(mode1==1) {
vector_input(vector_1);
}
else if(mode1==2) {
matrix_input(matrix_1);
}
//Vector or Matrix Number 2
cin >> mode_c;
mode2 = m_or_v(mode_c);
if(mode2==1) {
vector_input(vector_2);
}
else if(mode2==2) {
cout << "error-10";
matrix_input(matrix_2);
cout << "error-11";
}
switch(mult_mode(mode1, mode2)) {
case 1:
scalar_product(vector_1,vector_2);
break;
case 2:
if(mvp_valid(matrix_1, vector_2)==true) {
vector<int> result;
mvp_result(matrix_1, vector_2, result);
output_v(result);
}
else
cout << "error";
break;
case 3:
if(mxm_valid(matrix_1, matrix_2)==true) {
vector<vector<int>> result_m;
mxm_result(matrix_1, matrix_2, result_m);
size_m(result_m);
output_m(result_m);
}
else
cout << "error";
break;
}
}
Related
I have created a program to take in float values until a non-number is entered. The program will then print the numbers entered like {n0,n1,...,}, as well as sum up the number entered and compute the average.
My problem is after n0 is printed out all the rest of the numbers being printed out are not matching the number entered.
Here is the program:
#include <iostream>
using namespace std;
class ManagedArray
{
float *elements;
int numberOfElements;
public:
ManagedArray(float *ele, int NOE)
: elements(ele), numberOfElements(NOE)
{}
ManagedArray()
{
elements = NULL, numberOfElements = 0; //default constructor
}
int Size();
float get(int index);
void add(float value);
~ManagedArray(); // Destructor
ManagedArray(ManagedArray & ma); // copy constructor
void print(ManagedArray ma);
};
float ManagedArray::get(int index) { return elements[index]; }
int ManagedArray::Size() { return numberOfElements; };
void ManagedArray::add(float value)
{
float * biggerArray = new float[numberOfElements + 1];
if (elements != NULL)
{
// copy the old elements into the biggerArray
for (int i = 0; i < numberOfElements; i++)
{
biggerArray[i] = elements[i];
}
// the old array is not needed anymore, we have a better copy
delete[] elements;
}
// point at the new array
elements = biggerArray;
numberOfElements = numberOfElements + 1;
// put the new number into the last element of the array
elements[numberOfElements - 1] = value;
}
ManagedArray::~ManagedArray() { delete[] elements; }
ManagedArray::ManagedArray(ManagedArray & ma)
{
elements = new float[10]; // put here to get the number of input here
for (int i = 0; i <10; i++) // put here to get the number of input here
{
elements[i] = ma.elements[i];
}
numberOfElements = ma.numberOfElements;
}
void ManagedArray::print(ManagedArray ma)
{
bool hasNumbers = ma.Size() > 0;
if (hasNumbers) {
// print the stored numbers
cout << "Entered numbers: " << endl;
cout << "{";
for (int i = 0; i < ma.Size(); ++i)
{
if (i > 0)
{
cout << ", ";
}
cout << ma.get(i);
}
cout << "}" << endl;
float sum = 0;
for (int i = 0; i < ma.Size(); ++i)
{
sum += ma.get(i);
}
cout << "total: " << sum << endl;
cout << "average: " << (sum / ma.Size()) << endl;
}
else {
cout << "no numbers entered." << endl;
}
}
int main()
{
ManagedArray mArray; // default constructor call for ManagedArray
float userInput;
bool addingNumbersToTheList;
cout << "Keep entering numbers. Enter a non-number to stop." << endl;
do
{
cin >> userInput;
addingNumbersToTheList = !std::cin.fail();
if (addingNumbersToTheList) {
mArray.add(userInput);
}
} while (addingNumbersToTheList);
ManagedArray copy(mArray);
// fix cin after intentionally breaking it above.
if (std::cin.fail())
{
std::cin.clear();
while (std::cin.get() != '\n');
}
copy.print(copy);
copy.print(copy);
cin.get();
return 0;
}
So for instance I enter 1 , 2 , 3 , a
the program would print out {1, -4.22017e+37, 2.89451e+31}
Could someone point out what I am doing wrong with this method?
EDIT: I have fixed the copy constructor. Can someone show me how I would replace
the number 10 with the total of numbers input? in:
elements = new float[10];
and
for (int i = 0; i <10; i++)
I needed to iterate through every possible number in the array with a for loop and an array.
elements = new float[ma.Size()];
for (int i = 0; i < ma.Size(); i++)
{
elements[i] = ma.elements[i];
}
numberOfElements = ma.numberOfElements;
I made a sudoku solver, but need to be able to take inputs in to set the puzzle before being solved. The input will be in a 1,2,,,,3,4 format where a space between 2 commas indicates a blank space (and obviously this will all be done row by row). I also have my code set up to use blank spots as 0s and would like to know how to read the input, parse each number into an int and also parse blanks as 0s.
As stated above, this is for C++ and is in Visual Studio Express 2013.
// ConsoleApplication1.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "cstdlib"
#include "stdio.h"
#include "iostream"
#include "sstream"
using namespace std;
//find the first empty slot on the puzzle
bool FindEmptyCell(int puzzle[9][9], int &row, int &colm);
//check if the inserted number is a legal move
bool isLegal(int puzzle[9][9], int row, int colm, int num);
//being solving through backtracking
bool solve(int puzzle[9][9])
{
int row, colm; //establish rows and columns
//check if there are any empty slots
if (!FindEmptyCell(puzzle, row, colm))
{
return true; //puzzle is assumed solved
}
else
{
//start backtracking with the number 1
for (int i = 1; i<10; i++)
{
if (isLegal(puzzle, row, colm, i))
{
puzzle[row][colm] = i;
if (solve(puzzle) == true)
{
return true; //if there is no problem with the first number, move on
}
else
{
puzzle[row][colm] = 0;
}
}
}
}
return false; //start recursion to try next number
}
//check if the move is legal in the 3x3 square, needs the row and column of the square
bool CheckSquare(int puzzle[9][9], int sqRow, int sqColm, int chkNum)
{
for (int row = 0; row < 3; row++)
{
for (int colm = 0; colm < 3; colm++)
{
if (puzzle[row + sqRow][colm + sqColm] == chkNum)
{
return true; //the number is there and the move is illegal
}
}
}
return false; //the number is not there and the move is assumed legal
}
//check if the move is legal in the row
bool CheckRow(int puzzle[9][9], int row, int chkNum)
{
for (int colm = 0; colm <9; colm++)
{
if (puzzle[row][colm] == chkNum)
{
return true; //the number is there and the move is illegal
}
}
return false; // the number is not there and the move is assumed legal
}
//check if the move is legal in the column
bool CheckColm(int puzzle[9][9], int colm, int chkNum)
{
for (int row = 0; row <9; row++)
{
if (puzzle[row][colm] == chkNum)
{
return true; //the number is there and the move is illegal
}
}
return false; // the number is not there and the move is assumed legal
}
//definition of finding empty slot method
bool FindEmptyCell(int puzzle[9][9], int &row, int &colm)
{
for (colm = 0; colm < 9; colm++)
{
for (row = 0; row < 9; row++)
{
if (puzzle[row][colm] == 0)
{
return true;
}
}
}
return false;
}
//definition of is legal method
bool isLegal(int p[9][9], int r, int c, int cN)
{
if (CheckRow(p, r, cN) == false)
{
if (CheckColm(p, c, cN) == false)
{
if (CheckSquare(p, r - r % 3, c - c % 3, cN) == false) //use % to find the beginning row/column of the square
{
return true;
}
else
{
return false;
}
}
else
{
return false;
}
}
else
{
return false;
}
}
int main()
{
int puzzle[9][9];
string input;
for (int i=1; i <10; i++)
{
for (int j=1;j <10; j++)
{
cout << "Please insert the number for ["<< i << "," << j << "] (0 for no number)" << endl;
getline(cin, input);
int value = atoi(input.c_str());
puzzle[i-1][j-1] = value;
//get puzzle into correct format
}
}
if (solve(puzzle) == true)
{
string s;
cout << "Solving the puzzle..." << endl;
//print the puzzle to the screen
for (int i = 0; i<9;i++)
{
for (int j = 0; j<9; j++)
{
cout << puzzle[i][j] << ",";
}
cout << endl;
}
cout << "Press any button to escape";
getline(cin, s);
}
else
{
cout << "Can not solve the puzzle" << endl;
}
return 0;
}
Not sure why you need the code but here it is. Everything works properly, it just doesnt take input in the correct format currently.
As your numbers are only of 1 digit, you can:
int puzzle[9][9] = {};
for (int i = 1; i < 10; ++i)
{
cout << "Please input row #" << i << ": ";
getline(cin, input);
int j = 0;
const char *ptr = input.c_str();
while (*ptr)
{
if (isspace(*ptr)) ; // do nothing
else if (*ptr == ',') ++j; // new column
else puzzle[i - 1][j] = *ptr - '0';
++ptr;
}
}
To parse empty spaces as zerors, you need:
Initialize your matrix to zeros int puzzle[9][9] = { };
read the input line by line (each line representing a whole row)
use function strtok() to split (separate) the values using delimeter `','
for each separated value, trim it (i.e. remove spaces). Then, Use function atoi to covert it as an integer
Notice that you should check for empty separated string if (strlen(str))
My code is below. The problem happens when I try and run the addArray() function. I am completely new to C++ so I have no idea what a segmentation fault means.
I also know that there is probably a better way to initialize and return the 2d arrays, but I am slowly figuring that out.
My main problem now is the segmentation fault. I am guessing that it has something to do with how I am accessing the variables?
#include <iostream>
#include <cstdlib>
#include <iostream>
#include <vector>
#include <iomanip>
#include <time.h>
#include <stdlib.h>
using namespace std;
int c, q, w, row, coll, quit, qq, opt;
int** arr1;
int** arr2;
int** ans;
//Method Prototypes
int menu();
inline int** getArray(int opt);
inline void printArray(int** arr, int height, int width);
void addArray();
void subtractArray();
void multiplyArrays();
void determArray();
void transposeArray();
void inverseArray();
//Prints out the menu for choosing which option to go with
int menu() {
cout << "Press 1 for Addition\n";
cout << "Press 2 for Subtraction\n";
cout << "Press 3 for Multiplication\n";
cout << "Press 4 for Determinant\n";
cout << "Press 5 for Transpose\n";
cout << "Press 6 for Inverse\n";
cout << "Press 0 to quit\n\n";
cin >> c;
return c;
}
//Main method
int main(void) {
cout << "C++ 2d Matrix Operations Menu\n";
c = menu();
while (c != 0) {
if (c == 1) {
addArray();
} else if (c == 2) {
subtractArray();
} else if (c == 3) {
void multiplyArrays();
} else if (c == 4) {
void determArray();
} else if (c == 5) {
void transposeArray();
} else if (c == 6) {
}
c = menu();
}
cout << "Press Enter to Quit. GOOD BYE";
cin >> quit;
return 0;
}
/*
Prints out the specified array.
It's arguments are the actual array and the height/weight
*/
inline void printArray(int** arr, int height, int width) {
for (int i = 0; i < height; ++i) {
for (int j = 0; j < width; ++j) {
std::cout << arr[i][j] << ' ';
}
std::cout << std::endl;
}
}
//Returns an array.
inline int** getArray(int opt) {
if (opt == 0) {
cout << "How many rows and columns should be in the array?\n";
cin >> q >> w;
} else {
q = 3;
w = 3;
}
int** ary = new int*[q];
for (int i = 0; i < q; ++i) {
ary[i] = new int[w];
}
for (row = 0; row < q; row++) {
for (coll = 0; coll < w; coll++) {
cout << "What should the value be for item" << row << "," << coll << "\n";
cin >> ary[row][coll];
}
}
return ary;
}
//Adds arrays
void addArray() {
arr1 = getArray(0);
int h1 = q;
int w1 = w;
arr2 = getArray(0);
int h2 = q;
int w2 = w;
if ((h1 != h2) || (w1 != w2)) {
cout << "Both arrays must be the same size.";
return;
}
for (row = 0; row < q; row++) {
for (coll = 0; coll < w; coll++) {
ans[row][coll] = arr1[row][coll] + arr2[row][coll];
}
}
printArray(ans, q, w);
}
//Subtracts Arrays
void subtractArray() {
arr1 = getArray(0);
int h1 = q;
int w1 = w;
arr2 = getArray(0);
int h2 = q;
int w2 = w;
if ((h1 != h2) || (w1 != w2)) {
cout << "Both arrays must be the same size.";
return;
}
for (row = 0; row < q; row++) {
for (coll = 0; coll < w; coll++) {
ans[row][coll] = arr2[row][coll] - arr1[row][coll];
}
}
printArray(ans, q, w);
}
//Calculate the determinate of an array.
void determArray() {
arr1 = getArray(1);
printArray(arr1, q, w);
//There must be a better/more efficient way to do this using loops.
int determinant = arr1[0][0]*((arr1[1][1] * arr1[2][2]) - (arr1[2][1] * arr1[1][2])) - arr1[0][1]*(arr1[1][0] * arr1[2][2] - arr1[2][0] * arr1[1][2]) + arr1[0][2]*(arr1[1][0] * arr1[2][1] - arr1[2][0] * arr1[1][1]);
printf("\nDeterminant of vector using method 1 is: %d\n", determinant);
}
//Transpose an array.
void transposeArray() {
cout << "IN TRANS";
arr1 = getArray(0);
printArray(arr1, 3, 3);
//Flip the values
for (row = 0; row < q; row++) {
for (coll = 0; coll < w; coll++) {
ans[row][coll] = arr1[coll][row];
}
}
cout << "----------" << endl << "The new vector looks like: \n";
printArray(ans, q, w);
}
/*
Multiply arrays. One option is to just multiply it by a number and the other is to multiply it by another array.
*/
void multiplyArrays() {
arr1 = getArray(0);
int h1 = q;
int w1 = w;
cout << "Do you wish to multiply the first vector by a number(Enter 1), or by a second vector(Enter 2)?";
cin >> qq;
int mu;
//First Option is to multiply it by a single number
if (qq == 1) {
cout << "What number do you wish to multiply the vector by?";
cin >> mu;
for (row = 0; row < q; row++) {
for (coll = 0; coll < w; coll++) {
ans[row][coll] = arr1[row][coll] * mu;
}
}
printArray(ans, h1, w1);
//Multiply two arrays
} else if (qq == 2) {
arr2 = getArray(0);
int h2 = q;
int w2 = w;
int n1 = h1;
int n2 = w2;
int nCommon = n1;
if (n2 == nCommon) {
cout << "Amount of columns for vector 1 must match amount of rows for vector 2";
return;
}
for (int i = 0; i < n1; i++) {
for (int j = 0; j < n2; j++) {
for (int k = 0; k < nCommon; k++) {
ans[i][j] += arr1[i][k] * arr2[k][j];
}
}
}
printArray(ans, n1, n2);
}
}
You never allocate memory for ans. Just like you need to allocate storage for the two input arrays before filling them, you need to allocate storage for the answer.
A segmentation fault is generated when you attempt to write to memory that you do not have access to. In this case, because the ans array was not initialized, it points to random memory. When you do ans[row][coll] = arr2[row][coll] - arr1[row][coll];, you get a segfault because ans[row][col] is pointing somewhere outside your program space.
The problem is that you have not allocated memory for the ans array, but you are writing to it in the following code:
for (row = 0; row < q; row++) {
for (coll = 0; coll < w; coll++) {
ans[row][coll] = arr2[row][coll] - arr1[row][coll];
}
}
This is why you have segmentation fault.
Try to add a block to allocate memory for ans at first.
Here is the code I have for a programing assignment I have. Im getting this error when I run the program
"Unhandled exception at at 0x772BC41F in STRUCT2.EXE: Microsoft C++ exception: std::out_of_range at memory location 0x0043ED04." If I understand this right, the error means my array has exceeded the allotted memory space. is that correct? and if this is correct, what am I doing wrong? My input file has less than 30 elements in it.
#include "stdafx.h"
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
#include <cmath>
#include <sstream>
#include <cctype>
using namespace std;
struct Element
{
string Name;
char eN1;
char eN2;
float Weight;
};
struct Formula
{
char Element1;
char ElementA;
int Atom;
};
void ELEMENTS(Element ElmAry[30]);
float Str2Float(string Weight);
void FORMULAS(Formula FormAry[30]);
float CalculateMoleculeWeight(Element ElmAry[30], Formula FormAry[30]);
int main()
{
ifstream inputFile1;
ifstream inputFile2;
ofstream outputFile;
inputFile1.open("Element.txt");
inputFile2.open("Formula.txt");
outputFile.open("Molecular Weight.txt");
Element ElmAry[30];
Formula FormAry[30];
char inputCh;
int i = 0;
string String1;
string mFor;
string ABRV;
int ElmDigit = 0;
float StringWeight = 0;
string Name;
string Weight;
int LENGTH = 0;
float MOLEWT;
if(!inputFile1)
{
cout << "Couldn't find the Element.txt file." << endl;
return 0;
}
if(!inputFile2)
{
cout << "Couldn't find the Formula.txt file." << endl;
return 0;
}
ELEMENTS(ElmAry);
while(inputFile1)
{
Name = String1.substr(0,2);
ElmAry[i].Name = Name;
Weight = String1.substr(3,10);
String1.clear();
StringWeight = Str2Float(Weight);
ElmAry[i].Weight = StringWeight;
i++;
}
i--;
FORMULAS(FormAry);
while (inputFile2)
{
getline(inputFile2,String1);
LENGTH = String1.length();
int j = 0;
int n = 0;
while( j < LENGTH)
{
int pos = 0;
pos = String1.find(')');
while(n < LENGTH)
{
inputCh = String1.at(n);
if(isalpha(inputCh) && isupper(inputCh))
{
FormAry[j].Element1 = String1.at(n);
n++;
inputCh = String1.at(n);
}
if(isalpha(inputCh) && islower(inputCh))
{
FormAry[j].ElementA = String1.at(n);
n++;
inputCh = String1.at(n);
}
if(ispunct(inputCh))
{
n++;
inputCh = String1.at(n);
ElmDigit = (inputCh-'0');
}
if(isdigit(inputCh))
{
FormAry[j].Atom = ElmDigit;
n++;
}
inputCh = String1.at(n);
j++;
if(iscntrl(inputCh))
{
n++;
inputCh = String1.at(n);
j++;
}
n++;
}
}
}
MOLEWT = CalculateMoleculeWeight(ElmAry, FormAry);
cout << "\t\t MOLECULAR WEIGHT CHART \t\t\n" << endl;
cout << "\n| FORMULA |\t " << "\t| ATOM.WT |" << endl;
cout << "_______________________________";
outputFile << "\t\t MOLECULAR WEIGHT CHART \t\t\n" << endl;
outputFile << "\n| FORMULA |\t " << "\t| ATOM.WT |" << endl;
outputFile << "_______________________________";
for (int a = 0; a < 30; a++)
{
cout << MOLEWT << endl;
outputFile << MOLEWT << endl;
}
inputFile1.close();
inputFile2.close();
outputFile.close();
cin.get();
cin.get();
return 0;
}
void ELEMENTS(Element ElmAry[30])
{
for(int i = 0; i < 30; i++)
{
ElmAry[i].Weight = 0;
}
}
void FORMULAS(Formula FormAry[30])
{
for(int x = 0; x < 30; x++)
{
for(int x = 0; x < 9; x++)
{
FormAry[x].Atom = 1;
}
}
}
float Str2Float (string x)
{
stringstream ss(x);
float StringWeight;
ss >> StringWeight;
return StringWeight;
}
float CalculateMoleculeWeight(Element ElmAry[30], Formula FormAry[30])
{
int i;
int j=0;
float MoleWT = 0;
float MoleSum = 0;
char e1;
char e2;
char f1;
char f2;
for(i = 0; i < 30; i++)
{
f1 = FormAry[j].Element1;
f2 = FormAry[j].ElementA;
e1 = ElmAry[i].eN1;
e2 = ElmAry[i].eN1;
if
(e1 == f1 && e2 == f2)
{
MoleWT = ElmAry[i].Weight * FormAry[j].Atom;
MoleSum = MoleSum + MoleWT;
j++;
}
}
return MoleSum;
}
when I get to
while(inputFile1)
{
Name = String1.substr(0,2);
ElmAry[i].Name = Name;
Weight = String1.substr(3,10);//invalid string position
String1.clear();
StringWeight = Str2Float(Weight);
ElmAry[i].Weight = StringWeight;
i++;
}
i--;
Weight = String1.substr(3,10); gives me an invalid string position
std::out_of_range is an exception you get when you attempt to access memory outside the space you've allocated (in an STL container). In this particular case, you are accessing areas of a std::string that has not been allocated:
Weight = String1.substr(3,10); // empty string or string.length() < 4 throws here
std::string::substr takes index parameters that must be within the bounds of the array encapsulated by std::string. If the string is only 2 characters long, and you attempt to get characters starting at the 4th position, you will see the std::out_of_range exception. You should check the length prior to doing this kind of operation.
Additionally, you are declaring your arrays:
Element ElmAry[30];
Formula FormAry[30];
But you are looping through an entire file (which potentially has more than 30 elements). Thus, when i >= 30, you are out of bounds (and behavior will be undefined).
You can fix that by using std::vector, which will allow the array to be dynamically sized, or another collection (e.g. std::list, std::deque).
i am trying to do simple sets intersection , it works correctly , but when output comes , it shows only memory address or garbage random value , help me ,i applied breakpoints , but it's not working . actually i am new in C++
#include<iostream>
using namespace std;
class set
{
private:
int size;
int *elem;
public:
set()
{
size = 0;
elem = NULL;
}
set(int s);
~set();
set(set &s);
set intersection(set A, int z);
void inputset();
void outputset();
};
set::set(int s)
{
size = s;
elem = new int[s];
}
void set::inputset()
{
int i;
cout << "Enter the set Element" << endl;
for(i = 0 ; i < size ; i++)
{
cin >> elem[i];
}
}
set set::intersection(set A, int z)
{
int i, j, k = 0;
set R(z);
for(i = 0; i < size; i++)
{
for(j = 0; j < A.size; j++)
{
if(elem[i] == A.elem[j])
{
R.elem[k] = A.elem[j];
k++;
break;
}
}
}
return R;
}
set::~set()
{
delete []elem;
}
set::set(set &s)
{
int i;
if(size > 0)
{
delete []elem;
}
size = s.size;
elem = new int[size];
for(i = 0; i < size; i++)
{
elem[i] = s.elem[i];
}
}
void set::outputset()
{
int i;
cout << "The elements of new set is : " << endl;
for(i = 0; i < size; i++)
{
cout << elem[i] << endl;
}
cout << endl;
}
int main()
{
int x, y, z;
char choice;
cout << "Enter sizeof set A" << endl;
cin >> x;
set S1(x);
S1.inputset();
S1.outputset();
cout << "Enter sizeof set B" << endl;
cin >> y;
set S2(y);
S2.inputset();
S2.outputset();
z = x + y;
set S3(z);
cout << "Enter I for intersection" << endl << "Enter U for union" << endl << "Enter D for difference" << endl;
cin >> choice;
switch(choice)
{
case'I':
S3 = S1.intersection(S2, z);
S3.outputset();
break;
default:
cout << "Invalid entry";
}
return 0;
}
There are several ways to check intersections between two sets, if your sets are in arrays, I'd suggest looping one of them and have a check if it's in between the other:
for (int i = 0; i < element1_size; i++) {
for (int u = 0; u < element2_size; u++) {
if (element1[i] == element2[u]) {
cout << "Intersection point : " << element1[i] << endl;
}
}
}
Your copy ctor should be set(const set &s); instead of set(set &s); What you have is a ctor that accepts a reference to set, which is not a copy ctor. So compiler generates default one for you and you have issue returning object by value from method intersection()
Also please fix your code indent, it is not easy to read it.
Also remove following lines from your "copy ctor":
if(size>0)
{
delete []elem;
}
You cannot delete that pointer, your object is not constructed yet.
How about using a map to keep track of the "intersected" elements in much more efficient way. Here is a snippet of what I have in mind:
std::map<int, int> m;
for(int i = 0; i < size; ++i)
m.insert( std::pair<int, int>(elem[i], 1) );
for(int i = 0; i < A.size; ++i)
if(m.count(A[i]) > 0)
R.elem[k++] = A[i]
This way you avoid the nested for-loops, and will be able to compute the intersection with logarithmic time complexity.