I am attempting to make a program where people put in their preferences file what they would want to do for that week. I made a huge if else statement and need help with my else statement. My else statement is fair to the users/members as their list is randomly picked and the file is created. However, the else statement creates the file, but does not write any of the roles to it. Here is the code :
else {
string positions[23] =
{ "Day_Clean" "Dinner_Cook" "Dinner_Cook" "Dinner_Clean" "Dinner_Clean" "HEB_Shop" "Costco_Shop" "Silver_Fridge" "Stove_Micowave" "Appliance_Clean" "LH_Bathrooms" "Laundry_Room" "Upstairs_Commons" "Bikeroom_Entrance_Stairs" "Little_House_Commons" "Porch_Grounds" "Recycling" "Gardening" "Condi_Fridge_Personal_Fridge" "Freezer" "Downstairs_Bathroom_1" "Downstairs_Bathroom_2" "Upstairs_Bathroom" "Big_House_Hallways" };
ofstream randomPrefs;
randomPrefs.open(foo);
int randomPrefloopcount;
do {
int randomPrefs1 = rand() % 25;
randomPrefs << positions[randomPrefs1] << "\n";
randomPrefloopcount++;
} while(randomPrefloopcount <= 24);
randomPrefs.close();
The files are created, but they are all blank. Please help!
As stated by Sam Varshavchik your problem lies between the number of elements in your array and your loop.
Let's suppose your values never change, there is a safer way to declare and use an array like this in c++11.
#include <array>
#include <iostream>
int main()
{
constexpr std::size_t kArraySize{ 3 };
constexpr std::array<const char *, kArraySize> kArray {
"hehe"
, "hehe"
// , "hehe" // this one would work since there is 3 elements defined
// , "hehe" // this one would fail to compile
};
for (auto element : kArray)
{
if (element != nullptr)
{ std::cout << "element: " << element << std::endl; }
else
{ std::cout << "element is null" << std::endl; }
}
}
std::array ensures that values not defined by user will be zero-initialized, in this case it means that they will be nullptr'ed.
Specified in C++11 §8.5/8:
To value-initialize an object of type T means:
— if T is a (possibly cv-qualified) class type without a user-provided
or deleted default constructor, then the object is zero-initialized …,
and if T has a non-trivial default constructor, the object is
default-initialized;
Quote stolen from this post.
Edit, applied to your code it will look like this:
else {
constexpr std::size_t kArraySize{ 23 };
constexpr std::array<const char *, kArraySize> kPositions { "Day_Clean", "Dinner_Cook", "Dinner_Cook", "Dinner_Clean", "Dinner_Clean", "HEB_Shop", "Costco_Shop", "Silver_Fridge", "Stove_Micowave", "Appliance_Clean", "LH_Bathrooms", "Laundry_Room", "Upstairs_Commons", "Bikeroom_Entrance_Stairs", "Little_House_Commons", "Porch_Grounds", "Recycling", "Gardening", "Condi_Fridge_Personal_Fridge", "Freezer", "Downstairs_Bathroom_1", "Downstairs_Bathroom_2", "Upstairs_Bathroom", "Big_House_Hallways" };
ofstream randomPrefs;
randomPrefs.open(foo);
std::size_t maxRandomLoop { 25 };
for (std::size_t i = 0 ; i < maxRandomLoop ; ++i)
{
int randomPrefs1 = rand() % kArraySize;
if (kPositions[randomPrefs1] != nullptr)
{ randomPrefs << kPositions[randomPrefs1] << "\n"; }
}
randomPrefs.close();
}
Re-edited, you forgot the commas in your array.
A simple program to verify a concept:
#include <iostream>
int main()
{
static const char *tokens[] = {"Tory" "Grant"};
static const char *mythbusters[] = {"Adam", "Jamie"};
// Print out the quantity of elements:
std::cout << "Elements in tokens: " << (sizeof(tokens) / sizeof(tokens[0])) << "\n";
std::cout << "Elements in mythbusters: "
<< (sizeof(mythbusters) / sizeof(mythbusters[0]))
<< "\n";
return 0;
}
This will show you the difference between concatenation of string literals and specifying more than one literal.
Edit: Added '*' before tokens and mythbusters.
Related
Update: the question is why the code below (MWE) works as it is and not as I would expect it to.
For personal convenience, I created the following templated vector const:
// shorthand for loops, etc.
template <size_t N>
const vector<size_t> range = []() {
vector<size_t> res(N);
for (size_t i = 0; i < N; i++) res[i] = i;
cout << "Created range<" << N << ">: [";
for (auto x: res) cout << x << ' ';
cout << ']' << endl;
return res;
}();
So that further, I can write more laconic loops like the following:
for (auto i : range<42>) do_something(i);
However, I realised (after some debugging) that it seems to be not guaranteed that all required instantiations of range<N> are initialised before usage! This is rather counter-intuitive so I think if I am doing something wrong.
More precisely, I have the following MWE:
#include <bits/stdc++.h>
using namespace std;
template <size_t N>
const vector<size_t> range = []() {
cout << "Initialising range<" << N << ">" << endl;
vector<size_t> result(N);
for (size_t i = 0; i < N; i++) result[i] = i;
return result;
}();
template <size_t K>
class Data {
private:
size_t m_code;
public:
size_t get_code() const { return m_code; }
constexpr static size_t cardinality = K + 1;
explicit Data(size_t code);
const static vector<Data> elems;
};
template <size_t K>
const vector<Data<K>> Data<K>::elems = []() {
cout << "Creating Data elements for K=" << K << endl;
vector<Data<K>> xs;
for (size_t i : range<Data<K>::cardinality>) xs.push_back(Data<K>(i));
return xs;
}();
template <size_t K>
Data<K>::Data(size_t code) {
m_code = code;
cout << "At the moment, range<" << K << "> is [";
for (auto k : range<K>)
cout << k << ' '; // <<< Shouldn't range<K> be already initialised here?..
cout << "] (len=" << range<K>.size() << ")" << endl;
}
int main() {
cout << ">>> Inside main()" << endl;
constexpr size_t K = 2;
cout << "Data elements:" << endl;
for (const auto &X : Data<K>::elems) {
cout << "Element Data(" << X.get_code() << ")" << endl;
}
cout << "Now, range<" << K << "> is [";
for (auto k : range<K>) cout << k << ' ';
cout << "] (len=" << range<K>.size() << ")" << endl;
}
This produces the following output:
Initialising range<3>
Creating Data elements for K=2
At the moment, range<2> is [] (len=0)
At the moment, range<2> is [] (len=0)
At the moment, range<2> is [] (len=0)
Initialising range<2>
>>> Inside main()
Data elements:
Element Data(0)
Element Data(1)
Element Data(2)
Now, range<2> is [0 1 ] (len=2)
I don't really understand why it is working as it is. I mean, I would expect a const vector (or any vector!) to be initialised before it is used and thus range<2> to be of length two any time I use it in the code.
The dynamic initialization of non-local static storage duration variables resulting from (non-explicit) template specializations is unordered, i.e. sequenced indeterminately, meaning that the order in which the initializations happen is unspecified. It does not take into account either dependencies between the variables, or order of definition, or order of instantiation.
Therefore your program has undefined behavior, since Data<2>::elems, instantiated from the use in main, has unordered dynamic initialization and uses range<2> and range<3>, both of which also have unordered dynamic initialization. Because it is unspecified whether the former or the latter are initialized first, it is possible that you access range<2> or range<3> before their initializations have begun, causing undefined behavior.
This can be resolved by using std::array instead of std::vector for range and in its initializer (and removing the cout statements in the initializer), so that the initializer becomes a constant expression. Then range<K> will not have dynamic initialization, but constant initialization, which is always performed before any dynamic initialization, i.e. before Data<K>::elems will use it.
In addition you should then declare range as constexpr to make sure that the initializer is indeed a constant expression. Otherwise you might still get dynamic initialization and the undefined behavior without warning, for example when you make a change that accidentally causes the initializer not to be a constant expression anymore.
I'm trying to use boost to create a multidimensional array and I want said array to be a member of some class.
However I find two problems with it:
1 - I need to declare the size of the array with
boost::extents[2][2]
Everytime I want to use the array. Otherwise I get the following error:
a.out: /usr/include/boost/multi_array/base.hpp:136: Referenceboost::detail::multi_array::value_accessor_n<T, NumDims>::access(boost::type<Reference>, boost::detail::multi_array::value_accessor_n<T, NumDims>::index, TPtr, const size_type*, const index*, const index*) const [with Reference = boost::detail::multi_array::sub_array<double, 1ul>; TPtr = double*; T = double; long unsigned int NumDims = 2ul; boost::detail::multi_array::value_accessor_n<T, NumDims>::index = long int; boost::detail::multi_array::multi_array_base::size_type = long unsigned int]: Assertion `size_type(idx - index_bases[0]) < extents[0]' failed.
2 - Ok, maybe this is just part of how multidimensional arrays work in C++ with Boost, I'm going to write my code accepting every function "declares" the array. However, if I do this I find the array is empty.
Here's a snippet of code that reproduces this problem. During the "construction" of the class the array should be filled. However, the line
cout << "Result: " << testing.getArrayMember(0,1) << endl;
outputs "Result: 0".
#include <iostream>
#include "boost/multi_array.hpp"
typedef boost::multi_array<double, 2> dbl_array;
using namespace std;
class TestClass {
public:
dbl_array darray;
TestClass(double x);
void fillArray(double x);
double getArrayMember(int i, int j);
};
TestClass::TestClass(double x) {
dbl_array darray(boost::extents[2][2]);
cout << "Class constructor called" << endl;
fillArray(x);
}
void TestClass::fillArray(double x) {
cout << "Filling array" << endl;
dbl_array darray(boost::extents[2][2]); // Without this line, the code fails at runtime
darray[0][0] = x;
darray[1][0] = 2.0*x;
darray[0][1] = 3.0*x;
darray[1][1] = 4.0*x;
cout << "Array filled" << endl;
}
double TestClass::getArrayMember(int i, int j) {
dbl_array darray(boost::extents[2][2]); // Without this line, the code fails at runtime
return darray[i][j];
}
int main() {
TestClass testing = TestClass(5.0);
// The result is 0 in the end
cout << "Result: " << testing.getArrayMember(0,1) << endl;
return 0;
}
What am I doing wrong here?
Option 1 is to use an initialisation list:
TestClass::TestClass(double x) : darray(boost::extents[2][2]) {
cout << "Class constructor called" << endl;
fillArray(x);
}
Since otherwise the member of the class darray is created using the default constructor and not through your line
dbl_array darray(boost::extents[2][2]);
as you believe.
This is the same answers as given in initialize boost::multi_array in a class
However, I want to add the following bit, which I think it is relevant in this situation:
It might be necessary for you to generate the array after performing some kind of operation in the constructor of your class. You can achieve this using "resize" after the array has been created by the default constructor.
Ie, instead of
TestClass::TestClass(double x) {
dbl_array darray(boost::extents[2][2]);
cout << "Class constructor called" << endl;
fillArray(x);
}
you could have
TestClass::TestClass(double x) {
darray.resize(boost::extents[2][2]);
cout << "Class constructor called" << endl;
fillArray(x);
}
This question already has answers here:
Uninitialized values being initialized?
(7 answers)
Closed 8 years ago.
I'm doing some testing...
Firstly I post my source code
the .h file
class Complex{
private:
int r = 0;//initializer
int i ;
public:
Complex(int , int I = 0);
Complex();
void print();
void set(int, int I = 1);
static void print_count();
static int count;
};
the .cpp file
#include <iostream>
#include "complex.h"
int Complex::count = 1;
Complex::Complex(int R , int I){
r = R;
i = I;
count++;
std::cout << "constructing Complex object...count is " << Complex::count << std::endl;
}
Complex::Complex(){//default constructor
std::cout << "default constructor is called..." << std::endl;
}
void Complex::print(){
std::cout << "r = " << r << ';' << "i = " << i << std::endl;
return;
}
void Complex::set(int R, int I /*= 2*/){//will be "redefaulting", an error
r = R;
i = I;
return;
}
void Complex::print_count(){//static
Complex::count = -1;//jsut for signaling...
std::cout << "count is " << count << std::endl;
return;
}
the main function
#include <iostream>
#include "complex.h"
int main(){
Complex d;//using default constructor
d.print();
/*Complex c(4, 5);*/
Complex c(4);
//c.print();
/*c.set(2, 3)*/
c.print();
c.set(2 );
c.print();
std::cout << "count is " << c.count << std::endl;//c can access member data
c.print_count();
c.count++;//
return 0;
}
consider the Complex object d constructed with default ctor
because the data member r is initialized using with 0, when executing d.print(),
r is expected to be 0
and i isn't, so I expected it to be garbage value
but when I'm testing, one strange thing happens.
if I eliminate this and the following lines of code in the main file:
std::cout << "count is " << c.count << std::endl;//c can access member data
then d.print() will give the value of i as 32767 on my system, which I guess it's a garbage value;
but once that line is added, d.print() just give i's value to 0 on my system.
I don't get it. I hasn't set, modiify or initialize i's value, why should it be 0?
or, it is also a garbage value?
or, calling one of those function corrupts the value of i?
how is the thing run behind the scene here?
thx for helping.
0 is just as garbage value as any other. Don't make the mistake of thinking otherwise.
Formally, reading an uninitialized variable is undefined behavior, so there's no point in wondering about it: just fix it by initializing the variable properly.
I was debugging some code involving pointers to member fields, and i decided to print them out to see their values. I had a function returning a pointer to member:
#include <stdio.h>
struct test {int x, y, z;};
typedef int test::*ptr_to_member;
ptr_to_member select(int what)
{
switch (what) {
case 0: return &test::x;
case 1: return &test::y;
case 2: return &test::z;
default: return NULL;
}
}
I tried using cout:
#include <iostream>
int main()
{
std::cout << select(0) << " and " << select(3) << '\n';
}
I got 1 and 0. I thought the numbers indicated the position of the field inside the struct (that is, 1 is y and 0 is x), but no, the printed value is actually 1 for non-null pointer and 0 for null pointer. I guess this is a standard-compliant behavior (even though it's not helpful) - am i right? In addition, is it possible for a compliant c++ implementation to print always 0 for pointers-to-members? Or even an empty string?
And, finally, how can i print a pointer-to-member in a meaningful manner? I came up with two ugly ways:
printf("%d and %d\n", select(0), select(3)); // not 64-bit-compatible, i guess?
ptr_to_member temp1 = select(0); // have to declare temporary variables
ptr_to_member temp2 = select(3);
std::cout << *(int*)&temp1 << " and " << *(int*)&temp2 << '\n'; // UGLY!
Any better ways?
Pointers to members are not as simple as you may think. Their size changes from compiler to compiler and from class to class depending on whether the class has virtual methods or not and whether it has multiple inheritance or not. Assuming they are int sized is not the right way to go. What you can do is print them in hexadecimal:
void dumpByte(char i_byte)
{
std::cout << std::hex << static_cast<int>((i_byte & 0xf0) >> 4);
std::cout << std::hex << static_cast<int>(i_byte & 0x0f));
} // ()
template <typename T>
void dumpStuff(T* i_pStuff)
{
const char* pStuff = reinterpret_cast<const char*>(i_pStuff);
size_t size = sizeof(T);
while (size)
{
dumpByte(*pStuff);
++pStuff;
--size;
} // while
} // ()
However, I'm not sure how useful that information will be to you since you don't know what is the structure of the pointers and what each byte (or several bytes) mean.
Member pointers aren't ordinary pointers. The overloads you expect for << aren't in fact there.
If you don't mind some type punning, you can hack something up to print the actual values:
int main()
{
ptr_to_member a = select(0), b = select(1);
std::cout << *reinterpret_cast<uint32_t*>(&a) << " and "
<< *reinterpret_cast<uint32_t*>(&b) << " and "
<< sizeof(ptr_to_member) << '\n';
}
You can display the raw values of these pointer-to-members as follows:
#include <iostream>
struct test {int x, y, z;};
typedef int test::*ptr_to_member;
ptr_to_member select(int what)
{
switch (what) {
case 0: return &test::x;
case 1: return &test::y;
case 2: return &test::z;
default: return NULL;
}
}
int main()
{
ptr_to_member x = select(0) ;
ptr_to_member y = select(1) ;
ptr_to_member z = select(2) ;
std::cout << *(void**)&x << ", " << *(void**)&y << ", " << *(void**)&z << std::endl ;
}
You get warnings about breaking strict anti-aliasing rules (see this link), but the result is what you might expect:
0, 0x4, 0x8
Nevertheless, the compiler is free to implement pointer-to-member functionality however it likes, so you can't rely on these values being meaningful.
I think you should use printf to solve this problen
#include <stdio.h>
struct test{int x,y,z;}
int main(int argc, char* argv[])
{
printf("&test::x=%p\n", &test::x);
printf("&test::y=%p\n", &test::y);
printf("&test::z=%p\n", &test::z);
return 0;
}
I have the following functor:
class ComparatorClass {
public:
bool operator () (SimulatedDiskFile * file_1, SimulatedDiskFile * file_2) {
string file_1_name = file_1->getFileName();
string file_2_name = file_2->getFileName();
cout << file_1_name << " and " << file_2_name << ": ";
if (file_1_name < file_2_name) {
cout << "true" << endl;
return true;
}
else {
cout << "false" << endl;
return false;
}
}
};
It is supposed to be a strict weak ordering, and it's this long (could be one line only) for debug purposes.
I'm using this functor as a comparator functor for a stl::set. Problem being, it only inserts the first element. By adding console output to the comparator function, I learned that it's actually comparing the file name to itself every time.
Other relevant lines are:
typedef set<SimulatedDiskFile *, ComparatorClass> FileSet;
and
// (FileSet files_;) <- SimulatedDisk private class member
void SimulatedDisk::addFile(SimulatedDiskFile * file) {
files_.insert(file);
positions_calculated_ = false;
}
EDIT: the code that calls .addFile() is:
current_request = all_requests.begin();
while (current_request != all_requests.end()) {
SimulatedDiskFile temp_file(current_request->getFileName(), current_request->getResponseSize());
disk.addFile(&temp_file);
current_request++;
}
Where all_requests is a list, and class Request is such that:
class Request {
private:
string file_name_;
int response_code_;
int response_size_;
public:
void setFileName(string file_name);
string getFileName();
void setResponseCode(int response_code);
int getResponseCode();
void setResponseSize(int response_size);
int getResponseSize();
};
I wish I could offer my hypotesis as to what's going on, but I actually have no idea. Thanks in advance for any pointers.
There's nothing wrong with the code you've posted, functionally speaking. Here's a complete test program - I've only filled in the blanks, not changing your code at all.
#include <iostream>
#include <string>
#include <set>
using namespace std;
class SimulatedDiskFile
{
public:
string getFileName() { return name; }
SimulatedDiskFile(const string &n)
: name(n) { }
string name;
};
class ComparatorClass {
public:
bool operator () (SimulatedDiskFile * file_1, SimulatedDiskFile * file_2) {
string file_1_name = file_1->getFileName();
string file_2_name = file_2->getFileName();
cout << file_1_name << " and " << file_2_name << ": ";
if (file_1_name < file_2_name) {
cout << "true" << endl;
return true;
}
else {
cout << "false" << endl;
return false;
}
}
};
typedef set<SimulatedDiskFile *, ComparatorClass> FileSet;
int main()
{
FileSet files;
files.insert(new SimulatedDiskFile("a"));
files.insert(new SimulatedDiskFile("z"));
files.insert(new SimulatedDiskFile("m"));
FileSet::iterator f;
for (f = files.begin(); f != files.end(); f++)
cout << (*f)->name << std::endl;
return 0;
}
I get this output:
z and a: false
a and z: true
z and a: false
m and a: false
m and z: true
z and m: false
a and m: true
m and a: false
a
m
z
Note that the set ends up with all three things stored in it, and your comparison logging shows sensible behaviour.
Edit:
Your bug is in these line:
SimulatedDiskFile temp_file(current_request->getFileName(), current_request->getResponseSize());
disk.addFile(&temp_file);
You're taking the address of a local object. Each time around the loop that object is destroyed and the next object is allocated into exactly the same space. So only the final object still exists at the end of the loop and you've added multiple pointers to that same object. Outside the loop, all bets are off because now none of the objects exist.
Either allocate each SimulatedDiskFile with new (like in my test, but then you'll have to figure out when to delete them), or else don't use pointers at all (far easier if it fits the constraints of your problem).
And here is the problem:
SimulatedDiskFile temp_file(current_request->getFileName(),
current_request->getResponseSize());
disk.addFile(&temp_file);
You are adding a pointer to a variable which is immediately destroyed. You need to dynamically create your SDF objects.
urrent_request = all_requests.begin();
while (current_request != all_requests.end()) {
SimulatedDiskFile temp_file(...blah..blah..); ====> pointer to local variable is inserted
disk.addFile(&temp_file);
current_request++;
}
temp_file would go out of scope the moment next iteration in while loop. You need to change the insert code. Create SimulatedDiskFile objects on heap and push otherwise if the objects are smaller then store by value in set.
Agree with #Earwicker. All looks good. Have you had a look inside all_requests? Maybe all the filenames are the same in there and everything else is working fine? (just thinking out loud here)