C++ Copy one struct value to other - c++

I have a simple structure:
struct Appartament
{
char address[50];
char telephoneNumber[20];
char view[10];
double price;
double distanceFromCenter;
int roomCount;
};
I have some records written in a file. Now, I want to read all records from the file and to get only this who have roomCount smaller then a number (user input). This is easy, but the records should be displayed sorted by price. That's way I have to put them in a array and after that to sort them.
I have some problems and I believe that they are because I am not copping the structures well.
I have try different ways:
strcpy(CurrentRecords[index].address,currentRecord.address);
strcpy(CurrentRecords[index].telephoneNumber,currentRecord.telephoneNumber);
strcpy(CurrentRecords[index].view,currentRecord.view);
CurrentRecords[index].price=currentRecord.price;
CurrentRecords[index].distanceFromCenter=currentRecord.distanceFromCenter;
CurrentRecords[index].roomCount=currentRecord.roomCount;
or
memcpy(CurrentRecords[index],currentRecord,sizeof(Appartament));
and
CurrentRecords[index]=currentRecord
but nothing works...
EDIT: Here is the my code - "nothing works" refers to something like endless loop.
void AdvanceSearch()
{
clrscr();
Appartament currentRecord;
fstream currentFile("Records.dat",ios::binary|ios::in);
if(!currentFile)
{
cout<<"Error - the file could not be opened."<<endl;
return;
}
else
{
//Array with apartments records
Appartament CurrentRecords[MaxRecords];
currentFile.seekg(0L,ios::end);
long int length=currentFile.tellg();
currentFile.seekg(0L,ios::beg);
int isAppartamentFound=0;
if(length==0)
{
cout<<"The file is empty."<<endl;
return;
}
else
{
int userRoomCount;
do
{
clrscr();
cout<<"Enter apartment room count - ";
cin>>userRoomCount;
}while(userRoomCount<0);
clrscr();
cout<<endl<<"Apartments with "<<userRoomCount<<" rooms order by price:";
currentFile.read((char*)(&currentRecord),sizeof(Appartament));
int index=0;
while(!currentFile.eof())
{
if(currentRecord.roomCount==userRoomCount)
{
/*
strcpy(CurrentRecords[index].address,currentRecord.address);
strcpy(CurrentRecords[index].telephoneNumber,currentRecord.telephoneNumber);
strcpy(CurrentRecords[index].view,currentRecord.view);
CurrentRecords[index].price=currentRecord.price;
CurrentRecords[index].distanceFromCenter=currentRecord.distanceFromCenter;
CurrentRecords[index].roomCount=currentRecord.roomCount;
*/
memcpy(CurrentRecords[index],currentRecord,sizeof(Appartament));
//CurrentRecords[index]=currentRecord;
index++;
isAppartamentFound=1;
}
currentFile.read((char*)(&currentRecord),sizeof(Appartament));
}
currentFile.close();
}
if(isAppartamentFound==0)
{
cout<<endl<<"There are no matches!"<<endl;
}
else
{
//If only one apartment is found
if(sizeof(CurrentRecords)/sizeof(Appartament)==1)
{
cout<<endl;
ShowRecord(currentRecord);
}
else
{
//Sort the records
Appartament tempApartament;
int isChangeMade=1;
while(isChangeMade==1)
{
isChangeMade=0;
for(int index=0;index<(sizeof(CurrentRecords)/sizeof(Appartament))-1.0;index++)
{
if(CurrentRecords[index].price>CurrentRecords[index+1].price)
{
isChangeMade=1;
CopyApartament(tempApartament,CurrentRecords[index]);
CopyApartament(CurrentRecords[index],CurrentRecords[index+1]);
CopyApartament(CurrentRecords[index+1],tempApartament);
}
}
}
for(int index=0;index<sizeof(CurrentRecords)/sizeof(Appartament)-1.0;index++)
{
ShowRecord(CurrentRecords[index]);
}
}
}
}
}
void CopyApartament(Appartament RecordOne,Appartament RecordTwo)
{
/*
strcpy(RecordOne.address,RecordTwo.address);
RecordOne.distanceFromCenter=RecordTwo.distanceFromCenter;
RecordOne.price=RecordTwo.price;
RecordOne.roomCount=RecordTwo.roomCount;
strcpy(RecordOne.telephoneNumber,RecordTwo.telephoneNumber);
strcpy(RecordOne.view,RecordTwo.view);
*/
RecordOne=RecordTwo;
}
Note: I thought that my problem is the copying because I have not know how to do this.

