Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I was taught in school that using cin/cout to get and show information to the user in a function was considered bad practice. I was told that all input/output should be done in the main function.
Is this true and why?
Typical for schools, this is an oversimplification. What was really meant was probably that
Input/Output should be separate from data processing.
This is easily illustrated by an example:
Wrong:
void doStuff() {
std::string input;
std::cout << "Please provide input: ";
std::cin >> input;
for (int i = 0; i < input.size(); i += 2) {
input[i] = ' ';
}
std::cout << input << std::endl;
}
int main() {
doStuff();
}
Much better:
std::string getInput() {
std::string input;
std::cin >> input;
return input;
}
std::string processData(std::string input) {
for (int i = 0; i < input.size(); i += 2) {
input[i] = ' ';
}
return std::move(input);
}
void printOutput(std::string const& s) {
std::cout << s << std::endl;
}
int main() {
auto input = getInput();
auto output = processData(input);
printOutput(output);
}
This way you can easily mock or test each of the functions separately, and it's much easier to for example add input validation right now.
std::string getInput() {
std::string input;
if (!(std::cin >> input)) {
throw std::runtime_error("Input problem!");
}
if (input.empty()) {
throw std::length_error("Input can't be empty!");
}
return input;
}
As a side note, main could also be written as:
int main () {
printOutput(processData(getInput()));
}
What your teacher is most likely about is to prevent code like
void add(void) {
int a, b;
cin >> a >> b;
cout << (a + b) << endl;
}
Which is often seen from beginner programmers. What is bad about this code is that it's on the one hand lying about what it does (because it doesn't add, it reads, adds and prints) and on the other hand misuses the most important abstraction tool, the function:
A function is intended to solve one task (which may be complex and consist of subtask) and more over - keeping to the mathematical origin of the term - act as a kind of transformation from some given parameters to some result, ideally like in purely functional languages without changing our having any state. (That is no matter when, how often and in what circumstances you call f(a), if you once get b as result you'll get that every time you call f with a)
Applying that to the simple example gives
int add(int lhs, int rhs) {
return lhs + rhs;
}
Nonetheless we somehow need to access the real world (which is very stateful), so for things like the following it's OK to have IO in a function:
int askInteger(void) {
int result;
cout << "Please give me an integer!";
cin >> result;
return result;
}
Please note that this is just an relatively stupid example, without any error handling or parametrisation.
To keep closer to the functional style it's advisable to not hard code the source and target of the IO like above, but rather pass them as parameters:
int askInteger(std::istream & from, std::ostream & to) {
int result;
to << "Please give me an integer!";
from >> result;
return result;
}
// called like
askInteger(cin, cout);
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
I've been told to read/write disc as little as possible. For this solution, I've made a constructor that reads the file on object construction and fills the unordered map with the contents of the file. Is this a good way/practice to read from .txt files?
In terms of printing out the contents of the file, I've mentioned readFile again. Is this ok to do? I couldn't really find another way without making it global. Here is the code below:
class Test {
private:
string name;
string number;
unordered_map<string, string> mappy;
public:
Test()
{
ifstream readFile("A:\\Coding\\namesNumbers.txt");
while (readFile >> name >> number)
{
mappy[name] = number;
}
}
void print()
{
ifstream readFile("A:\\Coding\\namesNumbers.txt");
while (readFile >> name >> number)
{
for (int i = 0; i < 1; i++)
{
cout << name << ":" << " ";
cout << number << endl;
}
}
}
~Test() {};
};
You are reading the file twice. When you don't mind the order of the items, then you can also print from 'mappy'.
Note that it is better to declare 'name' and 'number' as local as possible.
(Consider using another data type for 'number' i.s.o. 'string'.)
In the code below, I assume you have C++17 (for Structured binding)
class Test {
private:
unordered_map<string, string> mappy;
public:
Test()
{
ifstream readFile("A:\\Coding\\namesNumbers.txt");
string name;
string number;
while (readFile >> name >> number)
{
mappy[name] = number;
}
}
void print()
{
for (auto [name, number] : mappy)
{
cout << name << ":" << " ";
cout << number << endl;
}
}
~Test() {};
};
Reading a file in a construct is not necessarily a bad practice. Depends on the intended usage of the class. Sometimes you need to separate (default) construction from the reading of the data. In such a case you can provide two constructors: one for default construction and one for construction with file reading. As long as your solution satisfies, you can stick to that.
I'm writing a simple, universal function that shows a dialog. I intend to call it from different places in my code. The problem is that I need to clear the input buffer at the beginning of the function so lingering data from previous input is not interpreted as an answer.
This has to be a pretty common think to do, so I believe that C++ standard library provide some function that does that. However, I haven't any luck in finding it.
Here is a practical example of what I want to accomplish:
#include <iostream>
#include <string>
unsigned dialog(const char question[], const char answers[])
{
//TODO reset std::cin
while (true)
{
std::cout << question << " [";
for (unsigned i = 0; answers[i] != '\0'; ++i)
{
if (i != 0)
std::cout << '/';
std::cout << answers[i];
}
std::cout << ']' << std::endl;
std::string line;
std::getline(std::cin, line);
if (line.empty())
{
for (unsigned i = 0; answers[i] != '\0'; ++i)
if (answers[i] >= 'A' && answers[i] <= 'Z')
return i;
} else if (line.length() == 1)
{
const char answer = toupper(line[0]);
for (unsigned i = 0; answers[i] != '\0'; ++i)
if (answer == toupper(answers[i]))
return i;
}
}
}
int main()
{
// --- optional part ---
std::cout << "Write something to clutter the input buffer..." << std::endl;
std::string foo;
std::cin >> foo; //User enters "aaa bbb ccc"
// --- optional part end ---
return dialog("Do you like this question?", "Yn");
}
interactive version
Unlike this other similar question, I'm looking for some portable solution. It should be supported in at least Windows and any Linux system.
There is also this question that is very similar to mine. However, all the answers seems to assume that input buffer is not empty at the moment. If I put it before my dialog and the input is empty at the moment (e.g. directly after start of the program), it leads to a situation when user needs to press Enter to even display my dialog on screen. A few answer from that question that don't assume that buffer is not empty, base on functions that depend on implementation of the standard library.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I made a program that should take input print it. Then run a simple addition thing but when i use spaces in the input it skips through the addition. I do not know what the problem is.
this is the class stuff
#include <iostream>
#include <string>
using namespace std;
class Cheese {
private:
string name;
public:
void setName(string x){
cin >> x;
x = name;
}
string getName(){
return name;
}
void print(){
cout << name << endl;
}
};
this is the main stuff
int main()
{
string h;
Cheese hole;
hole.setName(h);
hole.getName();
hole.print();
this part is getting skipped through without letting me input
int x = 5;
int y = 16;
cout << x+y;
num(x);
int a;
int b;
int c;
cout << "Type in a number and press enter.";
cin >> a;
cout << "Repeat.";
cin >> b;
c = a+b;
cout << c << endl;
if(c <= 21){
cout << "Good job!";
}
else {
cout << "You fail!";
}
return 0;
}
I suggest you divide the responsibilities a little differently. The Cheese class's setName function should simply take a string and set the instance's member variable to the given argument.
Then your program can read from standard input and populate a string within main, and pass that string to setName.
To be more concrete:
class Cheese {
private:
string name;
public:
void setName(const string& x){
// change this code to set the 'name' member variable
}
[...]
};
And the main becomes:
int main()
{
string h;
Cheese hole;
std::string input_name;
cout << "Type a name and press enter.";
cin >> input_name; // Will read up to first whitespace character.
hole.setName(input_name);
hole.getName(); // this is a no-op: compiler may warn of unused return value
hole.print();
In general, reading standard input as part of a class's interface is a bad idea, because it makes it hard to re-use that class in the future (for example, with programs that take input from a file instead of from a human at a console).
The input that you pass to cin input stream skips any white space, Tab space or newline. If you wish to input string then you can use cin.getline(string s). The input after the white space gets passed to next waiting cin, as the next cin accepts integer and it get a character string it skips that. Thus when enter a string with white spaces the program skips the remaining part.
This is my first post on stack overflow so I apologize in advance if I miss a rule.
I tried to search a few posts however couldn't find what I was looking for.
I am trying to submit the Reversed Binary problem on Spotify however it is giving a reply "WRONG ANSWER". I have coded the problem in both C and C++, and I am able to validate answers for a lot of inputs. It doesn't seem that the problem is with the logic of the program. The puzzle states that "Input is read from stdin".
I have tried to use:
C: printf, scanf functions
C++: cout and cin functions (and writing "using namespace std" at the top)
C++: directly using std::cout and std::cin functions.
However none seems to work.
int stack[32];
top=-1
long inputNum,outputNum=0;
cout<<"Enter a Number\n";
cin>>inputNum;
while(inputNum>1) {
if(inputNum%2 == 0) {
push(0);
inputNum=inputNum/2;
} else if(inputNum%2 == 1) {
push(1);
inputNum=inputNum/2;
}
}
push(1);
int i=0,x=0;
while(top>-1) {
x=pop();
if(x==0) {
i++;
continue;
} else if(x==1) {
outputNum=outputNum+powl(2,i);
i++;
}
}
cout<<outputNum;
Ok. You have to realise is that spotify thing seems to be an automated bot which compiles and runs your submitted code.
So first off you're polluting the answer by providing your "Enter A Number" prompt. A bot wouldn't separate that from the real answer.
Secondly, I can't see how it compiles. What's this push(), pop(), top and stack code? Are you trying to use std::stack class? If so, check how you're using it.
On the other hand, if you're not using std::stack, but some of your own custom macros (not shown), then my bet would be to check those.
To read from stdin in c++, and write to stdout:
#include <iostream>
int main() {
unsigned int value;
std::cin >> value;
std::cout << reverse_binary(value);
}
You just need to implement reverse_binary (c:
You can extract this to a function which works with any streams:
void main_io(std::istream& input, std::ostream& ouput) {
unsigned int value;
input >> value;
output << reverse_binary(value);
}
And call it using cin and cout:
int main() {
main_io(std::cin, std::cout);
}
Or you can test it using stringstreams:
#include <sstream>
#include <cassert>
int main() {
std::istringstream input("13");
std::ostringstream output;
main_io(input, output);
assert(output.str() == "11");
}
Your streaming (though buggy) works fine.
I ran you code with,
int reverse_binary(int value)
{
if (value == 13) return 11;
return 1;
}
It must be within your own reverse_binary function.
What's your actual problem?
so i've seen many people ask this and not many solid answers floating around the web. most just check that an integer was placed in place of a string but if a floating point number was entered then it truncates the bottom half or if integers and characters are intered it truncates the characters. i need help writing a piece of code that checks for user input and asks the user to retry if his input is not valid or a combination of valid/invalid. i think the basic idea was to make a string so it accepts anything then use sstream to manipulate and then back to int if the input was legit but i cant really manage to check the other parts. if anyones run accross this or can help me out please link me to it. i'll post my code when i get a good sense of what to do.
Assuming that you can't use boost::lexical_cast, you can write your own version:
#include <sstream>
#include <iostream>
#include <stdexcept>
#include <cstdlib>
template <class T1, class T2>
T1 lexical_cast(const T2& t2)
{
std::stringstream s;
s << t2;
T1 t1;
if(s >> std::noskipws >> t1 && s.eof()) {
// it worked, return result
return t1;
} else {
// It failed, do something else:
// maybe throw an exception:
throw std::runtime_error("bad conversion");
// maybe return zero:
return T1();
// maybe do something drastic:
exit(1);
}
}
int main() {
std::string smin, smax;
int imin, imax;
while(std::cout << "Enter min and max: " && std::cin >> smin >> smax) {
try {
imin = lexical_cast<int>(smin);
imax = lexical_cast<int>(smax);
break;
} catch(std::runtime_error&) {
std::cout << "Try again: ";
continue;
}
}
if(std::cin) {
std::cout << "Thanks!\n";
} else {
std::cout << "Sorry. Goodbye\n";
exit(1);
}
}
You can use C++11 string conversion functions like stol
try
{
std::string value = ...;
long number = std::stol(value);
}
catch (std::invalid_argument const& e)
{
// no conversion could be performed
}
Post-comments update: Visual C++ 11 shipped with Visual Studio 2012 implements std::stol as a convenient wrapper around strtol declared in <cstdlib>. I think it's safe to assume most C++11 implementations define it in most optimal way possible, not reaching for std::stringstream machinery.
The C function strtol (and it's siblings) will be able to tell you if the string fed to it is completely consumed.
std::string str;
char *endptr;
std::cin >> str;
long x = std::strtol(str.c_str(), &endptr, 0);
if (*endptr != 0)
cout << "That's not a valid number...";
I don't know if there are any classes in standard c++ lib that encapsule primitive types like in java but here how a simple and very basic implementation would look like
class Integer {
private:
int value;
void parse(string);
public:
Integer(string);
int intValue();
};
Integer::Integer(string sint) { parse(sint); }
int Integer::intValue() { return value; }
void Integer::parse(string sint) {
string::iterator its = sint.begin();
while(its != sint.end() && (! (*its < '0' || *its > '9'))) {
its++;
}
if(its != sint.end()) {
throw sint + ": Input is not a valid integer.";
}
value = atoi(sint.c_str());
}