Getting Garbage Values while reading struct data from a binary file - c++

Hi guys in my previous question, I was able to get the data of a struct to be loaded on a file, but now the issue is I'm getting garbage value while retrieving it.
File Contents: settings.bin
110#NormalCompression Level210#NormalCompression Level310#NormalCompression Level410#NormalCompression Level510#NormalCompression Level
Code
#include<cstdlib>
#include<iostream>
#include<string>
#include<iomanip>
#include<fstream.h>
using namespace std;
const char* ErrorLogFilePath = "resources\\error.txt";
const char* SettingsFilePath = "resources\\settings.bin";
const int NoOfSettings = 5;
struct Setting {
int SettingID;
int SettingINTValue;
double SettingDOUBLEValue;
char SettingCHARValue;
string SettingSTRINGValue;
string SettingName;
};
istream& operator>>(istream& _is, Setting& _s) {
_is>>_s.SettingID;
_is>>_s.SettingINTValue;
_is>>_s.SettingDOUBLEValue;
_is>>_s.SettingCHARValue;
_is>>_s.SettingSTRINGValue;
_is>>_s.SettingName;
}
ostream& operator<<(ostream& _os, const Setting& _s) {
_os<<_s.SettingID;
_os<<_s.SettingINTValue;
_os<<_s.SettingDOUBLEValue;
_os<<_s.SettingCHARValue;
_os<<_s.SettingSTRINGValue;
_os<<_s.SettingName;
}
class ErrorReport {
public:
fstream ErrorFile;
void PostError(string Title,string Data,int ErrorID) {
ErrorFile.open(ErrorLogFilePath,ios::out);
ErrorFile.close();
}
} Error;
class SettingsClass {
public:
Setting setting[NoOfSettings];
void ResetSettings() {
fstream SettingFile;
Setting defaultsetting[NoOfSettings];
for(int i=1; i<=NoOfSettings; i++) {
defaultsetting[i-1].SettingID = i;
defaultsetting[i-1].SettingINTValue = 0;
defaultsetting[i-1].SettingDOUBLEValue = 0;
defaultsetting[i-1].SettingCHARValue = '#';
defaultsetting[i-1].SettingSTRINGValue = "null";
switch(i) {
default:
defaultsetting[i-1].SettingName = "Compression Level";
defaultsetting[i-1].SettingSTRINGValue = "Normal";
defaultsetting[i-1].SettingINTValue = 1;
break;
}
}
SettingFile.open(SettingsFilePath,ios::binary|ios::out);
if(SettingFile.is_open()) {
for(size_t i=0; i<NoOfSettings; ++i) {
SettingFile<<defaultsetting[i];
}
} else {
cout<<"Error!";
}
SettingFile.close();
}
void _SettingsClass() {
fstream SettingFile;
SettingFile.open(SettingsFilePath,ios::binary|ios::in);
Setting TempSettings[NoOfSettings];
if(SettingFile.is_open()) {
for(size_t i=0; i<NoOfSettings; ++i) {
SettingFile>>TempSettings[i];
}
} else {
cout<<"Error...";
}
SettingFile.close();
for(int i=0; i<NoOfSettings; i++) {
cout<<TempSettings[i].SettingINTValue<<"\n";
}
}
} Settings;
int main(int argc, char *argv[])
{
Settings._SettingsClass();
// cout<<Settings.GetSetting(1).SettingName;
system("PAUSE");
return EXIT_SUCCESS;
}
Output
4473076
1
3
0
2686384
Now Why I'm getting those garbage values? Can anyone help me, cause I think it should not turn up like this(?). And I should be getting 1 for each such element of that struct array.
Thanks in Advance!