CurrentRecords[index]=currentRecord;
That copies an entire structure and should work as expected.
Are you sure you are sorting correctly?

I don't see any particularly good reason to have explicit copying of the data anywhere. I think I'd do something like this:
std::vector<Apartment> get_apts(int max_rooms) {
std::vector<Apartment> apts;
std::copy_if(file.begin(), file.end(), std::back_inserter(apts),
[max_rooms](Apartment const &a) {
return a.roomCount < max_rooms;
});
std::sort(apts.begin(), apts.end(),
[](Apartment const &a, Apartment const &b) {
return a.price < b.price);
});
return apts;
}

Related

Getting wrong answer in a DP problem although implementation looks correct

I was trying to solve Reduce String on codechef which says
Give a string s of length l, and a set S of n sample string(s). We do reduce the string s using the set S by this way:
Wherever Si appears as a consecutive substring of the string s, you can delete (or not) it.
After each deletion, you will get a new string s by joining the part to the left and to the right of the deleted substring.
I wrote a recursive function as follows:-
Basically what i am doing in my code is either don't delete the character or delete it if it is part of any substring but it is giving wrong answer.
#include <bits/stdc++.h>
using namespace std;
#define mx 255
int dp[mx];
unordered_map<string,int> sol;
void init(int n)
{
for(int i=0;i<n;i++)
{
dp[i]=-1;
}
}
int solve(string str,int low,int high,vector<string> smp)
{
if(low>high)
{
return 0;
}
if(dp[low]!=-1)
{
return dp[low];
}
int ans=1+solve(str,low+1,high,smp);
for(int i=low;i<high;i++)
{
string tem=str.substr(low,i-low+1);
for(int j=0;j<smp.size();j++)
{
cout<<"low i high str"<<low<<" "<<i<<" "<<high<<" "<<smp[j]<<" "<<tem<<endl;
if(tem.compare(smp[j])==0)
{
ans=min(ans,solve(str,i+1,high,smp));
}
}
}
return dp[low]=ans;
}
signed main()
{
sol.clear();
string str;
vector<string> smp;
int n;
cin>>str;
cin>>n;
for(int i=0;i<n;i++)
{
string tem;
cin>>tem;
smp.push_back(tem);
}
int len=str.length();
init(len+1);
cout<<solve(str,0,len-1,smp)<<endl;
return 0;
}
PS:
link to the question
This question is toughest(seen so far) and most beautiful(again seen so far) question based on DP ON INTERVALS.
The initial code would definitely not work since it only considers single pass on the string and would not consider remaining string after deleting the patterns again and again.
There are 3 cases:-
Case 1 Either character is not deleted.
Case 2It is deleted as a part of contiguous substring.
Case 3It is deleted as a part of subsequence that matches any word given in the set of patterns and everything that is not part of that subsequence is deleted first as a substring(which again belongs to set of words).
The third part is the most tricky and requires enough thinking and is even tougher to implement too.
So for every substring we need to check whether this substring can be completely destroyed or not.
The function compute_full_recur() is the function that ensures that whether substring can be deleted either in Case 2 or Case 3.
The function compute_full takes care of Case 1.And finally this code will not run on codechef link since all the function are recursive with memoization but to verify the code is working i Have run it on Problem Reducto of Hackerrank which is exact similar with lower constraints.Download test cases and then run on test cases on your PC for verifying.
#include <iostream>
#include <vector>
#include <string>
using namespace std;
#define mx 252
#define nx 40
bool full[mx][mx],vis[mx][mx],full_recur[mx][mx][nx][nx];
int ans[mx];
void init()
{
for(int i=0;i<mx;i++)
{
for(int j=0;j<mx;j++)
{
full[i][j]=false,vis[i][j]=false;
}
}
for(int i=0;i<mx;i++)
{
ans[i]=-1;
}
for(int i=0;i<mx;i++)
{
for(int j=0;j<mx;j++)
{
for(int k=0;k<nx;k++)
{
for(int l=0;l<nx;l++)
{
full_recur[i][j][k][l]=false;
}
}
}
}
}
bool compute_full_recur(string str,int low,int high,vector<string> pat,int idx,int len)
{
if(low>high&&len==pat[idx].length())
{
return true;
}
if(low>high&&len<pat[idx].length())
{
full_recur[low][high][idx][len]=false;
return false;
}
if(str[low]==pat[idx][len]&&compute_full_recur(str,low+1,high,pat,idx,len+1))
{
return full_recur[low][high][idx][len]=true;
}
for(int i=low+1;i<=high;i++)
{
if(str[low]==pat[idx][len]&&full[low+1][i]&&compute_full_recur(str,i+1,high,pat,idx,len+1))
{
return full_recur[low][high][idx][len]=true;
}
}
full_recur[low][high][idx][len]=false;
return false;
}
void compute_full(string str,int low,int high,vector<string> pats)
{
if(low>high)
{
return;
}
if(vis[low][high])
{
return;
}
vis[low][high]=true;
compute_full(str,low+1,high,pats);
compute_full(str,low,high-1,pats);
for(int i=0;i<pats.size();i++)
{
if(!full[low][high])
full[low][high]=compute_full_recur(str,low,high,pats,i,0);
}
}
int compute_ans(string str,int low,int high)
{
if(low>high)
{
return 0;
}
if(ans[low]!=-1)
{
return ans[low];
}
int sol=1+compute_ans(str,low+1,high);
for(int i=low+1;i<=high;i++)
{
if(full[low][i]==true)
{
sol=min(sol,compute_ans(str,i+1,high));
}
}
return ans[low]=sol;
}
signed main()
{
int t;
cin>>t;
while(t--)
{
string str;
int n;
vector<string> pats;
cin>>n>>str;
for(int i=0;i<n;i++)
{
string tem;
cin>>tem;
pats.push_back(tem);
}
init();
compute_full(str,0,str.length()-1,pats);
cout<<compute_ans(str,0,str.length()-1)<<endl;
}
return 0;
}

