I am doing a program that is supossed to save information of some classes. I am using ofstream and ifstream. Ofstream seems to be working properly as it creates one line for each attribute. This is the following .txt created by my ofstream function:
Audifonos
4.2
200
Water
10.4
12
Eggs
5.8
24
Attributes are declared as:
string name;
int cantidad;
float precio;
This is my ofstream function.
ofstream archivo("productos.txt", ios::out);
if(archivo.is_open())
{
for(size_t i(0); i<arreglo.size(); i++)
{
Producto &p = arreglo[i];
archivo << p.getName() <<endl;
archivo << p.getPrecio() <<endl;
archivo << p.getCantidad() <<endl;
}
archivo.close();
}
And this is my ifstream function.
ifstream archivo("productos.txt");
if(archivo.is_open())
{
while(!archivo.eof())
{
string linea;
Producto p;
getline(archivo,linea);
p.setName(linea);
getline(archivo, linea);
p.setPrecio(stof(linea));
getline(archivo,linea);
p.setCantidad(stoi(linea));
if(archivo.eof())
{
break;
}
agregarp(p);
}
}
Not a syntax problem, but I get this error when I execute the function while using the program:
terminate called after throwing an instance of 'std::invalid_argument'
what(): stof
Thank you very much, I wonder how to solve it.
Related
I am trying to set seed to the c++ std::default_random_engine:
#include<random>
#include<time.h>
#include<iostream>
using namespace std;
void print_rand();
int main() {
for (int i{0}; i < 20; ++i) {
print_rand();
}
return 0;
}
void print_rand() {
default_random_engine e;
e.seed(time(0));
cout << e() << endl;
}
It seems that the printed numbers are same, how could I set the seed to generate the random number according to the time?
You have to seed only once instead of every time the function is called. Then you will get different values. I will move the functionality to main() to demonstrate this.
#include<random>
#include<time.h>
#include<iostream>
int main() {
std::default_random_engine e;
e.seed(time(0));
for (int i{0}; i < 20; ++i) {
std::cout << e() << std::endl;
}
return 0;
}
See Live Demo
As #P.W. said, you should seed only once. A minimal change in that direction would be using a static variable with the seed given to the constructor:
#include<random>
#include<time.h>
#include<iostream>
void print_rand();
int main() {
for (int i{0}; i < 20; ++i) {
print_rand();
}
return 0;
}
void print_rand() {
static std::default_random_engine e(time(0));
cout << e() << endl;
}
Here is what I am supposed to do.
Here is what I did.(on codeblocks IDE with minGW compiler)
#include <iostream>
using namespace std;
class person
{
private:
string name;
int age;
double height;
double weight;
public:
void set_private_members(string n, int a, double h, double w)
{
name = n;
age = a;
weight = h;
height = w;
}
void print_private_members()
{
cout <<"The name of person is:- "<<name<<"\n The age of person is:- " <<age<<"\n The weight of person is:- "<<weight;
cout <<"\n The height of person is:- "<<height<<endl;
}
};
void modify_person(person);
int main()
{
person p;
p.set_private_members("Ayush",19,165.7,47.2);
cout <<"We are in main function right now \n";
p.print_private_members();
modify_person(p);
cout <<"We are now back in main function \n The values of object passed to modify_person function are as \n";
p.print_private_members();
return 0;
}
void modify_person(person z)
{
cout <<"We are in modify_person function \n Modifying person details... \n";
z.set_private_members("Priyanshi",15,159.1,50.6);
cout <<"The details are now as:- \n";
z.print_private_members();
}
Here is the output to this code
however the expected output is to have priyanshi details in the class object when print_private_members function is called in main() for the last time.
Who is wrong? Me or they? I think if I call modify_person by reference then the expected should come.
After many trials I still do not understand how to properly take advantage of the move semantics in order to not copy the result of the operation and just use the pointer, or std::move, to "exchange" the data pointed to. This will be very usefull to speed-up more complicated functions like f(g(),h(i(l,m),n(),p(q()))
The objective is to have:
t3={2,4,6};
t1={}; // empty
While executing the code below the output is:
t3={2,4,6};
t1={1,2,3};
Code:
namespace MTensor {
typedef std::vector<double> Tensor1DType;
class Tensor1D {
private:
//std::shared_ptr<Tensor1DType> data = std::make_shared<Tensor1DType>();
Tensor1DType * data = new Tensor1DType;
public:
Tensor1D() {
};
Tensor1D(const Tensor1D& other) {
for(int i=0;i<other.data->size();i++) {
data->push_back(other.data->at(i));
}
}
Tensor1D(Tensor1D&& other) : data(std::move(other.data)) {
other.data = nullptr;
}
~Tensor1D() {
delete data;
};
int size() {
return data->size();
};
void insert(double value) {
data->push_back(value);
}
void insert(const std::initializer_list<double>& valuesList) {
for(auto value : valuesList) {
data->push_back(value);
}
}
double operator() (int i) {
if(i>data->size()) {
std::cout << "index must be within vector dimension" << std::endl;
exit(1);
}
return data->at(i);
}
Tensor1D& operator=(Tensor1D&& other) {
if (this == &other){
return *this;
}
data = other.data;
other.data = nullptr;
return *this;
}
void printTensor(Tensor1DType info) {
for(int i=0;i<info.size();i++) {
std::cout << info.at(i) << "," << std::endl;
}
}
void printTensor() {
for(int i=0;i<data->size();i++) {
std::cout << data->at(i) << "," << std::endl;
}
}
};
} // end of namespace MTensor
In file main.cpp:
MTensor::Tensor1D scalarProduct1D(MTensor::Tensor1D t1, double scalar) {
MTensor::Tensor1D tensor;
for(int i=0;i<t1.size();++i) {
tensor.insert(t1(i) * scalar);
}
//return std::move(tensor);
return tensor;
}
int main() {
MTensor::Tensor1D t1;
t1.insert({1,2,3});
std::cout << "t1:" << std::endl;
t1.printTensor();
MTensor::Tensor1D t3(scalarProduct1D(t1,2));
std::cout << "t3:" << std::endl;
t3.printTensor();
std::cout << "t1:" << std::endl;
t1.printTensor();
return 0;
}
Your use of new is a red flag, especially on a std::vector.
std::vectors support move semantics natively. They are a memory management class. Manual memory management of a memory management class is a BIG red flag.
Follow the rule of 0. =default your move constructor, move assignment, copy constructor, destructor and copy assignment. Remove the * from the vector. Don't allocate it. Replace data-> with data.
The second thing you should do is change:
MTensor::Tensor1D scalarProduct1D(MTensor::Tensor1D t1, double scalar) {
As it stands you take the first argument by value. That is great.
But once you take it by value, you should reuse it! Return t1 instead of creating a new temporary and returning it.
For that to be efficient, you will want to have a way to modify a tensor in-place.
void set(int i, double v) {
if(i>data->size()) {
std::cout << "index must be within vector dimension" << std::endl;
exit(1);
}
data.at(i) = v;
}
which gives us:
MTensor::Tensor1D scalarProduct1D(MTensor::Tensor1D t1, double scalar) {
for(int i=0;i<t1.size();++i) {
ts.set(i, t1(i) * scalar);
}
return t1; // implicitly moved
}
We are now getting close.
The final thing you have to do is this:
MTensor::Tensor1D t3(scalarProduct1D(std::move(t1),2));
to move the t1 into the scalarProduct1D.
A final problem with your code is that you use at and you check bounds. at's purpose is to check bounds. If you use at, don't check bounds (do so with a try/catch). If you check bounds, use [].
End result:
typedef std::vector<double> Tensor1DType;
class Tensor1D {
private:
//std::shared_ptr<Tensor1DType> data = std::make_shared<Tensor1DType>();
Tensor1DType data;
public:
Tensor1D() {};
Tensor1D(const Tensor1D& other)=default;
Tensor1D(Tensor1D&& other)=default;
~Tensor1D()=default;
Tensor1D& operator=(Tensor1D&& other)=default;
Tensor1D& operator=(Tensor1D const& other)=default;
Tensor1D(const std::initializer_list<double>& valuesList) {
insert(valuesList);
}
int size() const {
return data.size();
};
void insert(double value) {
data.push_back(value);
}
void insert(const std::initializer_list<double>& valuesList) {
data.insert( data.end(), valuesList.begin(), valuesList.end() );
}
double operator() (int i) const {
if(i>data.size()) {
std::cout << "index must be within vector dimension" << std::endl;
exit(1);
}
return data[i];
}
void set(int i, double v) {
if(i>data->size()) {
std::cout << "index must be within vector dimension" << std::endl;
exit(1);
}
data.at(i) = v;
}
static void printTensor(Tensor1DType const& info) {
for(double e : info) {
std::cout << e << "," << std::endl;
}
}
void printTensor() const {
printTensor(data);
}
};
MTensor::Tensor1D scalarProduct1D(MTensor::Tensor1D t1, double scalar) {
for(int i=0;i<t1.size();++i) {
t1.set(i, t1(i) * scalar);
}
return t1;
}
int main() {
MTensor::Tensor1D t1 = {1,2,3};
std::cout << "t1:" << std::endl;
t1.printTensor();
MTensor::Tensor1D t3(scalarProduct1D(std::move(t1),2));
std::cout << "t3:" << std::endl;
t3.printTensor();
std::cout << "t1:" << std::endl;
t1.printTensor();
return 0;
}
with a few other minor fixes (like using range-for, DRY, etc).
You need to move t1 when calling scalarProduct1D, otherwise you'll make a copy:
MTensor::Tensor1D t3(scalarProduct1D(std::move(t1),2));
You need to explicitly use std::move because t1 is an lvalue expression.
Note that you'll have to fix your printing functions to avoid dereferencing nullptr if you want accessing the moved-from object to be a valid operation. I instead suggest to avoid making method invocation on moved-from objects valid as it requires additional checks and doesn't follow the idea of "this object has been moved, now it's in an invalid state".
live wandbox example
I have the following code below, where I am trying to store my kernel that I compiled into a variable functor that can then be accessed later. Unfortunately, when I declare auto kernelTest in the struct, it throws an error saying that "non-static member declared as auto". What does cl::make_kernel actually return, and how can I store it as a private variable?
struct OCLData
{
cl::Device device;
cl::Context context;
cl::CommandQueue queue;
cl::Program program;
auto kernelTest; (PROBLEM)
const char *kernelTestSource = MULTILINE(
__kernel void kernelTest(const int N, __global float* A, __global float* B, __global float* C)
{
int i = get_global_id(0);
int j = get_global_id(1);
}
);
OCLData(){
try{
// Set Device
cl_uint deviceIndex = 0;
std::vector<cl::Device> devices;
unsigned numDevices = getDeviceList(devices);
if (deviceIndex >= numDevices)
{
std::cout << "Invalid device index (try '--list')\n";
return;
}
this->device = devices[deviceIndex];
// Set Context and Queue
std::vector<cl::Device> chosen_device;
chosen_device.push_back(device);
this->context = cl::Context(chosen_device);
this->queue = cl::CommandQueue(context, device);
// Print Device Name
std::string name;
getDeviceName(this->device, name);
std::cout << "\nUsing OpenCL device: " << name << "\n";
// Compile GPU Code
this->program = cl::Program(this->context, this->kernelTestSource, true);
//auto kernel = cl::make_kernel<int, cl::Buffer, cl::Buffer, cl::Buffer>(this->program, "kernelTest");
this->test = cl::make_kernel<int, cl::Buffer, cl::Buffer, cl::Buffer>(this->program, "kernelTest");
//cl::make_kernel<int, cl::Buffer, cl::Buffer, cl::Buffer> naive_mmul(this->program, "kernelTest");
std::cout << "GPU Code Compiled: " << "\n";
} catch (cl::Error err)
{
std::cout << "Exception\n";
std::cerr << "ERROR: "
<< err.what()
<< "("
<< err_code(err.err())
<< ")"
<< std::endl;
}
}
};
cl::make_kernel<int, cl::Buffer, cl::Buffer, cl::Buffer> creates object of that type.
According to C++11 standard auto class member must be also static const which means it must be initialized however there is quite a bit of the code to be executed before cl::make_kerenl<...> could be created.
In this case you can use std::shared_ptr as a member type of the struct:
std::shared_ptr<cl::make_kernel<int, cl::Buffer, cl::Buffer, cl::Buffer>> kernelTest;
and then later in the code:
this->kernelTest.reset(new cl::make_kernel<int, cl::Buffer, cl::Buffer, cl::Buffer>(this->program, "kernelTest"));
I did this as suggested by a friend:
typedef cl::make_kernel <float, cl::Buffer&> kernelTestType;
std::function<kernelTestType::type_> kernelTest;
this->kernelTest = kernelTestType(this->program, "kernelTest");
Looks like this works
I am trying to build up a client to get data via a specific protocol from a server.
I know that my code is not the best - but at the moment I am still experimenting with the basic functions of Boost ASIO.
I want to implement an read from TCP-Function which blocks until a specific amount of bytes have been received.
My Problem:
When I call boost::asio::read or boost::asio::write i geht following error:
error C2039: 'read_some' : is not a member of boost::shared_ptr'
I am working with VS2013 Professional, Boost 1.55.00 (precompiled).
Here is my Code: ( You can find the line by the comment "//HEEERE"
boost::mutex cout_lock;
int main()
{
// creating io_service
boost::shared_ptr<boost::asio::io_service> io_service(new boost::asio::io_service);
// creating work and assigning it to io_service
boost::shared_ptr<boost::asio::io_service::work> work(new boost::asio::io_service::work(*io_service));
// creating strand and assigning it to io_service
boost::shared_ptr<boost::asio::io_service::strand> strand(new boost::asio::io_service::strand(*io_service));
// creating socket
boost::shared_ptr<boost::asio::ip::tcp::socket> socket(new boost::asio::ip::tcp::socket(*io_service));
try {
// creating resolver
boost::asio::ip::tcp::resolver resolver(*io_service);
// creating query
boost::asio::ip::tcp::resolver::query query(IPConfig_str, boost::lexical_cast<std::string>(IPConfig_PortNr));
// creating iterator
boost::asio::ip::tcp::resolver::iterator iterator = resolver.resolve(query);
// creating endpoint
boost::asio::ip::tcp::endpoint endpoint = *iterator;
// connecting synchronously
socket->connect(endpoint);
}
catch(std::exception &ex) {
cout_lock.lock();
std::cout << "[main]:\t" << "Exception:" << ex.what() << std::endl;
cout_lock.unlock();
}
// Create Query
CommandCreator CMDCreator;
Command sendCommand;
CMDCreator.Create_fpga_GetSwVers(&sendCommand);
std::cout << std::endl;
std::cout << "SENT:" << std::endl;
for (int i = 0; i < sendCommand.length; i++)
{
std::cout << std::hex << std::setw(2) << std::setfill('0') << int(sendCommand.buffer[i]) << ", ";
}
std::cout << std::endl;
// Send Query
boost::system::error_code ec;
socket->async_send(boost::asio::buffer(sendCommand.buffer, sendCommand.length), boost::asio::transfer_all());
Sleep(300); // sleep 100 ms (at least 85 <- not stable!)
// Receive Answer - Header
Command receiveCommandHeader;
receiveCommandHeader.InitBuffer(4);
// Async
// socket->async_receive(boost::asio::buffer(receiveCommandHeader.buffer, receiveCommandHeader.length), 0, boost::bind(HandleRead, ec));
//HEEERE
boost::asio::read(socket, boost::asio::buffer(receiveCommandHeader.buffer, receiveCommandHeader.length), boost::asio::transfer_all(), ec);
//shutting down
socket->shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec);
socket->close(ec);
io_service->stop();
return 0;
}
class Command
{
friend class CommandCreator; // TODO: is there a better and as simple method as a friend class?
public:
Command() : buffer(0)
{}
virtual ~Command()
{
delete[] buffer;
buffer = 0;
}
void InitBuffer(int const len)
{
this->length = len;
this->buffer = new uint8_t[len];
}
uint8_t* buffer;
int length;
};
Actually the problem is located at this part of boost in the file read.hpp, where async_read_some is called from 'stream_'.
void operator()(const boost::system::error_code& ec,
std::size_t bytes_transferred, int start = 0)
{
std::size_t n = 0;
switch (start_ = start)
{
case 1:
n = this->check_for_completion(ec, total_transferred_);
for (;;)
{
stream_.async_read_some(
boost::asio::buffer(buffer_ + total_transferred_, n),
BOOST_ASIO_MOVE_CAST(read_op)(*this));
return; default:
total_transferred_ += bytes_transferred;
if ((!ec && bytes_transferred == 0)
|| (n = this->check_for_completion(ec, total_transferred_)) == 0
|| total_transferred_ == boost::asio::buffer_size(buffer_))
break;
}
handler_(ec, static_cast<const std::size_t&>(total_transferred_));
}
}
Okey, I've just found the problem.
// creating socket
boost::shared_ptr<boost::asio::ip::tcp::socket> socket(new boost::asio::ip::tcp::socket(*io_service));
I created the socket as a pointer but all the interfaces of read, read_some and other boost-library functions require the object. Therefore adding the dereferencing operator did it:
boost::asio::async_read(*socket, boost::asio::buffer(receiveCommandHeader.buffer, receiveCommandHeader.length),
boost::asio::transfer_all(), boost::bind(HandleRead, ec));