Inserting a node (containing str and bool values) into an array C++ - c++11

Anyways, I am working on a trivia game for a school project. I am reading in questions and answers from a CSV file that will be displayed to the user through the terminal. But I am having trouble inserting my nodes into the array.
My tactic here is to read in question first then read the correct answer in second, and the last three answers are the incorrect answers which will be shuffled later.
ifstream questionFile("questions.csv");
getline(questionFile, header);
if(questionFile.is_open())
{
string line;
while(getline(questionFile, line))
{
stringstream ss;
ss << line;
string item;
getline(ss, item, ',');
question = item;
getline(ss, item, ',');
answer1 = item;
getline(ss, item, ',');
answer2 = item;
getline(ss, item, ',');
answer3 = item;
getline(ss, item, ',');
answer4 = item;
g.insertAndShuffle(question, answer1, answer2, answer3, answer4);
}
}
questionFile.close()
I then pass these values into a function which will assign the answer strings into a node which will also hold a boolean value (correct answer holds true). Here's my issue I think... I then pass pointers to these nodes along with the question into an array[5] so that I can shuffle array[1]-[5] to randomize the answers.
Here is the function:
string* Game::insertAndShuffle(string question, string answer1, string answer2, string answer3, string answer4)
{
Answer *nodeC = new Answer(answer1, true);
Answer *node1 = new Answer(answer2, false);
Answer *node2 = new Answer(answer3, false);
Answer *node3 = new Answer(answer4, false);
quizArray[0] = question;
quizArray[1] = nodeC;
quizArray[2] = node1;
quizArray[3] = node2;
quizArray[4] = node3;
random_shuffle(&quizArray[1], &quizArray[5]);
return quizArray;
}
The class containing the function:
class Game
{
public:
bool isAsked;
string quizArray[5];
int questionNum = 1;
bool letsPlay = false;
string* insertAndShuffle(string question, string answer1, string answer2, string answer3, string answer4);
string askQuestions(string* quizArray);
bool startGame(bool letsPlay, string playerName);
// bool checkAnswer(string playerResponse, string answer1);
private:
Answer *nodeC;
Answer *node1;
Answer *node2;
Answer *node3;
};
And the struct being used for answers:
struct Answer
{
string answer;
bool isCorrect;
Answer();
Answer(string item, bool value)
{
answer = item;
isCorrect = value;
}
};
There seems to be a problem when I am trying to access the the pointer to the struct through the class function. Here is my error:
./project.hpp:22:2: error: unknown type name 'Answer'
Answer *nodeC;
^
./project.hpp:23:2: error: unknown type name 'Answer'
Answer *node1;
^
./project.hpp:24:2: error: unknown type name 'Answer'
Answer *node2;
^
./project.hpp:25:2: error: unknown type name 'Answer'
Answer *node3;
^
./project.hpp:43:2: error: C++ requires a type specifier for all declarations
CorrectAnswer();
^
./project.hpp:44:2: error: C++ requires a type specifier for all declarations
CorrectAnswer(string item, bool value)
^
In file included from projectMain.cpp:8:
./project.cpp:85:22: error: no matching constructor for initialization of 'Answer'
Answer *nodeC = new Answer(answer1, true);

Related

How do you perfectly hash a union of a possibly unicode char with a 32-bit integer?

I've never really had the need to create hash function before but right now it seems like the best solution for this.
I haven't tried anything, but I guess what I would try first is to hash take the unicode integer as the least significant 32-bits of a long. Then in the most significant 32-bits, store the integer.
struct Symbol
{
private:
enum Type {
Terminal,
Variable,
}
union {
char m_term;
int m_var;
}
Type m_type;
public:
this(char term) {
m_type = Type.Terminal;
m_term = term;
}
this(int var) {
m_type = Type.Variable;
m_var = var;
}
}
Symbol is the struct I'd like to hash. It contains a union which we should hash to achieve this. Was just wondering if my approach above is correct.
Thanks to commenters.
bool opEquals(Symbol sym) const {
if (m_type == Type.Terminal)
return m_term == sym.m_term;
else
return m_var == sym.m_var;
}
ulong toHash() {
ulong bit = m_type;
ulong key;
if (m_type == Type.Terminal)
key = cast(ulong) m_term;
else
key = m_var;
return bit | (key << 1);
}

C++: std::bind -> std::function