How to correctly create a ofstream of a struct vector? (abort() is called)

I'm currently building a game and in this part my goal is to update a previously created file of High Scores ("rank.txt")
To do so, I've created a couple of functions so they can read what's in the txt file and so it can update it. Though the reading is ok, while adding the update function it gives me an error and tells me abort() has been called.
void highScoresUpdate(vector<PlayerInfo> player)
{
// This function is responsible for updating the High Scores Table present in the RANK.TXT file
vector<HighScoresStruct> highScores_temp;
HighScoresStruct temp;
ofstream out_file_3("rank.txt");
highScores_temp = readHighScores("rank.txt");
for (int k = 0; k < player.size(); k++)
{
player[k].name = temp.name;
player[k].score = temp.score;
player[k].time = temp.time;
highScores_temp.push_back(temp);
}
sort(highScores_temp.begin(), highScores_temp.end(), compareByScore);
for (int i = 0; i < highScores_temp.size(); i++)
{
out_file_3 << highScores_temp[i].name << endl << highScores_temp[i].score << endl << highScores_temp[i].time << endl;
}
out_file_3.close();
}
For background information, so i don't spam this thread with code all you need to know is that readHighScores is the function responsible for extracting information from the txt file and placing it on a vector .
The structs and comparebyScore funtion are listed below.
bool compareByScore(const HighScoresStruct &a, const HighScoresStruct &b)
{
if (a.score < b.score)
return true;
else if (a.score == b.score)
{
if (a.time > b.time)
return true;
else
return false;
}
else
return false;
}
struct PlayerInfo
{
string name;
unsigned int score;
vector<char> hand;
bool inGame;
unsigned int time;
};
struct HighScoresStruct
{
string name;
unsigned int score;
unsigned int time;
};
So... Can anyone help me?

Prime numbers in an dynamic array