Formatted input requires delimiters so it knows when to stop reading for a particular value. Even though you're opening the file in binary mode what you're writing is in essence a text file with no delimiters so you can't read it back.
If you must have a binary file then this is the way to read/write one using your structure:
#include <iostream>
#include <string>
#include <iomanip>
#include <fstream>
#include <vector>
const char* SettingsFilePath = "settings.bin";
struct Setting
{
int SettingID;
int SettingINTValue;
double SettingDOUBLEValue;
char SettingCHARValue;
std::string SettingSTRINGValue;
std::string SettingName;
Setting()
: SettingID(0)
, SettingINTValue(0)
, SettingDOUBLEValue(0)
, SettingCHARValue(0)
{
}
void Write(std::fstream& out)
{
out.write(reinterpret_cast<const char*>(&SettingID), sizeof(SettingID));
out.write(reinterpret_cast<const char*>(&SettingINTValue), sizeof(SettingINTValue));
out.write(reinterpret_cast<const char*>(&SettingDOUBLEValue), sizeof(SettingDOUBLEValue));
out.write(reinterpret_cast<const char*>(&SettingCHARValue), sizeof(SettingCHARValue));
size_t str_size = SettingSTRINGValue.size();
out.write(reinterpret_cast<const char*>(&str_size), sizeof(str_size));
out.write(SettingSTRINGValue.c_str(), SettingSTRINGValue.size());
str_size = SettingName.size();
out.write(reinterpret_cast<const char*>(&str_size), sizeof(str_size));
out.write(SettingName.c_str(), SettingName.size());
}
void Read(std::fstream& in)
{
in.read(reinterpret_cast<char*>(&SettingID), sizeof(SettingID));
in.read(reinterpret_cast<char*>(&SettingINTValue), sizeof(SettingINTValue));
in.read(reinterpret_cast<char*>(&SettingDOUBLEValue), sizeof(SettingDOUBLEValue));
in.read(reinterpret_cast<char*>(&SettingCHARValue), sizeof(SettingCHARValue));
size_t str_size;
std::vector<char> str_data;
in.read(reinterpret_cast<char*>(&str_size), sizeof(str_size));
str_data.resize(str_size);
in.read(&str_data[0], str_size);
SettingSTRINGValue.assign(str_data.begin(), str_data.end());
in.read(reinterpret_cast<char*>(&str_size), sizeof(str_size));
str_data.resize(str_size);
in.read(&str_data[0], str_size);
SettingName.assign(str_data.begin(), str_data.end());
}
void Print(const std::string& title)
{
std::cout << title << "\n";
std::cout << std::string(title.size(), '-') << "\n";
const size_t w = 22;
std::cout << std::setw(w) << std::right << "SettingID : " << SettingID << "\n";
std::cout << std::setw(w) << std::right << "SettingINTValue : " << SettingINTValue << "\n";
std::cout << std::setw(w) << std::right << "SettingDOUBLEValue : " << SettingDOUBLEValue << "\n";
std::cout << std::setw(w) << std::right << "SettingCHARValue : " << SettingCHARValue << "\n";
std::cout << std::setw(w) << std::right << "SettingSTRINGValue : " << SettingSTRINGValue << "\n";
std::cout << std::setw(w) << std::right << "SettingName : " << SettingName << "\n";
std::cout << "\n";
}
};
int main()
{
{
Setting s;
s.Print("Default before Write");
s.SettingID = 1;
s.SettingINTValue = 2;
s.SettingDOUBLEValue = 3.5;
s.SettingCHARValue = 'Z';
s.SettingSTRINGValue = "Blah Blah";
s.SettingName = "Some Settings";
std::fstream f(SettingsFilePath, std::ios::out | std::ios::binary);
s.Write(f);
s.Print("Values written to file");
}
{
Setting s;
s.Print("Default before read");
std::fstream f(SettingsFilePath, std::ios::in | std::ios::binary);
s.Read(f);
s.Print("Values after read");
}
return EXIT_SUCCESS;
}

It seems you forgot to load your setting into file.
int main(int argc, char *argv[])
{
Settings.ResetSettings(); // insert code here
Settings._SettingsClass();
// cout<<Settings.GetSetting(1).SettingName;
system("PAUSE");
return EXIT_SUCCESS;
}

Related

Create binray file in constructor