I have several functions which receive the following type:
function<double(int,int,array2D<vector<double *>>*)>
Where array2D is a custom type. Further, I have a function which takes the following as arguments:
double ising_step_distribution(double temp,int i,int j,array2D<vector<double *>>* model)
Right now, in order to bind the first value, temp, and return a functor which has the correct signature, I am writing:
double temp = some_value;
function<double(int,int,array2D<vector<double *>>*)> step_func =
[temp](int i, int j, array2D<vector<double *>>* model){
return ising_step_distribution(temp,i,j,model);
}
}
And this works. However, the following breaks:
auto step_func =
[temp](int i, int j, array2D<vector<double *>>* model){
return ising_step_distribution(temp,i,j,model);
}
}
With the following error:
candidate template ignored:
could not match
'function<double (int, int, array2D<vector<type-parameter-0-0 *, allocator<type-parameter-0-0 *> > > *)>'
against
'(lambda at /Users/cdonlan/home/mcmc/main.cpp:200:25)'
void mix_2D_model(function<double(int,int,array2D<vector<T*>>*)> step_distribution_func,...
And so, the code clump is ugly, obfuscative and repetitive (because I am making many of these).
I have been reading the documentation, and I understand that I should be able to write:
function<double(int,int,array2D<vector<double *>>*)> step_func =
bind(ising_step_distribution,temp,_1,_2,_3);
However, the only examples I have seen are for functions of type function<void()>. This one fails with an error:
// cannot cast a bind of type
// double(&)(double,int,int,array2D<vector<double *>>*)
// as function<double(int,int,...)
How do I get a visually clean bind and cast?
How do I get a visually clean bind and cast?
One way is:
using F = function<double(int,int,array2D<vector<double *>>*)>;
auto step_func =
[temp](int i, int j, array2D<vector<double *>>* model){
return ising_step_distribution(temp,i,j,model);
}
}
And then:
auto step_func_2 = F(step_func);
mix_2D_model(step_func_2, ...);
Or:
mix_2D_model(F(step_func), ...);

Pointer not printing char[] array

I'm writing some code to take in a string, turn it into a char array and then print back to the user (before passing to another function).
Currently the code works up to dat.toCharArray(DatTim,datsize); however, the pointer does not seem to be working as the wile loop never fires
String input = "Test String for Foo";
InputParse(input);
void InputParse (String dat)
//Write Data
datsize = dat.length()+1;
const char DatTim[datsize];
dat.toCharArray(DatTim,datsize);
//Debug print back
for(int i=0;i<datsize;i++)
{
Serial.write(DatTim[i]);
}
Serial.println();
//Debug pointer print back
const char *b;
b=*DatTim;
while (*b)
{
Serial.print(*b);
b++;
}
Foo(*DatTim);
I can't figure out the difference between what I have above vs the template code provided by Majenko
void PrintString(const char *str)
{
const char *p;
p = str;
while (*p)
{
Serial.print(*p);
p++;
}
}
The expression *DatTim is the same as DatTim[0], i.e. it gets the first character in the array and then assigns it to the pointer b (something the compiler should have warned you about).
Arrays naturally decays to pointers to their first element, that is DatTim is equal to &DatTim[0].
The simple solution is to simply do
const char *b = DatTim;

C++ Ensuring that user input value is int only [duplicate]

This question already has answers here:
How to test whether stringstream operator>> has parsed a bad type and skip it
(5 answers)
Closed 8 years ago.
I am a little new to C++ and would really appreciate any input or suggestions! So with our intro course projects I have been looking for a way to ensure that when the prog. is asking for int values it correctly responds! That is it states its invalid in cases of both a double as well as string being entered! So if cin >> intVariable ... intVariable will not accept cin entry of "abdf" or 20.01.
So to achieve this I wrote the following function...It works but I am looking for your thoughts on how this process can be further improved!
void getIntegerOnly(int& intVariable, string coutStatement)
{
bool isInteger; // Check if value entered by user is int form or not
string tmpValue; // Variable to store temp value enetered by user
cout << coutStatement; // Output the msg for the cin statement
do
{
cin >> tmpValue; // Ask user to input their value
try // Use try to catch any exception caused by what user enetered
{
/* Ex. if user enters 20.01 then the if statement converts the
string to a form of int anf float to compare. that is int value
will be 20 and float will be 20.01. And if values do not match
then user input is not integer else it is. Keep looping untill
user enters a proper int value. Exception is 20 = 20.00 */
if (stoi(tmpValue) != stof(tmpValue))
{
isInteger = false; // Set to false!
clear_response(); // Clear response to state invalid
}
else
{
isInteger = true; //Set to true!
clear_cin(); // Clear cin to ignore all text and space in cin!
}
}
catch (...) // If the exception is trigured!
{
isInteger = false; // Set to false!
clear_response(); // Clear response to state invalid
}
} while (!isInteger); //Request user to input untill int clause met
//Store the int value to the variable passed by reference
intVariable = stoi(tmpValue);
}
This is simply an example of getting users age and age is greater than zero when running a Win32 console based application! Thank you for the feedback :)
One way would be something like the following:
std::string str;
std::cin >> str;
bool are_digits = std::all_of(
str.begin(), str.end(),
[](char c) { return isdigit(static_cast<unsigned char>(c)); }
);
return are_digits ? std::stoi(str) : throw std::invalid_argument{"Invalid input"};
and catch the exceptions on the calling side (stoi can also throw std::out_of_range).
You can leverage the second parameter of stoi().
string tmpValue;
size_t readChars;
stoi(tmpValue, &readChars);
if(readChars == tmpValue.length())
{
// input was integer
}
EDIT: this will not work for strings containing "." (for example integers passed in scientific notation).
This is not my work, but the answer to this question is what you want. Pass the string to it as a reference. It will return true is your string is an integer.
How do I check if a C++ string is an int?

