I have to create the required function template prompt which displays a supplied string and then returns a value of the templated type. Finally, add a line which calls this function with the string "What is the answer? " (note the trailing space) and stores this answer in the misc field of the supplied struct.
I have no idea what I am doing, please help!
#include <string>
#include <iostream>
using std::string;
struct Answers {
string name;
float answer;
int misc;
};
// write template function "prompt" here
**template <class T>
void prompt(string prompt_question, T& answer)
{
prompt_question = "What is the answer? ";
cin >> answer;
misc = answer;
}**
// what should I have written?
int main(int argc, char* argv[])
{
**using namespace std;
Answers info {
prompt<string>("What is your name? "),
prompt<float>(argv[2]),
};**
cout << '\n' << "Who: " << info.name;
cout << '\n' << "Knowledge: " << info .answer;
cout << '\n' << "Wisdom: " << info.misc;
return 0;
}
I feel stupid for not knowing how to solve it, been trying to figure it out since 7 est. Please help
Things between ** are the only things I can edit unfortunately
IMHO, that attempt of OP was not so lucky.
I try to sort it out:
template <class prompt> prompt(string prompt_question)
That's broken. The identifier of function is missing. Or, may be, the return type of function is missing but then the name of the function is the same as the identifier of template parameter.
prompt_question = answer;?
What shall this be good for?
answer is not declared in this scope nor initialized.
Why prompt_question shall be overridden with it?
answer = "What is the answer??
What shall this be good for?
misc = answer;?
What shall this be good for?
misc is not declared in this scope.
My working sample to show how this could look like:
#include <cassert>
#include <iostream>
struct Answers {
std::string name;
float answer;
int misc;
};
template <class T>
void prompt(const std::string &question, T &answer)
{
std::cout << question;
std::cin >> answer;
}
int main()
{
Answers info { };
prompt("Who: ", info.name);
if (!std::cin) { std::cerr << "Input failed!\n"; return -1; }
prompt("Age: ", info.answer);
if (!std::cin) { std::cerr << "Input failed!\n"; return -1; }
std::cout << "\nYou claim to be " << info.name << " with an age of " << info.answer << ".\n";
}
Output:
Who: Just
Age: 34
You claim to be Just with an age of 34.
Live Demo on coliru
After Edit it seems, the OP requires that template parameter is the return type:
#include <cassert>
#include <iostream>
struct Answers {
std::string name;
float answer;
int misc;
};
template <class T>
T prompt(const std::string &question)
{
std::cout << question;
T answer;
std::cin >> answer;
return answer;
}
int main(int argc, char **argv)
{
Answers info {
prompt<std::string>("Who: "),
prompt<float>("Age: ")
};
if (!std::cin) { std::cerr << "Input failed!\n"; return -1; }
std::cout << "\nYou claim to be " << info.name << " with an age of " << info.answer << ".\n";
}
Output:
Who: Just
Age: 34
You claim to be Just with an age of 34.
Live Demo on coliru
Comparing first and second approach, you will notice a design weakness of the second:
While in the first approach, the type can be deduced by the compiler, this is not possible in the second. The only difference of template instances of second template function prompt() will be the return type – not deducible for compiler. Hence, the second template function must be used with an explicit template parameter always (which introduces another opportunity to make something wrong).
A general recommendation:
When you attempt to write a template function and you are uncertain about templates then start with a plain function, and a typedef for the type which shall become a template parameter:
typedef std::string T;
void prompt(const std::string &question, T &answer)
{
std::cout << question;
std::cin >> answer;
}
Compiling, testing, admiring, done.
Now, it can be turned into a template function:
//typedef std::string T; // obsolete
template <class T>
void prompt(const std::string &question, T &answer)
{
std::cout << question;
std::cin >> answer;
}
Compiling, testing, admiring, done.
If I understand correctly you can use operator>> overloading:
struct AnimalNameAnswer
{
std::string animalName;
};
std::istream& operator>>(std::istream& in, AnimalNameAnswer& ana)
{
return in >> ana.animalName;
}
struct CarSpeedAnswer
{
int MPH;
};
std::istream& operator>>(std::istream& in, CarSpeedAnswer& csa)
{
return in >> cas.MPH;
}
template<class ANSWER>
void prompt(ANSWER& a)
{
std::cout << "Enter answer:" << std::endl;
std::cin >> a;
}
Related
I am a beginner , so i wanted to ask , can we create a class object vector/array , that does not delete it's content when i close the program like , so like I want a customer record , but whenever if we try to restart the program we need to enter the customer details again and again ...
how to prevent that from happening
#include <iostream>
#include <vector>
using namespace std;
class customer{
public:
int balance;
string name;
int password;
};
int main(){
vector <customer> cus;
...
if(choice == 1){
cout << cus[i].balance
}
return 0;
}
As a complement to Adam's answer, it is possible to encapsulate the serialization in the container class itself. Here is an simplified example:
The header file defining a persistent_vector class that saves its content to a file:
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
#include <initializer_list>
namespace {
// Utility functions able to store one element of a trivially copyable type
template <class T>
std::ostream& store1(std::ostream& out, const T& val) {
out.write(reinterpret_cast<const char*>(&val), sizeof(val));
return out;
}
template <class T>
std::istream& load1(std::istream& in, T& val) {
in.read(reinterpret_cast<char*>(&val), sizeof(val));
return in;
}
// Specialization for the std::string type
template <>
std::ostream& store1<std::string>(std::ostream& out, const std::string& val) {
store1<size_t>(out, val.size());
if (out) out.write(val.data(), val.size());
return out;
}
template <>
std::istream& load1<std::string>(std::istream& in, std::string& val) {
size_t len;
load1<size_t>(in, len);
if (in) {
char* data = new char[len];
in.read(data, len);
if (in) val.assign(data, len);
delete[] data;
}
return in;
}
}
template <class T>
class persistent_vector {
const std::string path;
std::vector<T> vec;
// load the vector from a file
void load() {
std::ifstream in(path);
if (in) {
for (;;) {
T elt;
load1(in, elt);
if (!in) break;
vec.push_back(elt);
}
if (!in.eof()) {
throw std::istream::failure("Read error");
}
in.close();
}
}
// store the vector to a file
void store() {
std::ofstream out(path);
size_t n = 0;
if (out) {
for (const T& elt : vec) {
store1(out, elt);
if (!out) break;
++n;
}
}
if (!out) {
std::cerr << "Write error after " << n << " elements on " << vec.size() << '\n';
}
}
public:
// a bunch of constructors, first ones load data from the file
persistent_vector(const std::string& path) : path(path) {
load();
}
persistent_vector(const std::string& path, size_t sz) :
path(path), vec(sz) {
load();
};
// last 2 constructors ignore the file because they do receive data
persistent_vector(const std::string& path, size_t sz, const T& val) :
path(path), vec(sz, val) {
};
persistent_vector(const std::string& path, std::initializer_list<T> ini) :
path(path), vec(ini) {
}
// destructor strores the data to the file before actually destroying it
~persistent_vector() {
store();
}
// direct access to the vector (const and non const versions)
std::vector<T>& data() {
return vec;
}
const std::vector<T>& data() const {
return vec;
}
};
It can, out of the box, handle any trivially copyable type and std::string. User has to provide specializations of store1 and load1 for custom types.
Here is a trivial program using it:
#include <iostream>
#include <string>
#include "persistent_vector.h"
int main() {
std::cout << "Create new vector (0) or read an existing one (1): ";
int cr;
std::cin >> cr;
if (!std::cin || (cr != 0 && cr != 1)) {
std::cout << "Incorrect input\n";
return 1;
}
if (cr == 0) {
persistent_vector<std::string> v("foo.data", 0, "");
// skip to the end of line...
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
for (;;) {
std::string line;
std::cout << "Enter a string to add to the vector (empty string to end program)\n";
std::getline(std::cin, line);
if (line.empty()) break;
v.data().push_back(line);
}
}
else {
persistent_vector<std::string> v("foo.data");
for (const std::string& i : v.data()) {
std::cout << i << '\n';
}
}
return 0;
}
When a programmer creates a vector class, he must ensure that the resources acquired for that vector are released when they are no longer needed. (See RAII)
C++ Reference : https://en.cppreference.com/w/cpp/language/raii
Wikipedia : https://en.wikipedia.org/wiki/Resource_acquisition_is_initialization
Stack Overflow : What is meant by Resource Acquisition is Initialization (RAII)?
Microsoft : https://learn.microsoft.com/en-us/cpp/cpp/object-lifetime-and-resource-management-modern-cpp?view=msvc-170
Before the program closes, all resources must be released.
(No leaking resources, memory included)
It is not possible to create a vector class that does not delete its contents after closing a program. Secure operating systems will release program resources when the program is closed.
If you want the program not to lose customer information after closing, you need to save the information in persistent (non-volatile) storage device, such as a disk.
As CinCout, 김선달, Serge Ballesta say, you have to save the customer information to a file, and write the program so that you can read that file during the start of the program.
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
struct customer {
std::string name;
int balance;
int password;
};
int main() {
std::vector <customer> customers;
std::ifstream ifs("info.txt");
{
customer customer{};
while (ifs >> customer.name >> customer.balance >> customer.password)
customers.push_back(customer);
}
for (const auto& [name, balance, password] : customers) {
std::cout <<
"\nName : " << name <<
"\nBalance : " << balance <<
"\nPassword : " << password <<
'\n';
}
std::cout << "\n\nWelcome\n\n";
std::ofstream ofs("info.txt", std::ios_base::app);
char cont{};
do {
customer customer{};
std::cout << "Name : ";
std::cin >> customer.name;
std::cout << "Balance : ";
std::cin >> customer.balance;
std::cout << "Password : ";
std::cin >> customer.password;
ofs << customer.name << ' ' << customer.balance << ' ' << customer.password << '\n';
std::cout << "Add another customer? (Y/N) : ";
std::cin >> cont;
} while (cont == 'Y');
for (const auto& [name, balance, password] : customers) {
std::cout <<
"\nName : " << name <<
"\nBalance : " << balance <<
"\nPassword : " << password <<
'\n';
}
}
CPlusPlus : https://www.cplusplus.com/doc/tutorial/files/
LearnCpp : https://www.learncpp.com/cpp-tutorial/basic-file-io/
(About File I/O)
This program is a prototype, I left some things incomplete (like check readings, user-defined I/O operators, duplicate code, formatting, reallocations of customers, ifs is not required after range-for + structured binding,...).
I suggest you read the book "Programming: Principles and Practice Using C+", I’m reading it and it helped me a lot.
(I’m also a beginner)
Edit: I also suggest you use "using namespace std;" only for small projects, examples or simple exercises.
Do not use "using namespace std;" for real projects, large projects or projects that may include other dependencies because the use of "using namespace std;" could lead to a possible naming collisions between names within std and the names of other codes and libraries.
It’s not good practice to use it all the time.
I have been trying to make a Convert.To command like in C# in C++ but I dont want to do it like "IntToString" Instead I want to make it like "ToString" just like in C#. I was wondering how can I know the format of the parameter given inside the function? Or is there any other way to do this?
#include <iostream>
#include <sstream>
class converting {
public:
std::string Int32ToString(int x) {
std::stringstream asd;
asd << x;
std::string cnvrtd;
asd >> cnvrtd;
return cnvrtd;
}
int StringToInt32(std::string x) {
std::stringstream asdf(x);
int cnvrtd;
asdf >> cnvrtd;
return cnvrtd;
}
};
int main() {
converting Convert;
std::cout << "This is for a test. Avaiable options are:" << std::endl << "StringToInt32" << std::endl << "Int32ToString" << std::endl;
std::string firstinput;
std::cin >> firstinput;
if (firstinput == "StringToInt32") {
std::string input;
int result;
std::cin >> input;
result = Convert.StringToInt32(input);
std::cout << result;
return 0;
}
else if (firstinput == "Int32ToString") {
int input;
std::string result;
std::cin >> input;
result = Convert.Int32ToString(input);
std::cout << result;
return 0;
}
else {
std::cout << "Please enter a valid input";
return 0;
}
}
When you say - Format of the parameter given inside the function, do you mean, how do you know the data type of the parameter. If that's the case, you will have to write functions for all the data types for which you want to support conversion, inside your Converting class with same function name, this is called function overloading in C++. e.g.
std::string convert (int n){}
std::string convert (float n){}
std::string convert (double n){}
When you will invoke this convert function compiler will choose appropriate overloaded function according to the data type.
However there is smaller way to achieve the same functionality by writing a template function like
template<class Dt>
std::string Convert (Dt n){
return std::to_string(n);
}
Hope I am not missing considering any limitations if you have mentioned.
I want to pass a struct to function something like below (I know i can pass single member to function like input(int age, string s) but i want to pass whole struct like input(student s) )
#include <iostream>
using namespace std;
struct student
{
string name;
int age;
};
void input(student s)
{
cout << "Enter Name: ";
cin >> s.name;
cout << "Enter age: ";
cin >> s.age;
}
int main(int argc, char *argv[]) {
struct student s1;
input(s1);
cout << "Name is: " << s1.name << endl;
cout << "Age is: " << s1.age << endl;
}
Above code does not produce correct output, I want to use above code with pointer so to get expected output.
Test:If i input name to "abc" and age to 10. It does not get printed in main
Your function makes a local copy of the input. It looks like you need to pass by reference:
void input(student& s) { .... }
// ^
By default, function arguments are passed by value, so this issue is not specific to classes. For example,
void increment_not(int i) { ++i; }
int i = 41;
increment_not(i);
std::cout << i << std::endl; // prints 41
Your function passes student s by value, that's why the variable s1 in main doesn't change.
Change it to pass reference:
void input(student& s)
// ^
You need to pass the struct by reference, rite now you are passing it by copy so whatever changes are made they are on copy of the passed object.
void input(student& s){....}
i am new to c++ from other languages, and looking at examples this code looked like it should work
#include <iostream>
using namespace std;
main()
{
string input = "";
cout << "in: ";
getline(cin, input);
input_recv(input);
}
input_recv(input)
{
if (input == "hello"){
cout << "derp" << endl;
}
}
it will not let me use the function input_recv. it gives me several errors in my IDE. one being `input_recv' undeclared (first use this function). basically what i am trying to do for this is make it respond to input using a function.
EDIT:
#include <iostream>
#include <string>
using namespace std;
void input_recv(string);
int main()
{
while (1 == 1){
string input = "";
cout << "in: ";
getline(cin, input);
input_recv(input);
cin.get();
}
}
void input_recv(string input){
if (input == "hello"){
cout << "derp" << endl;
}
}
thanks
C++ requires the function to be declared before it's used, so if you move the input_recv definition above the main function, it will work. Otherwise, you can leave the program the way it is and add a forward declaration above main like this:
void input_recv(string);
int main()
{
...
}
void input_recv(string input)
{
...
}
Edit:
There are a few other errors here as well as other comments pointed out. One, functions should have a return type and parameter types specified. Also, before using the string type, you need to
#include <string>.
Declare the function first, and use a correct function prototype, here there is not type for input, no return type ... Example below,
#include <iostream>
#include <string>
void input_recv(const std::string& input);
int main()
{
std::string input = "";
std::cout << "in: ";
std::getline(std::cin, input);
input_recv(input);
return 0;
}
void input_recv(const std::string& input)
{
if (input == "hello"){
cout << "derp" << endl;
}
}
C++ is a strongly-typed language. You must declare your variables and your functions with explicit types:
// forward declare your function
void input_recv(std::string input);
// alternatively
void input_recv_better(const std::string& input);
int main()
{
std::string input;
std::cout << "In: ";
std::getline(std::cin, input);
input_recv(input);
input_recv_better(input);
return 0;
}
void input_recv(std::string input)
{
if (input == "hello")
{
std::cout << "derp" << std::endl;
}
}
void input_recv_better(const std::string& input)
{
if (input == "hello")
{
std::cout << "derp!" << std::endl;
}
}
There's a few things definitely wrong with this snippet, I will correct them all so you can observe the difference:
#include <iostream>
using namespace std;
void input_recv(string input);
int main()
{
string input = "";
cout << "in: ";
getline(cin, input);
input_recv(input);
}
void input_recv(string input)
{
if (input == "hello"){
cout << "derp" << endl;
}
}
I have added return types to your functions, data types to your parameters, and a forward declaration of the input_recv function so that the main function knows it exists.
You will definitely want to pick up a book like C++ Primer (the latest edition revised for the C++11 standard) before learning bad practice by trying to forgo some sort of standard training.
#include <iostream>
using namespace std;
void input_recv(string input)
{
if (input == "hello"){
cout << "derp" << endl;
}
}
int main()
{
string input = "";
cout << "in: ";
getline(cin, input);
input_recv(input);
return 0;
}
I'm having trouble converting a string into a double.
My string has been declared using the "string" function, so my string is:
string marks = "";
Now to convert it to a double I found somewhere on the internet to use word.c_str(), and so I did. I called it and used it like this:
doubleMARK = strtod( marks.c_str() );
This is similar to the example I found on the web:
n1=strtod( t1.c_str() );
Apparently, that's how it's done. But of course, it doesn't work. I need another parameter. A pointer I believe? But I'm lost at this point as to what I'm suppose to do. Does it need a place to store the value or something? or what?
I also need to convert this string into a integer which I have not begun researching as to how to do, but once I find out and if I have errors, I will edit this out and post them here.
Was there a reason you're not using std::stod and std::stoi? They are at least 9 levels more powerful than flimsy strtod.
Example
#include <iostream>
#include <string>
int main() {
using namespace std;
string s = "-1";
double d = stod(s);
int i = stoi(s);
cout << s << " " << d << " " << i << endl;
}
Output
-1 -1 -1
If you must use strtod, then just pass NULL as the second parameter. According to cplusplus.com:
If [the second parameter] is not a null pointer, the function also sets the value pointed by endptr to point to the first character after the number.
And it's not required to be non-NULL.
Back in the Bad Old Dark Days of C, I'd do something ugly and unsafe like this:
char sfloat[] = "1.0";
float x;
sscanf (sfloat, "%lf", &x);
In C++, you might instead do something like this:
// REFERENCE: http://www.codeguru.com/forum/showthread.php?t=231054
include <string>
#include <sstream>
#include <iostream>
template <class T>
bool from_string(T& t,
const std::string& s,
std::ios_base& (*f)(std::ios_base&))
{
std::istringstream iss(s);
return !(iss >> f >> t).fail();
}
int main()
{
int i;
float f;
// the third parameter of from_string() should be
// one of std::hex, std::dec or std::oct
if(from_string<int>(i, std::string("ff"), std::hex))
{
std::cout << i << std::endl;
}
else
{
std::cout << "from_string failed" << std::endl;
}
if(from_string<float>(f, std::string("123.456"), std::dec))
{
std::cout << f << std::endl;
}
else
{
std::cout << "from_string failed" << std::endl;
}
return 0;
}
Personally, though, I'd recommend this:
http://bytes.com/topic/c/answers/137731-convert-string-float
There are two ways. C gives you strtod which converts between a char
array and double:
// C-ish:
input2 = strtod(input.c_str(), NULL);
The C++ streams provide nice conversions to and from a variety of
types. The way to use strings with streams is to use a stringstream:
// C++ streams:
double input2;
istringstream in(input);
input >> input2;
We can define a stringTo() function,
#include <string>
#include <sstream>
template <typename T>
T stringTo(const std::string& s) {
T x;
std::istringstream in(s);
in >> x;
return x;
}
Then, use it like
std::cout << stringTo<double>("-3.1e3") << " " << stringTo<int>("4");