Here I am using Data Structure Queues to change cards places using strings. User picks the top card than put it at last of the deck. The problem is that I need to return updated string to main. What it is returning is junk Values. I also tried to copy the string array and than returning that arraybut didn't work. Can anyone help?
#include<iostream>
#include<string>
using namespace std;
string CommunityChest(string Cards[]){
struct Que{
string cards[6];
int front =0;
int back=-1;
}ComQ;
string temp;
for(int i=0; i<5;i++)
{//Enqueue(Cards)
ComQ.back++;
if(ComQ.back<=5)
{
ComQ.cards[ComQ.back]=Cards[i];
}
else{
cout<<"Overflow";
}
}
//Display
for(int i=ComQ.front; i<=ComQ.back; i++)
{
cout<<ComQ.cards[i]<<endl;
}
//Del()
if(ComQ.front>=0)
{
temp=ComQ.cards[ComQ.front];
ComQ.front++;
}
cout<<endl<<"Pick the top Card"<<endl;
cout<<temp<<endl;
//EnQ the picked card
ComQ.back++;
if(ComQ.back<=5)
{
ComQ.cards[ComQ.back]=temp;
}
else{
cout<<"Overflow";
}
cout<<endl<<"After Inserting top card:"<<endl;
//Display
string newQ1[5];
for (int i=ComQ.front; i<=ComQ.back; i++) //Making an alternate array to copy Comq.cards array data
{
newQ1[i]=ComQ.cards[i];
}
for(int i=0; i<5; i++)
{
return newQ1[i]; //trying to return string array
//cout<< newQ1<<endl;
}
}
int main(){
string cards[5]{ "1 Advance ........",
"2. It is your ...........",
"3. You have won .............",//Cards as strings
"4. From sale of..............",
"5. Pay Hospital............"};
string newQ1=CommunityChest(cards);
for(int i=0; i<5; i++)
cout << newQ1[i] << endl;
return 0;
}
There are some issues with this code as mentioned in the comments, you are trying to do a return in a loop, this may look okay but it's wrong since a return can get you out of the function. But it seems like you want to return an array of strings.
A fix for this function would be like this:
#include <iostream>
std::string* CommunityChest(std::string Cards[]) {
struct Que {
std::string cards[6];
int front = 0;
int back = -1;
} ComQ;
std::string temp;
for (int i = 0; i < 5; i++) { // Enqueue(Cards)
ComQ.back++;
if (ComQ.back <= 5) {
ComQ.cards[ComQ.back] = Cards[i];
}
else {
std::cout << "Overflow";
}
}
// Display
for (int i = ComQ.front; i <= ComQ.back; i++) {
std::cout << ComQ.cards[i] << std::endl;
}
// Del()
if (ComQ.front >= 0) {
temp = ComQ.cards[ComQ.front];
ComQ.front++;
}
std::cout << std::endl
<< "Pick the top Card" << std::endl;
std::cout << temp << std::endl;
// EnQ the picked card
ComQ.back++;
if (ComQ.back <= 5) {
ComQ.cards[ComQ.back] = temp;
}
else {
std::cout << "Overflow";
}
std::cout << std::endl
<< "After Inserting top card:" << std::endl;
// Display
// Creating a dynamic array to store the values
std::string* newQ1 = new std::string[5];
for (int i = ComQ.front, j = 0; i <= ComQ.back && j < 5; i++, j++) {// Making an alternate array to copy Comq.cards array data
newQ1[j] = ComQ.cards[i];
}
return newQ1; // Returning the dynamic array
}
int main()
{
std::string cards[5]{
"1 Advance ........",
"2. It is your ...........",
"3. You have won .............", // Cards as strings
"4. From sale of..............",
"5. Pay Hospital............"
};
std::string* newQ1 = CommunityChest(cards);
for(int i = 0; i < 5; i++) {
std::cout << newQ1[i] << std::endl;
}
delete[] newQ1; // Deleting the array
return 0;
}
The output will be:
1 Advance ........
2. It is your ...........
3. You have won .............
4. From sale of..............
5. Pay Hospital............
Pick the top Card
1 Advance ........
After Inserting top card:
2. It is your ...........
3. You have won .............
4. From sale of..............
5. Pay Hospital............
1 Advance ........
In this fix, I'm returning a dynamically allocated array of strings because a static array will be destroyed once the scope ends, it would be better sometimes to use other ways to allocate memory such as std::unique_ptr<> or std::shared_ptr<>, but I'd suggest you learn how to do it yourself first then use those when needed.
EDIT:
You can also return an std::array<>, I suggest you to read about it as C-Style arrays cannot be returned in you way that you tried and can't be returned without using dynamic allocation, so an std::array<> can be a good replacement over std::string* in this case
Related
I've encountered a problem while trying to create a code which converts decimal numbers to binary, using functions. At first I created the code using only main function and it worked fine, but decided to modify it to use function. I believe code is written right, however when I try to cout my answer I get a big number like 115120160758866453687091316369641637416.
This is the code
#include <iostream>
#include <math.h>
using namespace std;
int* unsigned_dec(int dec_M) { //function for converting absolute part of numbers
int bin[8] = { 0,0,0,0,0,0,0,0 };
int ind = 7;
int arr_ind = 0;
for (int base = (int)abs(dec_M); base > 0; base = base / 2) {
if (base % 2 == 0) {
bin[arr_ind] = 0;
ind--;
}
else {
bin[arr_ind] = 1;
ind--;
}
arr_ind++;
}
return bin;
}
int main() {// main function
int dec_N;
cin >> dec_N;
int* bin_main = unsigned_dec(dec_N); //we are not sure if we are assigning the returned value of function to array in correct
for (int i = 0; i <= 7; i++) {
cout << bin_main[i];
}
cout << endl;
return 0;
}
then I tried to change the cout code to
cout << bin_main[0] << bin_main[1] << bin_main[2] << bin_main[3] << bin_main[4] << bin_main[5] << bin_main[6] << bin_main[7] << endl;
And this worked fine.
Then I wrote the same 2nd variant of cout in other way
cout << bin_main[0];
cout << bin_main[1];
cout << bin_main[2];
cout << bin_main[3];
cout << bin_main[4];
cout << bin_main[5];
cout << bin_main[6];
cout << bin_main[7];
cout << endl;
and my code started to cout the same strange number. I think that all 3 ways of couts are almost the same (especially 2 and 3), but don't understand what makes it not to work.
int bin[8] = { 0,0,0,0,0,0,0,0 };
is allocated on stack. You should either allocate bin on heap
auto bin = std::unique_ptr<int, std::default_deleter<int[]>>(new int[8]);
or even better, use std::vector
you are returning pointer to local array of intbin[] in unsigned_dec. This array on stack of function unsigned_dec will get invalidated once another function from main gets called i.e cout operator .
As others have already mentioned: A function should never return a pointer to a local variable. Local variable is not valid when the function returns.
A better way is to use a vector and just make the function return the vector.
Something like:
#include <iostream>
#include <math.h>
using namespace std;
//function for converting absolute part of numbers
vector<int> unsigned_dec(int dec_M) {
vector<int> bin; // Create a vector
bin.resize(8, 0); // Fill it with 8 elements initialized to zero
int arr_ind = 0;
// Note: added check for arr_ind being valid
for (int base = (int)abs(dec_M); base > 0 && arr_ind < 8; base = base / 2) {
if (base % 2 == 0) {
bin[arr_ind] = 0;
}
else {
bin[arr_ind] = 1;
}
arr_ind++;
}
return bin; // Return the vector
}
int main() {
int dec_N;
cin >> dec_N;
vector<int> bin_main = unsigned_dec(dec_N);
for (int i = 0; i < bin_main.size(); i++) {
cout << bin_main[i];
}
cout << endl;
return 0;
}
The issue I'm having is I'm trying to return an array from the function EnterNumber() and display it in the main, but its coming out fairly crazy. I went through with the debugger and the numbers are correct in the debugger, just not correct in once it prints to the screen.
I realize there's a global const int in my program, but it was sanctioned by my professor who wanted us to do it just this time for this program.
Just looking for a nudge on why its printing incorrectly. Thank you.
#include <iostream>
using namespace std;
void EnterNumber(int Number[]);
const int SIZE=20;
int main()
{
int LargeNumber1[SIZE];
int LargeNumber2[SIZE];
for (int Counter1=0; Counter1<=19; ++Counter1)//zeros arrays out
{
LargeNumber1[Counter1]=0;
LargeNumber2[Counter1]=0;
}
EnterNumber(LargeNumber1);
for (int Counter2=0; Counter2<=19; ++Counter2)//display array 1 contents
{
cout << LargeNumber1[SIZE];
}
cout << "\n\n";
EnterNumber(LargeNumber2);
for (int Counter2=0; Counter2<=19; ++Counter2)//display array 2 contents
{
cout << LargeNumber2[SIZE];
}
}
void EnterNumber(int Number[])
{
int TemporaryArray[SIZE];
int PlaceCounter;
char Storage;
PlaceCounter=0;
for (int Counter1=0; Counter1<=19; ++Counter1)//zeros arrays out
{
TemporaryArray[Counter1]=0;
Number[Counter1]=0;
}
cout << "Please enter a large number --> ";
cin.get(Storage);
while (Storage!='\n' && PlaceCounter<SIZE)//puts number in temp array - left aligned
{
TemporaryArray[PlaceCounter]=(Storage-'0');
++PlaceCounter;
cin.get(Storage);
}
--PlaceCounter;//decrement one to get it to work properly with element style counting, else, extra zero at end
for (int A=SIZE-1; PlaceCounter>=0; A--, PlaceCounter--)//transfers old array into new array, right aligned
{
Number[A]=TemporaryArray[PlaceCounter];
}
cout << "\n";
}
This:
for (int Counter2=0; Counter2<=19; ++Counter2)
{
cout << LargeNumber1[SIZE];
}
should be this:
for (int Counter2=0; Counter2<SIZE; ++Counter2)
{
cout << LargeNumber1[Counter2];
}
You were repeatedly printing a number that was just beyond the end of the array.
I have a file that contains a directed graph. Graph vertices are labeled from 1 to N with N close to 800.000 (thousands). My cointainers are:
vector<long> isExplored;
vector<long> f;
vector<vector<long>> matrix;
vector<vector<long>> matrixInverse;
My file function to read the file and set the vectors is(vector[0] is always zero, that is the containers have size n+1):
void InputClass::readFile() {
ifstream inputFile;
inputFile.open(fileName);
string line;
string word;
int vertexNumber = 0;
while(getline(inputFile, line)) {
istringstream inputStream(line);
inputStream >> word;
if(vertexNumber != stoi(word)) {
vertexNumber = stoi(word);
matrix.resize(vertexNumber + 1);
}
while(inputStream >> word) {
if(matrix[vertexNumber].size() == 0) {
matrix[vertexNumber].push_back(0);
}
matrix[vertexNumber].push_back(stoi(word));
}
}
long size = matrix.size();
isExplored.resize(size);
f.resize(size);
for(unsigned long i = 0; i < matrix.size(); i++) {
isExplored.push_back(false);
f.push_back(0);
}
cout << "done";
}
My dfs algorithm is:
void dfs(long vertex, InputClass kostas) {
isExplored[vertex] = true;
cout << "vertex: " << vertex; //1
for(unsigned long i = 1; i < kostas.matrix[vertex].size(); i++) {
cout << " i: " << i << endl;
if(!isExplored[kostas.matrix[vertex].at(i)]) {
cout << "done1" << endl;
dfs(kostas.matrix[vertex].at(i), kostas);
cout << "done2" << endl;
}
}
t++;
f[vertex] = t;
}
And finally the dfs loop:
void dfsLoop(InputClass kostas) {
t = 0;
for(unsigned long i = kostas.matrix.size() - 1; i >= 1; i--) {
if(!isExplored[i]) {
dfs(i, kostas);
cout << "done" << " t " << endl;
}
//more code here
}
My program crashes at i = kostas.matrix.size() - 1 after some(i think 5) dfs recursive calls. The crash happens on the dfs call and //1 is never printed. I have checked the vector but they are intialized fine. Since //1 is never printed my guess is that the crash happens on function's variables long vertex or InputClass kostas. Kostas should be fine and my guess is that long vertex causes the error. Any suggestions? I must also mention that the algorithm works wihout a problem on small/medium inputs.
It appears to me that you are copying the InputClass every time you make a call to dfs. Try passing it by reference by changing the method to void dfs(long vertex, InputClass &kostas) and the method call to dfs(i, kostas);
I have an assignment with several ways to manipulate an array, but I'm having trouble with one of the parts.
I am reading about 50 numbers into the array from a .txt file
And for every odd location in the array (1,3,5,…), I have to subtract it from the previous even location (0,2,4,…) and store results in the odd location. Then I print out all values in the array.
Here is what I have so far:
void oddMinusEven(int ary[],int num)
{
for(int idx = ary[0]; idx<num; ary[idx+2])
{
ary[idx] = ary[idx+2]-ary[idx];
cout<<ary[idx]<<endl;
}
}
How do I do this? If you could provide some examples, that would be great.
This should do:
void oddMinusEven(int ary[], int num) {
for(int i = 1; i < num; i += 2) {
ary[i] = ary[i-1] - ary[i];
std::cout << "a[" << i << "] = " << ary[i] << std::endl;
}
}
The following pertains to homework. Restraunt pet project type thing, task is to update it to use vectors. The issue I'm having is this:
This winds up causing a core segmentation fault, yet is able to retrieve all the information appropriately when I use valgrind.
void Table::partyCheckout(void)
{
if(status == SERVED)
{
cout << " ---------------- " << endl;
cout <<"Table: " << tableId << "\nParty Size: " << numPeople << "\nWaiter: " << waiter->getName() << "\nSummary: " <<endl;
order->requestSummary();
cout << "Total: " << endl;
order->requestTotal();
cout << " ---------------- " << endl;
status = IDLE;
}
else
{
cout << "Error: " << tableId << " ";
if(numPeople == 0)
{
cout << "No one is at this table." << endl;
}
else
{
cout << "This party hasn't been served." << endl;
}
}
}
Setup: I'm storing the waiters and the orders in vectors.At runtime: when it does the waiter->getName() it complains that it's an invalid read, and that the memory location has been free'd by vector via a deallocater. My logic on the matter: It looks ahead and sees that the vector itself is not accessed again and so deallocates it. Since I do no more writing after this point, the memory location remains intact. When it tries to read the location it sees it has been free'd, hence invalid read but it still gets the appropriate data. So my question then, I suppose is two fold:Does this logic sound right? What should I do to fix it?
#ifndef HW3_H
#define HW3_H
#include <vector>
#include "Table.h"
#include "Waiter.h"
class hw3
{
private:
vector<Table> tables;
vector<Waiter> waiters;
vector<Order> orders;
public:
void begin();
};
#endif
.cpp file, most of the allocation:
ifstream configFile("config.txt"); //This guy is for initializing things
string line;
Menu theMenu;
getline(configFile, line);
stringstream intMaker;
int t1;
int t2;
string temp;
string temp2;
string temp3;
while (true)
{
getline(configFile, line);
Tokenizer str(line, " \n");
if(line =="")
{
break;
}
else
{
temp = str.next();
temp2 = str.next();
intMaker << temp;
intMaker >> t1;
intMaker.str("");
intMaker.clear();
intMaker << temp2;
intMaker >> t2;
intMaker.str("");
intMaker.clear();
tables.push_back(*(new Table(t1,t2)));
}
}
getline(configFile, line);
while (true)
{
getline(configFile, line);
Tokenizer name(line, " ");
string tabl = "";
//Siphon off the name and the tables.
temp = name.next();
tabl = name.next();
Tokenizer strink(tabl, ",\n");
int numTables = (int) tables.size();
Table * tabs[numTables];
t1 = 0;
int keepinTabs = 0;
while(true)
{
string temp2 = strink.next();
if (temp2 == "")
{
break;
}
else
{
intMaker << temp2;
intMaker >> t1;
intMaker.str("");
intMaker.clear();
for(int i = 0; i < numTables; i++)
{
if(tables.at(i).getTableId() == t1)
{
tabs[keepinTabs] = &tables.at(i);
}
}
keepinTabs++;
}
}
waiters.push_back(*(new Waiter(temp, tabl, *tabs))); //Waiter(name, list of tables, and an array of table numbers.
for(int j = 0; j < keepinTabs; j++)
{
for(int i = 0; i < tables.size(); i++)
{
if(tabs[j]->getTableId() == tables[i].getTableId())
{
tables.at(i).assignWaiter(&(waiters.back()));
}
}
}
if(line == "")
{
break;
}
}
Multiple issues I can see:
tables.push_back(*(new Table(t1,t2)));
This code dynamically allocates an object of type Table, then pushes a copy of this object into tables, and then forgets the address of the dynamically allocated object - you're leaking memory.
waiters.push_back(*(new Waiter(temp, tabl, *tabs)));
As above, with Waiter this time.
tabs[keepinTabs] = &tables.at(i);
This takes the address of an object inside the vector. While legal, it's extremely fragile. std::vector can move its contents around in memory when it resizes (e.g. when you push into it).
This (or similar code elsewhere) might be the cause of your segfault. Seeing as you're allocating the objects dynamically, maybe you should declare your vectors to hold just pointers:
vector<Table*> tables;
vector<Waiter*> waiters;
vector<Order*> orders;
You would then do e.g. tables.push_back(new Table(t1, t2));. Of course, you have to make sure to delete the dynamically allocated objects when you remove them from the vectors. An alternative would be to use smart pointers, e.g.:
vector<std::shared_ptr<Table> > tables;
vector<std::shared_ptr<Waiter> > waiters;
vector<std::shared_ptr<Order> > orders;