Strange error when sorting strings with D

I am in the process of learning D (I decided it would be a better beginner friendly language than C++) and I decided to give myself the excercise of implementing a general quicksort in D. My program runs fine when sorting integers but it doesn't compile and throws a strange error when sorting strings.
Here is my code:
import std.stdio, std.algorithm;
T[] quickSort(T)(T[] input) {
if (input.length <= 1) {return input;}
ulong i = input.length/2;
auto pivot = input[i];
input = input.remove(i);
T[] lesser = [];
T[] greater = [];
foreach (x; input) {
if (x<=pivot)
{
lesser ~= x;
}
else
{
greater ~=x;
}
}
return (quickSort(lesser) ~ cast(T)pivot ~ quickSort(greater));
}
void main() {
//Sort integers, this works fine
//writeln(quickSort([1,4,3,2,5]));
//Sort string, throws weird error
writeln(quickSort("oidfaosnuidafpsbufiadsb"));
}
When I run it on a string it throws this error:
/usr/share/dmd/src/phobos/std/algorithm.d(7397): Error: template std.algorithm.move does not match any function template declaration. Candidates are:
/usr/share/dmd/src/phobos/std/algorithm.d(1537): std.algorithm.move(T)(ref T source, ref T target)
/usr/share/dmd/src/phobos/std/algorithm.d(1630): std.algorithm.move(T)(ref T source)
/usr/share/dmd/src/phobos/std/algorithm.d(1537): Error: template std.algorithm.move cannot deduce template function from argument types !()(dchar, dchar)
/usr/share/dmd/src/phobos/std/algorithm.d(7405): Error: template std.algorithm.moveAll does not match any function template declaration. Candidates are:
/usr/share/dmd/src/phobos/std/algorithm.d(1786): std.algorithm.moveAll(Range1, Range2)(Range1 src, Range2 tgt) if (isInputRange!(Range1) && isInputRange!(Range2) && is(typeof(move(src.front, tgt.front))))
/usr/share/dmd/src/phobos/std/algorithm.d(7405): Error: template std.algorithm.moveAll(Range1, Range2)(Range1 src, Range2 tgt) if (isInputRange!(Range1) && isInputRange!(Range2) && is(typeof(move(src.front, tgt.front)))) cannot deduce template function from argument types !()(string, string)
helloworld.d(9): Error: template instance std.algorithm.remove!(cast(SwapStrategy)2, string, ulong) error instantiating
helloworld.d(31): instantiated from here: quickSort!(immutable(char))
helloworld.d(31): Error: template instance helloworld.quickSort!(immutable(char)) error instantiating
the problem is that strings are immutable so remove won't work (as it manipulates the string)
you can fix that by not removing and not inserting the pivot in the concat:
auto pivot = input[i];
//input = input.remove(i); //<- remove this line
T[] lesser = [];
//...
return (quickSort(lesser) ~ quickSort(greater)); //<- remove cast(T)pivot ~
or by passing in a dup:
writeln(quickSort("oidfaosnuidafpsbufiadsb".dup));
You have to put a "d" behind the string to make it utf-32, otherwise remove won't accept it.
writeln(quickSort("oidfaosnuidafpsbufiadsb"d.dup));

Resources