I write a small Store that contain Item. I create two function one to print content of file one to sort the records and insert them back into file. With the initializer list it display correctly the content of file, but said that there is "Error with file". How to correct this issue and what is the best way to create a binary file in constructor
#pragma once
#include <iostream>
#include <fstream>
#include <cstring>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
struct Item
{
char name[20];
int code;
float price;
int quantity;
Item() { code = 0, price = 0, quantity = 0;
char name1[20] = { 0 }; strcpy_s(name, 20, name1);
}
Item(const char* name, int code, float price, int quantity)
{
strcpy_s(this->name, strlen(name) + 1, name);
this->code = code;
this->price = price;
this->quantity = quantity;
}
friend ostream& operator<<(ostream& os, Item& item)
{
os << "Name: " << item.name << endl;
os << "code: " << item.code << endl;
os << "price: " << item.price << endl;
os << "quantity: " << item.quantity << endl << endl;
return os;
}
bool operator!()
{
return code != 0;
}
};
class Store
{
private:
int size = 100;
fstream file;
string fileName;
public:
Store(string fname);
~Store();
Store& operator+=(Item& myItem);
friend ostream& operator<<(ostream&, Store&);
void sortStore();
};
#include "Store.h"
Store::Store(string fname) : file(fname,ios::binary)
{
Item tmp;
if (!file)
cout << "Error with file" << endl;
for (int i = 0; i < size; i++)
file.write((char*)&tmp, sizeof(Item));
//file.close();
file.open(fname, ios::binary | ios::in | ios::out);
}
Store::~Store()
{
file.close();
}
Store& Store::operator+=(Item& myItem)
{
file.write((char*)&myItem, sizeof(myItem));
return (*this);
}
ostream& operator<<(ostream& out, Store& store)
{
Item tmp;
store.file.seekg(0, ios::beg);
for (int i = 0; i < store.size; i++)
{
store.file.read((char*)&tmp, sizeof(Item));
if (!tmp)
cout << i << ": " << tmp;
}
return out;
}
void Store::sortStore()
{
Item tmp;
vector<Item> items;
file.seekg(0, ios::beg);
while (!file.eof())
{
file.read((char*)&tmp, sizeof(Item));
items.push_back(tmp);
}
sort(items.begin(), items.end(), [](Item& first, Item& second)
{
return first.code < second.code;
});
file.clear();
remove("store.dat");
Store("store.dat");
file.seekp(0, ios::beg);
for (auto it = items.begin(); it < items.end(); it++)
file.write((char*)&(*it), sizeof(Item));
}
int main()
{
Store ourStore("store.dat");
Item apple("apple", 45, 12.2, 10);
Item ananas("ananas", 12, 27, 10);
Item strawberry("strawberry", 1, 24.2, 5);
Item banana("banana",23,14.2, 12);
ourStore.operator+=(apple);
ourStore.operator+=(ananas);
ourStore.operator+=(strawberry);
ourStore.operator+=(banana);
int choice = -1;
while (choice != 0)
{
cout << "1.Sorting, 2 Print" << endl;
switch (choice)
{
case 1:
cout << "Sorting" << endl;
ourStore.sortStore();
case 2:
cout << "Print" << endl;
cout << ourStore << endl;
}
cin >> choice;
}
return 0;
}
The local variable file in Store::Store hides the member variable Store::file.
You want an initializer list:
Store::Store : file(fname, ios::binary)
{
// ...

Saving vector of objects using SDL2

Im learning SDL2 and now im trying to save a game ranking into a .bin file. I have placed the ranking data into a vector. But im unable to save the data. Perhabs it has to do with file size, but im unable to solve that. This is the code that im using now:
class Player {
private:
std::string name, faction, dific;
int points;
public:
Player() {};
virtual ~Player() {};
void addName(std::string s);
void addFacti(std::string s);
void addDific(std::string s);
void addPoint(int p);
std::string getName() const;
std::string getFacti() const;
std::string getDific() const;
int getPoint() const;
bool operator>(const Player& p) const;
};
Player p1; Player p2;//just two examples
//add properties to each object
std::vector<Player>classi;
classi.push_back(p1); classi.push_back(p2);
std::sort(classi.begin(), classi.end(), std::greater<Player>());
//load file
SDL_RWops* rankfile = SDL_RWFromFile("ranking.bin", "r+b");
for (int i = 0; i < classi.size(); ++i) { SDL_RWread(rankfile, &classi[i], sizeof(Player), 1); }
SDL_RWclose(rankfile);
//im able to render the objects
//save file - but it doesnt save anything
rankfile = SDL_RWFromFile("ranking.bin", "w+b");
for (int i = 0; i < classi.size(); ++i) { SDL_RWwrite(rankfile, &classi[i], sizeof(Player), 1); }
SDL_RWclose(rankfile);
Here's an example of how I might serialize a struct containing std::string to/from binary. It doesn't use the SDL functions because I don't use SDL but it wouldn't be difficult to modify if desired.
You may have a different problem since you say your file is empty, and I am concerned that you try and read the file before you write it, but you could try something like this and see if it helps.
#include <iostream>
#include <string>
#include <fstream>
#include <tuple>
template <typename T>
std::ostream &writeBinary(std::ostream &f, T data)
{
return f.write(reinterpret_cast<char *>(&data), sizeof(data));
}
std::ostream &writeBinary(std::ostream &f, const std::string &str)
{
// If file size is a concern you might use a smaller type like uint16_t.
// Just make sure to mirror the change in readBinary.
std::string::size_type sz = str.size();
if (f)
{
f.write(reinterpret_cast<char *>(&sz), sizeof(sz));
}
if (f)
{
f.write(str.data(), str.size());
}
return f;
}
template <typename T>
std::istream &readBinary(std::istream &f, T &data)
{
if (f)
{
f.read(reinterpret_cast<char *>(&data), sizeof(data));
}
return f;
}
std::istream &readBinary(std::istream &f, std::string &str)
{
std::string::size_type sz = 0;
if (f)
{
f.read(reinterpret_cast<char *>(&sz), sizeof(sz));
}
if (f)
{
str.resize(sz);
f.read(str.data(), sz);
}
return f;
}
struct Thing
{
std::string shortString;
int i;
double d;
std::string longString;
Thing()
: i(99)
, d(99.99)
{ }
bool operator==(const Thing &rhs) const
{
return std::tie(shortString, i, d, longString)
== std::tie(rhs.shortString, rhs.i, rhs.d, rhs.longString);
}
bool write(std::ofstream &f)
{
if (!writeBinary(f, shortString))
{
return false;
}
if (!writeBinary(f, i))
{
return false;
}
if (!writeBinary(f, d))
{
return false;
}
if (!writeBinary(f, longString))
{
return false;
}
return true;
}
bool read(std::ifstream &f)
{
if (!readBinary(f, shortString))
{
return false;
}
if (!readBinary(f, i))
{
return false;
}
if (!readBinary(f, d))
{
return false;
}
if (!readBinary(f, longString))
{
return false;
}
return true;
}
};
std::ostream &operator<<(std::ostream &o, const Thing &t)
{
return o << "'" << t.shortString << "'" << ", "
<< t.i << ", " << t.d << ", "
<< "'" << t.longString << "'";
}
int main()
{
Thing t1;
// Shorter string to hopefully fit in any short string optimization buffer in the string.
t1.shortString = "Short";
t1.longString = "Long string that should be long enough to not fit in the SSO buffer.";
t1.i = 42;
t1.d = 42.42;
std::cout << "t1 Before Write: " << t1 << "\n";
std::ofstream out("thing.bin", std::ios::binary);
if (!t1.write(out))
{
std::cout << "Error writing t1!\n";
return -1;
}
out.close();
std::cout << "t1 After Write: " << t1 << "\n";
Thing t2;
std::cout << "t2 Before Read: " << t2 << "\n";
std::ifstream in("thing.bin", std::ios::binary);
if (!t2.read(in))
{
std::cout << "Error reading t2!\n";
return -1;
}
in.close();
std::cout << "t2 After Read: " << t2 << "\n";
std::cout << "t1 == t2: " << std::boolalpha << (t1 == t2) << "\n";
return 0;
}

C++ Read Value from a pointer to struct including the target struct in an array

I am new to c++ and trying to make an atm. It consits of one file reading user data from files and a main file. Everytime I try to read the output of the returned pointer to the array of structs, where the data is stored, I get strange data. I think there is a problem when assigning strings to the first struct, because when I tried with test values (third file) it worked.
Edit:
I can read out integeres from the strcut, but I have problems with strings.
Here is the code
users.cpp (Creates the struct, included in main.cpp)
#include <fstream>
#include <string>
#include <iostream>
#define STRING_ERROR 4294967295
#define MAX_USERS 100000
using namespace std;
struct user
{
int id;
string firstname;
string name;
int age;
int pin;
};
struct user_container{
int size;
user users [MAX_USERS];
};
typedef struct user User;
typedef struct user_container container;
void print_user_vars(User *user){
cout << "Id: " << user->id << "\nFirstname: " << user->firstname << "\nName: " << user->name << "\nAge: " << user->age << "\nPIN: " << user->pin << endl;
}
int get_usercount(string path){
int usercount = 0;
ifstream file;
string line;
file.open(path, ios::binary | ios::in);
while(true){
getline(file , line);
if(file.fail())
break;
if(line.find("}") != STRING_ERROR){
usercount++;
}
}
file.close();
return usercount;
}
container * get_users(string path){
const int usercount = get_usercount(path);
ifstream file;
string line;
User users[usercount];
const char *values[5] = {"id", "firstname", "name", "age", "pin"};
file.open(path, ios::binary | ios::in);
User proto_user;
int user_num = 0;
while(true){
getline(file , line);
if(file.fail())
break;
if(line.find(":") != STRING_ERROR){
for(int i = 0; i < 5; i++){
if(line.find(values[i]) != STRING_ERROR){
string value;
for(int v = 0; v < line.length(); v++){
if(v > line.find_first_of(":")){
value += line[v];
}
}
if(values[i] == "id"){
proto_user.id = stoi(value);
}
else if(values[i] == "firstname"){
proto_user.firstname = value;
}
else if(values[i] == "name"){
proto_user.name = value;
}
else if(values[i] == "age"){
proto_user.age = stoi(value);
}
else if(values[i] == "pin"){
proto_user.pin = stoi(value);
}
break;
}
}
}
else if(line.find("}") != STRING_ERROR){
//print_user_vars(&proto_user);
users[user_num++] = proto_user;
//cout << "Added user at " << user_num << endl;
}
//cout << line << endl;
}
for(int i = 0; i < user_num; i++){
//cout << "\nUSER: " << i + 1 << endl;
//print_user_vars(&users[i]);
}
static container con;
con.size = usercount;
for(int i = 0; i < usercount; i++){
if(i <= MAX_USERS){
// con.users[i] = users[i] didnt work, but this does
con.users[i].firstname = users[i].firstname;
con.users[i].age = users[i].age;
con.users[i].name = users[i].name;
con.users[i].pin = users[i].pin;
con.users[i].id = users[i].id;
}
}
print_user_vars(&con.users[0]);
return &con;
}
main.cpp (Calls the function)
#include <iostream>
#include "includes/users.h"
using namespace std;
int main(void){
string wasd = "w";
int id;
int pin;
cout << "\n Welcome\n\n ID\n>>> ";
cin >> id;
cout << " PIN\n>>> ";
cin >> pin;
container *con = get_users("users");
int size = con->size;
cout << "Age: " << con->users[0].age << ", PIN: " << con->users[0].pin << ", Firstname: " << con->users[0].firstname << ", Name: "
<< con->users[0].name << ", ID: " << con->users[0].id << endl;
//Functionality
return 0;
}
Simpler.cpp (Just like users.cpp, but with test values, included in main.cpp)
#include <fstream>
#include <string>
#include <iostream>
#define STRING_ERROR 4294967295
#define MAX_USERS 100000
using namespace std;
struct user
{
int id;
string firstname;
string name;
int age;
int pin;
};
struct user_container{
int size;
user users [MAX_USERS];
};
typedef struct user User;
typedef struct user_container container;
container * get_users(string path){
const int usercount = 2;
User users[usercount];
users[0].age = 59;
users[0].firstname = "Peter";
users[0].name = "Bremer";
users[0].id = 456878;
users[0].pin = 1234;
users[1].age = 8;
users[1].firstname = "a";
users[1].name = "b";
users[1].id = 456;
users[1].pin = 1111;
static container con;
con.size = usercount;
for(int i = 0; i < usercount; i++){
if(i <= MAX_USERS){
// con.users[i] = users[i] didnt work, but this does
con.users[i].firstname = users[i].firstname;
con.users[i].age = users[i].age;
con.users[i].name = users[i].name;
con.users[i].pin = users[i].pin;
con.users[i].id = users[i].id;
}
}
cout << "Usercount " << usercount << endl;
return &con;
}
int main(void){
container *con = get_users("users");
int size = con->size;
cout << "Age: " << con->users[0].age << ", PIN: " << con->users[0].pin << ", Firstname: " << con->users[0].firstname << ", Name: "
<< con->users[0].name << ", ID: " << con->users[0].id << endl;
return 0;
}
Not really the answer you are looking for:
Avoid using typedef when you don't need it. Just name your struct User, it will be available under that name without writing struct User.
And for your container, just use one of the STL containers. std::vector<User> would be a good start. This also removes the need for MAX_USERS.
struct User
{
int id;
std::string firstname;
std::string name;
int age;
int pin;
};
typedef std::vector<User> container;
With the three interfaces in user.cpp you can now just use
void print_user_vars(const User& user);
int get_usercount(const std::string& path);
container get_users(const std::string& path);
and thus get rid of the static container con; in get_users.
With a std::vector I no longer see a need for the get_usercount function.
And instead of macros go for constants (and remove magic numbers):
auto const STRING_ERROR = std::string::npos;
(Though I don't agree with the name STRING_ERROR. It's more a STRING_NOT_FOUND.)
Cleanup of print_user_vars after signature change:
void print_user_vars(const User& user)
{
std::cout << "Id: " << user.id << "\nFirstname: " << user.firstname
<< "\nName: " << user.name << "\nAge: " << user.age
<< "\nPIN: " << user.pin << std::endl;
}
And getting some inspiration from get_usercount (a method I don't believe you need):
int get_usercount(const std::string& path)
{
int usercount = 0;
std::ifstream file(path, std::ios_base::binary);
std::string line;
while(std::getline(file, line))
{
if(line.find("}") != STRING_ERROR)
{
usercount++;
}
}
return usercount;
}
This line in get_users is NOT C++. (It's part of the C99 standard):
User users[usercount];
And as #bruno points out:
else if(values[i] == "name"){
does not work. Consider
else if(std::strcmp(values[i], "name") == 0){

Error while Pushing Elements from a std::string onto a Stack of String Type

I get this error while trying to loop through a string to push each element onto a stack of string type s1 in my isPalindrome() function.
no instance of overloaded function "std::stack<_Ty, _Container>::push
[with _Ty=std::string, _Container=std::deque>]" matches the argument list
When I assign, the element that is at the top of the stack to a string variable an error pops up:
'std::stack>>::top':
non-standard syntax; use '&' to create a pointer to member
Why does it mention std::deque?
#include <iostream>
#include <string>
#include <stack>
#include <algorithm>
class Palindrome
{
public:
Palindrome();
void inputString();
std::string convert2lower();
bool isPalindrome();
private:
std::string userstring;
std::stack<std::string> s1;
};
Palindrome::Palindrome()
{}
void Palindrome::inputString()
{
std::cout << "Enter a string: ";
std::getline(std::cin,userstring);
}
std::string Palindrome::convert2lower()
{
userstring.erase(remove(userstring.begin(), userstring.end(), ' '), userstring.end());
userstring.erase(std::remove_if(userstring.begin(), userstring.end(), ispunct), userstring.end());
transform(userstring.begin(), userstring.end(), userstring.begin(), tolower);
return userstring;
}
bool Palindrome::isPalindrome()
{
size_t n = userstring.size();
for (size_t i = 0; i < n; ++i)
{
s1.push(userstring[i]);
}
std::string reversed;
for (size_t i = 0; i < n; ++i)
{
std::string temp = s1.top;
reversed.insert(i,temp);
s1.pop();
}
if (reversed == userstring)
{
return true;
}
return false;
}
int main()
{
Palindrome p1;
p1.inputString();
std::cout << "\nCalling convert2lower(): " << std::endl;
std::cout << "The new string is " << p1.convert2lower() << std::endl;
std::cout << "\nCalling isPalindrome(): " << std::endl;
if (!p1.isPalindrome())
{
std::cout << "String is NOT a Palindrome!" << std::endl;
}
else
{
std::cout << "String is a Palindrome!" << std::endl;
}
}
Here is your code fixed with the absolute minimum changes...
#include <iostream>
#include <string>
#include <stack>
#include <algorithm>
class Palindrome
{
public:
Palindrome();
void inputString();
std::string convert2lower();
bool isPalindrome();
private:
std::string userstring;
std::stack<char> s1;
};
Palindrome::Palindrome()
{}
void Palindrome::inputString()
{
std::cout << "Enter a string: ";
std::getline(std::cin, userstring);
}
std::string Palindrome::convert2lower()
{
userstring.erase(remove(userstring.begin(), userstring.end(), ' '), userstring.end());
userstring.erase(std::remove_if(userstring.begin(), userstring.end(), ispunct), userstring.end());
transform(userstring.begin(), userstring.end(), userstring.begin(), tolower);
return userstring;
}
bool Palindrome::isPalindrome()
{
size_t n = userstring.size();
for (size_t i = 0; i < n; ++i)
{
s1.push(userstring[i]);
}
std::string reversed;
for (size_t i = 0; i < n; ++i)
{
char temp = s1.top();
reversed.insert(i, &temp, 1);
s1.pop();
}
if (reversed == userstring)
{
return true;
}
return false;
}
int main()
{
Palindrome p1;
p1.inputString();
std::cout << "\nCalling convert2lower(): " << std::endl;
std::cout << "The new string is " << p1.convert2lower() << std::endl;
std::cout << "\nCalling isPalindrome(): " << std::endl;
if (!p1.isPalindrome())
{
std::cout << "String is NOT a Palindrome!" << std::endl;
}
else
{
std::cout << "String is a Palindrome!" << std::endl;
}
}
Here are answers to your questions:
no instance of...this is caused by using string instead of char as the stack type.
non standard syntax...this is because you left the () off of pop.
deque is mentioned because stack is a specialization of deque.

C++: transfer a vector into a subprogram

In my example there are three similar vectors which I would like to print.
Could you help me understand how to transfer a vector into a subprogram so that not to
repeat myself?
#include "stdafx.h";
#include <vector>;
#include <iostream>
#include <algorithm>
#include <iterator>
using namespace std;
struct SPoint
{
int X;
int Y;
};
vector<SPoint> points;
vector<SPoint> selected;
vector<SPoint> cleared;
void print_points()
{
cout << "Points: "<< endl;
for (int i = 0; i < points.size(); i++)
{
cout << '('<<points[i].X <<',' <<points[i].Y <<')'<< endl;
}
cout << endl;
}
void print_selected()
{
cout << "Selected: "<< endl;
for (int i = 0; i < selected.size(); i++)
{
cout << '('<<selected[i].X <<',' <<selected[i].Y <<')'<< endl;
}
cout << endl;
}
void print_cleared()
{
cout << "Cleared: "<< endl;
for (int i = 0; i < cleared.size(); i++)
{
cout << '('<<cleared[i].X <<',' <<cleared[i].Y <<')'<< endl;
}
cout << endl;
}
int main ()
{
SPoint temp = {0, 0};
for (int i = 0; i < 11;i++)
{
temp.X = i;
temp.Y = i;
points.push_back(temp);
}
for (int i = 5; i< 11;i++)
{
temp.X = i;
temp.Y = i;
points.push_back(temp);
}
print_points();
print_selected();
print_cleared();
system ("pause");
return 0;
}
You could do something like this:
void
print(const std::vector<SPoint>& vect, const std::string& message)
{
std::cout << message << ":" << std::endl;
for (int i = 0, size = vect.size(); i < size; ++i)
std::cout << vect[i].X << ":" << vector[i].Y << " ";
std::endl;
}
print(points, "Points");
print(points, "Selected");
print(points, "Cleared");
Good luck
To pass a vector as an argument to a function you do something like this:
void func(const vector<SPoint>& points) {
... do stuff
}
Then you call the function in you code like this:
...some stuff
vector<SPoint> a;
func(a);
Just use a const reference to a vector and pass it to the function:
void print(const vector<SPoint> &data) const {
}
...
print(points);
Here is a full C++ style approach:
struct SPoint
{
int X;
int Y;
};
std::ostream& operator <<( std::ostream& stream, SPoint const& point )
{
stream << '(' << point.X << ',' <<point.Y << ')';
return stream;
}
void print_vector( std::ostream& stream, std::vector< SPoint > const& vector )
{
std::copy(
points.begin(), points.end()
, std::ostream_iterator< SPoint >( std::cout, '\n' )
);
}
and then:
print_vector( std::cout, points );
print_vector( std::cout, selected );
print_vector( std::cout, cleared );