I've a program which inserts all prime numbers up to a specific number in an array.
The calculation is correct. My problems are the function parameters and the transfer of my dynamic array to the function. My function doesn't modify my array.
Please take a look at the code:
#include <iostream>
using namespace std;
int primeinlesen(int *i);
int primarrayspeicherung (int *primarray,int *bis);
int main()
{
int reload=1;
while(reload==1)
{
int bis=0,*primarray,valcounter;
primeinlesen(&bis);
valcounter=primarrayspeicherung(primarray,&bis);
for(int i=0;i<valcounter;i++)
{
cout<<i<<". Primzahl: "<<primarray[i]<<"\n";
}
delete [] primarray;
cout<<"Anzahl Primzahlen: "<<valcounter<<endl;
cout<<"Erneute Berechnung?(Ja(1) oder Nein(0))";
cin>>reload;
}
return 0;
}
int primeinlesen(int *i)
{
cout<<"Bis zu welchem Wert moechten SiePrimzahlen ausgegeben,haben(max.500)";
cin>>*i;
if(*i>500)
{
cout<<"Wert zu hoch...";
}
return 0;
}
int primarrayspeicherung (int *primarray,int *bis)
{
int x,y,counter,e,valcounter=0,xcounter=0,xvalcounter=0,xx,xy,xe;
for(x=2;x<*bis;x++)
{
counter=0;
for(y=2;y<x;y++)
{
e=x%y;
if(e==0)
{
counter++;
}
}
if(counter==0)
{
valcounter++;
}
}
//ZWEITER DURCHGANG
primarray=new int[valcounter];
for(xx=2;xx<*bis;xx++)
{
xcounter=0;
for(xy=2;xy<xx;xy++)
{
xe=xx%xy;
if(xe==0)
{
xcounter++;
}
}
if(xcounter==0)
{
primarray[xvalcounter]=xx;
xvalcounter++;
}
}
return valcounter;
}
Best regards
In this function:
int primarrayspeicherung (int *primarray,int *bis)
primarray is a local variable. Everything you're doing to it (e.g. allocating, assigning) only affects the local primarray, not the one you pass in. If you want to modify both, you need to pass in a reference:
int primarrayspeicherung (int*& primarray,int *bis)

Quiz program always evaluating answer to be wrong

class Question{
protected:
int op1;
int op2;
string operate;
public:
Question();
};
class generateRandomQuiz:Question{
public:
generateRandomQuiz();
int getp1();
int getp2();
string getOp();
};
class checkAnswer:generateRandomQuiz{
private:
int Ans;
public:
checkAnswer(int ans);
};
Question::Question()
{
op1=23;
op2=12;
operate="/";
}
generateRandomQuiz::generateRandomQuiz():Question()
{
op1=rand()%50;
op2=rand()%50;
string s="+-/*";
int n=rand()%4;
operate=s[n];
}
int generateRandomQuiz::getp1()
{
return op1;
}
int generateRandomQuiz::getp2()
{
return op2;
}
string generateRandomQuiz::getOp()
{
return operate;
}
checkAnswer::checkAnswer(int ans):generateRandomQuiz()
{
Ans=ans;
string operate=getOp();
int op1=getp1();
int op2=getp2();
if (operate=="+")
{
if (op1+op2==Ans)
{
cout<<"Your answer is correct."<<endl;
}
else
{
cout<<"You can do better next time."<<endl;
}
}
if (operate=="-")
{
if (op1-op2==Ans)
{
cout<<"Your answer is correct."<<endl;
}
else
{
cout<<"You can do better next time."<<endl;
}
}
if (operate=="*")
{
if (op1*op2==Ans)
{
cout<<"Your answer is correct."<<endl;
}
else
{
cout<<"You can do better next time."<<endl;
}
}if (operate=="/")
{
if (op1/op2==Ans)
{
cout<<"Your answer is correct."<<endl;
}
else
{
cout<<"You can do better next time."<<endl;
}
}
}
int main()
{
cout<<"This quiz is about evaluating an expression which is being generatedrandomly"
<<endl;
generateRandomQuiz Q;
int answer;
int op1=Q.getp1();
int op2=Q.getp2();
string opr=Q.getOp();
cout<<"What is: "<<op1<<op2<<op2<<"=?"<<endl;
cin>>answer;
checkAnswer A(answer);
system("PAUSE");
return 0;
}
I am writing a program which generates a quiz randomly and asks the user for an answer answer like this: What is : 15 / 43 = ? The operator and numbers are randomly generated.But when i givw the correct answer,even then the comment for the wrong answer is printed.I have written conditions quite clear.Can someone please point it out?thanks
To check the answer you are relying on the fact that checkAnswer inherits from generateRandomQuiz.
But when you actually check the answer, you use a different instance than the random generated quiz, so you cannot get the generated quiz by doing stuff like int op1=getp1();.
By doing this you will get default constructed values only, and since your constructor does the randomizing, you will get a different question altogether. So the checking mechanism is right, its just checking a different question. I suggest you rethink your code structure, it looks very awkward.

