C++ strange "format" of output string - c++

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 :?

Related

strcpy is copying sth character onwards i string . How to resolve this error?

My complete code is at pastebin.
There is a train database , and user enters train number to book a ticket.The function updt_tick should copy the values of train's name,source and destination into passenger's reservation object.
But the problem is that 5th character onwards are only being copied.
Here is the function's code sample.Train database is entered by user.
void updt_tick()
{
fstream f;
f.open("train.dat",ios::in | ios::binary);
while(f.read((char*)&t,sizeof(t)))
{
if (tno==t.tno)
{
strcpy(bp,t.source);
strcpy(dest,t.dest);
strcpy(tname,t.tname);
amt=SeatNum*t.PerSeatFare;
break;
}
}
f.close();
}
The train class is ->
class train
{
public:
int tno;
char tname[100];
char source[100];
char dest[100];
int PerSeatFare;
public:
void getdetail();
void showdetail();
}t;
The reserv class is ->
`
class reserv
{
//Assume that cust select train according to his source and destination.
public:
int pnr;
int tno;
char tname[100];
char pnames[10][100];
int ages[10];
int SeatNum;
int i;
int d,m,y;
float amt;
char bp[100],dest[100];
void updt_tick()
{
fstream f;
f.open("train.dat",ios::in | ios::binary);
while(f.read((char*)&t,sizeof(t)))
{
if (tno==t.tno)
{
strcpy(bp,t.source);
strcpy(dest,t.dest);
strcpy(tname,t.tname);
amt=SeatNum*t.PerSeatFare;
break;
}
}
f.close();
}
public:
void getresdet()
{
cout<<"Enter the details as follows\n";
cout<<"Train no:";
cin>>tno;
cout<<"No of seats required:";
cin>>SeatNum;
cin.ignore();
for(i=0; i<SeatNum ; i++)
{
cout<<"Passenger name:";
gets(pnames[i]);
cout<<"Passenger age:";
cin>>ages[i];
cin.ignore();
}
cout<<"Date of travel:";
cin>>d>>m>>y;
cout<<"Details Accepted\n";
pnr=rand();
updt_tick();
}
void showresdet()
{
cout<<"Pnr no:"<<pnr;
cout<<"\nTrain no:"<<tno;
cout<<"\nTrain name:";
puts(tname);
cout<<"Boarding point:";
puts(bp);
cout<<"Destination pt:";
puts(dest);
cout<<"No of seats reserved:"<<SeatNum;
for(i=0; i<SeatNum; i++)
{
cout<<"Passenger name:";
puts(pnames[i]);
cout<<"Passenger age:"<<ages[i];
}
cout<<"\nDate of reservation:"<<d<<"-"<<m<<"-"<<y;
cout<<"\nYou must pay:"<<amt<<endl;
}
int getpnr()
{
return pnr;
}
};
Edit: There was nothing wrong with strcpy or any other code. I made
the foolish mistake of giving the file name as "train.dat" instead of
"trains.dat:.
Im not sure how did you manage to read 5 characters, because there is a problem is in your code. The file which you use to store train details is "trainS.dat", not "train.dat".

how to use gets function in c++ code?

In the main function of this code in the case 2 of switch case after entering the string program terminates! What is the problem with the code?
/*this code is a implementation of bubble sort algorithm*/
#include <iostream>
#include<conio.h>
#include<stdio.h>
#include<string.h>
#include<dos.h>
using namespace std;
int counter;
template <class T>//template created
class program//class which holds all the sorting functions
{
public:
T *v,x;
int j,k,l,siz,flag;
time_t t1,t2;
char c;
public:
void sortlist()//fn to sort characters and numbers
{
cout<<endl<<"------->>INTERMEDIATE STEPS<<-------";
for(k=1;k<=siz-1;k++)//sorting using a bubble sort
{ flag=0;
cout<<endl<<"PASS : "<<k<<endl;
j=0;
while(j<=siz-1-k)
{
if(v[j]>v[j+1])//comparing two consecutive elements
{
x=v[j+1];
v[j+1]=v[j];
v[j]=x;
flag++;
}
for(l=0;l<siz;l++)
{
cout<<v[l]<<" ";
}
cout<<endl;
j++;
}
cout<<"COMPARISONS:"<<(siz-k)<<endl;
if(flag==0)
{
cout<<endl<<"----->NO need to carry out more passes"<<endl<<"List is already sorted"<<endl;
break;
}
}
}
void stringsort()//fn to sort the strings
{
T a[90][20],b[1][20];
cout<<"enter the size of list:";
cin>>siz;
cout<<"enter the list:";
cin.ignore();
for(j=0;j<siz;j++)
{
gets(a[j]);
}
cout<<endl<<"------->>INTERMEDIATE STEPS<<-------";
for(k=1;k<=siz-1;k++)//sorting using bubble sort
{
flag=0;
cout<<endl<<"PASS : "<<k<<endl;
j=0;
while(j<siz-k)
{
x=strcmp(a[j],a[j+1]);//comparing two consecutive string
if(x>0)
{
strcpy(b[1],a[j+1]);
strcpy(a[j+1],a[j]);
strcpy(a[j],b[1]);
flag++;
}
for(l=0;l<siz;l++)
{
cout<<a[l]<<" ";
}
cout<<endl;
j++;
}
cout<<endl<<"COMPARISON:"<<(siz-k)<<endl;
if(flag==0)
{
cout<<endl<<"No need to carry out more passes"<<endl<<"List is already Sorted"<<endl;
break;
}
}
cout<<"SORTED LIST:"<<endl;
for(j=0;j<siz;j++)
{
cout<<endl<<a[j]<<endl;
}
}
};
int main()//main fn
{
int x;
char c;
do
{
program <char> p1;
program <int> p2;
cout<<endl<<"To sort a list of NUMBERS enter -> 1"<<endl<<endl<<"To sort string of CHARACTERS enter -> 2"<<endl<<endl<<"To sort a list OF STRINGS and DOUBLE_STRINGS enter -> 3";
cout<<endl<<endl<<"Enter either 1 OR 2 OR 3:";
cin>>x;
switch(x)
{
case 1://to sort list of numbers
{
cout<<endl<<"enter the size of list: ";
cin>>p2.siz;
cout<<"enter the list: "<<endl;
p2.v=new int[p2.siz];
for(p2.l=0;p2.l<=p2.siz-1;p2.l++)
{
cin>>p2.v[p2.l];
}
p2.sortlist();//sort and search in numbers
cout<<endl<<"SORTED LIST:"<<endl;//sorted list after the bubble sort
for(x=0;x<=(p2.siz)-1;x++)
{
cout<<p2.v[x]<<endl;
}
}
break;
case 2://to sort string of character
{
cout<<"enter the string of characters:";
cin.ignore()
gets(p1.v);
p1.siz=strlen(p1.v);
p1.sortlist();//sort in characters
cout<<endl<<"SORTED STRING:"<<p1.v;
}
break;
case 3://to sort list of strings
{
p1.stringsort();//sort list of string
}
break;
default:
cout<<"INVALID_CHOICE"<<endl<<endl;
}
cout<<endl<<"do u want to enter another list?y/n";
cin>>c;
}
while(c=='y');
return 0;
}
gets requires that you pass a pointer to enough storage space to hold the string that gets read. Your program passes an uninitialized pointer.
You're not really allowed to do anything with uninitialized values, so in theory your program can crash before it even enters the gets function.
Since the user can pass any amount of data to gets and your program would be responsible for storing it, the function is deprecated. It doesn't even exist any more in the C++ standard library as std::gets since 2011, although ::gets will probably always be available in POSIX. The short answer is, "don't."
You might consider std::string and std::getline instead.

Infinite loop when writing blank records to a binary file

The purpose of the following short program is to search through a binary file (that contains details of different trains) for a particular train (whose number is accepted from the user) and then rewrite a blank record at that location.
That is, I wish to 'delete' that train record.
The problem is that the program goes into an infinite loop and repeatedly writes blank records to the binary file, thereby resulting in an enormous 2 GB .dat file being created.
#include<iostream.h>
#include<fstream.h>
struct train {
int train_no;
char train_name[50], source[20], dest[20];
int n_AC1, n_AC2, n_ACC, n_FC, n_SLC, n_SS; // variables for no of seats
train() { //default constructor
train_no = 0;
n_AC1=0, n_AC2=0, n_ACC=0, n_FC=0, n_SLC=0, n_SS=0;
strcpy(train_name, "/0");
strcpy(source, "/0");
strcpy(dest, "/0");
}
//member functions to accept and display the above values
};
void remove_train(fstream &f) {
train t, blank;
int tno, found = 0;
do {
cout<<"Enter the train no: ";
cin>>tno;
if(tno <=0)
cout<<"Invalid train number. Please re-enter."<<endl;
}
while(tno <=0);
f.seekg(0L, ios::beg);
f.read((char*)&t, sizeof(train));
while(!f.eof() && !found) {
if(t.train_no == tno) {
found = 1;
f.seekp(-sizeof(train), ios::cur);
f.write((char*)&blank, sizeof(train));
cout<<"Train number "<<tno<<" has been deleted!"<<endl;
}
else
f.read((char*)&t, sizeof(train));
}
if(found == 0)
cout<<"ERROR: train not found."<<endl;
}
int main() {
fstream f("Trains.dat", ios::binary | ios::in | ios::out);
remove_train(f);
cin.ignore();
cin.get();
}
When the above program is executed, after I input the train number as '1', the only observable output is "Train number 1 has been deleted", following which the program goes into the aforementioned infinite loop.
This doesn't seem to be an isolated issue; whenever I try to move back by one record and
then write a blank record anywhere in the Railway Reservation project that this code is a part of, the same problem ensues. For instance, if it is a passenger record I wish to overwrite, this is the relevant code fragment that seems to be causing the issue:
f.seekp(-1L*sizeof(passenger), ios::cur);
f.write((char*)&p, sizeof(passenger));
MAJOR EDIT: The problem was fixed when I replaced -sizeof(train) with -110L (which is the byte size of the 'train' structure)! Any idea why this is the case?
I must say I am at a loss to find a fault in your code. I've run a copy of it and it worked as expected.
There are a few minor errors (for instance it will fail if your data file does not exist) and the code could certainly be improved (your usage of f.eof() is somewhat awkward), but nothing that can explain the behaviour you're describing.
Here is the exact version I'm running right now. Except for a bit of extra code to create a dummy data file and a few debug outputs, I don't see any difference with yours.
Maybe you could try to compile it and see if it fails in your environment?
#include<iostream>
#include<fstream>
#include <string.h>
using namespace std;
struct train {
int train_no;
char train_name[50], source[20], dest[20];
int n_AC1, n_AC2, n_ACC, n_FC, n_SLC, n_SS; // variables for no of seats
train() { //default constructor
train_no = 0;
n_AC1=0, n_AC2=0, n_ACC=0, n_FC=0, n_SLC=0, n_SS=0;
strcpy(train_name, "");
strcpy(source, "");
strcpy(dest, "");
}
//member functions to accept and display the above values
};
void remove_train(fstream &f) {
train t, blank;
int tno, found = 0;
do {
cout<<"Enter the train no: ";
cin>>tno;
if(tno <=0)
cout<<"Invalid train number. Please re-enter."<<endl;
}
while(tno <=0);
cout<<"deleting train "<<tno<<endl;
f.seekg(0L, ios::beg);
f.read((char*)&t, sizeof(train));
while(!f.eof() && !found) {
cout<<f.tellp()<<endl;
if(t.train_no == tno) {
found = 1;
f.seekp(-sizeof(train), ios::cur);
cout<<"delete "<<f.tellp()<<"/"<<f.tellg()<<endl;
f.write((char*)&blank, sizeof(train));
cout<<"Train number "<<tno<<" has been deleted!"<<endl;
}
else
{
cout<<"read "<<f.tellg()<<endl;
f.read((char*)&t, sizeof(train));
}
}
if(found == 0)
cout<<"ERROR: train not found."<<endl;
else
cout<<"done"<<endl;
}
void create_trains(int n)
{
fstream f("Trains.dat", ios::binary | ios::out);
train t;
for (int i = 1 ; i <= n ; i++)
{
t.train_no = i;
f.write((char*)&t, sizeof(train));
}
}
int main() {
create_trains (10);
fstream f("Trains.dat", ios::binary | ios::in | ios::out);
remove_train(f);
cin.ignore();
cin.get();
}

searching method using certain keyword to give desired output

here i want enter the patient data, and then i want to be able to give output after key in the id, this means that i use searching method, here i use linear search. i use array, to save the patient data, such as name and age. so in pharmacy department i want to be able to search the patient data before approving giving medicine.
#include<iostream.h>
int linear(int patient[],int size,int key);
int linear(int patient[],int size,int key) {
int i;
for(i=0;i<2;i++) {
if(key==patient[i].id) {
return i;
}
}
return -1;
}
void main() {
int i=0;
int size=2;
struct patientRecord {
char name[20];
int id,age;
int *patient;
};
patientRecord patient[i];
int choice;
cout<<"Welcome to Hospital Sejahtera\n";
cout<<"Please enter your choice:";
cout<<"1.Patient Registration\n2.Pharmacy\n3.Doctor Appoinment";
cin>>choice;
if(choice==1) {
for(i=0;i<2;i++) {
cout<<"Please enter patient name";
cin>>patient[i].name;
cout<<"Please enter patient id";
cin>>patient[i].id;
cout<<"Please enter patient age";
cin>>patient[i].age;
}
} else if(choice==2) {
int i;
for(i=0;i<2;i++) {
cout<<"Enter the patient id to search:";
cin>>patient[i].id;
linear(patient,size,patient[i].id);
cout<<"Location at index:";
cout<<endl;
}
}
}
i would be glad if you all can point out my mistake. im still learning. please help.
You might get a compile warning here that the variable size is not used.
You should check out what that is and where it should go.
int linear(int patient[],int size,int key) {
int i;
for(i=0;i<2;i++) {
if(key==patient[i].id) {
return i;
}
}
return -1;
}

C++ Copy one struct value to other

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;
}