C++ strange "format" of output string

I am writing a C++ applications that is working with files. I have implemented standard operations like writing and reading from the file, some search functions, etc.
After doing some operations, my output strings come in a very strange way. For example the text "Address -", comes as "?п&&..&":
Is there any buffer in C++ that could be full by the file operations and it is doing this output so i need to empty it or clean it?
Edit: The problem appeared when I write a functions that is reading the records from my file, choosing some of them due to user criteria and then sorting them.
Here is my code:
Stucture:
struct Appartament
{
char address[50];
char telephoneNumber[20];
char view[10];
double price;
double distanceFromCenter;
int roomCount;
};
Function working with the file:
//Search by room count and order by price (rising)
void AdvanceSearch()
{
clrscr();
Appartament currentRecord;
int recordsCount=0;
fstream currentFile("Records.dat",ios::binary|ios::in);
if(!currentFile)
{
cout<<"Error - the file could not be opened."<<endl;
return;
}
else
{
//Array with apartments records
Appartament CurrentRecords[MaxRecords];
currentFile.seekg(0L,ios::end);
long int length=currentFile.tellg();
currentFile.seekg(0L,ios::beg);
int isAppartamentFound=0;
if(length==0)
{
cout<<"The file is empty."<<endl;
return;
}
else
{
int userRoomCount;
do
{
clrscr();
cout<<"Enter apartment room count - ";
cin>>userRoomCount;
}while(userRoomCount<0);
clrscr();
cout<<endl<<"Apartments with "<<userRoomCount<<" rooms order by price:";
currentFile.read((char*)(&currentRecord),sizeof(Appartament));
while(!currentFile.eof())
{
if(currentRecord.roomCount==userRoomCount)
{
CurrentRecords[recordsCount]=currentRecord;
recordsCount++;
isAppartamentFound=1;
}
currentFile.read((char*)(&currentRecord),sizeof(Appartament));
}
currentFile.close();
}
if(isAppartamentFound==0)
{
cout<<endl<<"There are no matches!"<<endl;
}
else
{
//If only one apartment is found
if(recordsCount==1)
{
cout<<endl;
ShowRecord(currentRecord);
}
else
{
//Sort the records
Appartament tempApartament;
int isChangeMade=1;
for(int index=0;index<recordsCount;index++){
//ShowRecord(CurrentRecords[index]);
}
while(isChangeMade==1)
{
isChangeMade=0;
for(int index=0;index<recordsCount-1;index++)
{
if(CurrentRecords[index].price>CurrentRecords[index+1].price)
{
isChangeMade=1;
tempApartament=CurrentRecords[index];
CurrentRecords[index]=CurrentRecords[index+1];
CurrentRecords[index+1]=tempApartament;
}
}
}
for(index=0;index<recordsCount;index++)
{
ShowRecord(CurrentRecords[index]);
}
}
}
}
}
Function for showing a record:
void ShowRecord(Appartament Record)
{
cout<<"Apartment Information"<<endl;
cout<<"The address is - "<<Record.address<<" and it is only "<<Record.distanceFromCenter<<" miles away from the center."<<endl;
cout<<"The price is "<<Record.price<<" $ for "<<Record.roomCount<<" rooms with "<<Record.view<<" view."<<endl;
}
Тhis is possible output:
I have run my program on other machine with other version of Borland and it is working perfectly. That's why the questions is what is wrong with mine compiler :?