I'm am a beginner in C++. I'm using Xcode to compile my code. Right now I am going over variables and doing a brief exercise on the subject. The exercise asks that I ask for the user to input their first and last name as well their age. As a additional requirement I need to use a double floating point for age so I can multiply the age into months. Below is my code:
#include <iostream>
#include <math.h>
int main()
{
std::cout << "Please enter your first name, second name, and age (then press enter).\n";
std::string first;
std::string last;
std::double age;
std::cin >> first >> last >> age;
std::cout << "Hello, " << first << " " << last << ". Your age is " << age << " and you are " << (age * 12) << " months old.";
return 0;
}
I get an error that says that the double is an expected unqualified-id. Can someone point out what I'm doing wrong and the correct way to do this?
double does not live in the std namespace. You need
double age;
You also need to include the string header for std::string. You may get it indirectly from iostream on some implementations, but you cannot rely on that: it is a fluke.
double is a built-in type. It doesn't live in any namespace and doesn't need any qualification! Just remove the std:: in front of double:
double age;
Note, you should test whether your input was actually successful:
if (std::cin >> first >> last >> age) {
// process successful input
}
else {
std::cout << "ERROR: failed to read expected input\n";
}
First of all it is a good idea to include header <string>
#include <string>
If in C# so-called built-in types in realty are aliases for classes as for example double is an alias for System.Double and you can write
System.Double age;
or
double age;
in C++ these types indeed are built in types and use keywords as doubleto specify a type
double age;
Though i do not understand why age should be double because the number of months in year is an integer value.:)
I believe the code below is about ideal for learning how to do this kind of nearly-first C++ program.
The little technical problem with your code was just that double is keyword, not a name defined by the standard library, and hence, not in namespace std.
In addition I’ve added
inclusion of the <string> header, necessary for using std::string in a portable way,
a using namespace std; directive, very handy for small exploration programs (but do not place this in the global namespace in a header file!),
checking of whether input operations succeed (also output can fail but that’s extremely rare).
The way that I check for input operation failure, using boolean "or" (the || operator), is not yet very much used in C++, but is common in some other languages. Essentially the left hand argument of || is converted to bool, since that’s what || requires. The left hand argument is the expression result of some input operation, which in general is a reference to the cin stream, and a bool value is then produced via a defined conversion that is equivalent to writing !cin.fail() (where ! is the logical "not" operation).
E.g., getline( cin, first ) || fail( ... ) reads very nicely as “getline or else fail”, and in addition to reading nicely it’s also visually distinctive, easy to recognize as a failure check.
#include <iostream>
#include <string>
#include <stdlib.h> // exit, EXIT_FAILURE
using namespace std;
// Poor man's way to handle failure, but good enough here:
bool fail( string const& message )
{
cerr << "!" << message << endl;
exit( EXIT_FAILURE );
}
int main()
{
cout << "Please enter your first name: ";
string first;
getline( cin, first )
|| fail( "Sorry, input of your first name failed." );
cout << "Please enter your last name: ";
string last;
getline( cin, first )
|| fail( "Sorry, input of your last name failed." );
cout << "Please enter your age in years: ";
double age;
cin >> age
|| fail( "Sorry, input of your age failed." );
cout << "Hello, " << first << " " << last << "." << endl;
cout
<< "Your age is " << age << " years"
<< " and you are "<< (age*12) << " months old."
<< endl;
}
Related
I am not sure where I put the char command declaration where I wont get a "Not defined in this scope" error and it will loop through accepting a new char command the next time the program loops.
I tried putting it inside of the do loop but then it said that char was not defined in that scope, I then put it right after the int main function and when entering A as a command it infinitely loops my add_entry function without allowing user input.
Do I have to pass by reference maybe? Or pass by value?
My file that holds all function definitions
#include "main.h"
using namespace std;
int syntax::add_entry()
{
cout << "Enter a concept name: ";
cin.get(name, SIZE);
cout << endl << "Enter an example of the syntax: ";
cin.get(example,SIZE);
cout << endl << "Enter a description of the syntax: ";
cin.get(desc,SIZE);
cout << endl << "Enter a difficulty rating from 1-10: ";
cin.get(diff,SIZE);
cout << endl << "Enter a usefulness rating from 1-10: ";
cin.get(use,SIZE);
//open and write to the file
ofstream myfile;
myfile.open("data.txt");
myfile << "Name: " << name << endl;
myfile << "Example of syntax: " << example << endl;
myfile << "Description of syntax: " << desc << endl;
myfile << "Difficulty rating from 1-10: " << diff << endl;
myfile << "Usefulness rating from 1-10: " << use << endl;
myfile.close();
return 0;
}
int syntax::display_entry()
{
ifstream myfile("data.txt");
/*
char name[SIZE];
char example[SIZE];
char desc[SIZE];
char diff[SIZE];
char use[SIZE];
*/
if(myfile.is_open())
{
while(myfile >> name >> example >> desc >> diff >> use)
{
std::cout << name << ", " << example << ", " << desc << ", " << diff << ", " << use;
}
myfile.close();
}else
cout << "File is not open" << endl;
std::cin.get();
return 0;
}
my main .cpp file
#include "main.h"
using namespace std;
int main()
{
char command;
syntax c;
do{
cout << "Welcome to the C++ concept syntax user database." << endl;
cout << "Choose one of the following commands: " << endl;
cout << endl << endl;
cout << "A) Add a new entry B) Display all entrys C) Search for difficulty D) Exit: ";
cin >> command;
cout << endl;
if(command == 'A' || command == 'a')
{
c.add_entry();
}
else if(command == 'B' || command == 'b')
{
c.display_entry();
}
else if(command == 'D' || command == 'd')
{
cout << "Quitting program, Thank you for using" << endl;
}
}while(command != 'D' || command != 'd');
return 0;
}
my .h file
#include <iostream>
#include <fstream>
#include <cstring>
#include <cctype>
using namespace std;
class syntax
{
public:
const static int SIZE = 50;
char name[SIZE];
char example[SIZE];
char desc[SIZE];
char diff[SIZE];
char use[SIZE];
int display_entry();
int add_entry();
private:
};
You need to read and understand about "formatted input" and "unformatted input". Please check here.
Formatted input is done using the extractor operator >>. It reads characters from a stream and formats them to the expected variable type. If you write int x; std::cin >> x and you enter the number 12, so the digits/characters '1' and '2', your input will be formatted / converted to an integer value 12.
It is important to understand that formatted input
ignores leading white space
stops any conversion when encountering white space (but does not extract it from the stream)
Meaning, if you enter 12 and then press the enter-key, the characters '1' and '2' will be extracted from the stream, but the newline 'n' will not be consumed or extracted from the screen and is still available.
This default behavior can be addapted by setting certain flags.
Now, if we look at "unformatted input" functions, like get, it will read all kind of characters, including spaces and so on until it hits the specified delimiter, which is '\n' per default. For the get function, the delimiter '\n' will not be extracted. So, it is still in the stream. This is in contrast to the getline function which would extract the '\n' from the stream (but not store it).
All this you can read in the linked description.
And now, the root cause for all you problems, is also written in the description:
If no characters were extracted, calls setstate(failbit)
Then, let us look on the order of events
You enter a 'a', becuase you want to add an entry
The 'a' will be extracted and the '\n' is still in the stream
In function "add_entry" you call "get"
Get will try to read charcters, until it finds a newline '\n'
But, as a leftover from the previous operation, it will immediately see the '\n' , and hence store no other data at all, and consequently sets the failbit of the stream. All the following calls to std::cin will do nothing, because the failbit of the stream is set.
The functions returns to main and the failbit is still set
The next call cin >> command; will do nothing and will especially not modify the "command" variable. This will still contain an 'a'
And then the loop runs forever
You have an additional bug in the "while" condition. This must be corrected to: ´while (command != 'D' && command != 'd');´
Now, what to do.
First, and very important, for any IO-function you need to check, if it worked or not. There are functions to read the iostate of the stream. But c++ makes life easier. The bool-operator and the not-operator are overwritten and will return state information. If you want to know, if any IO operation was successful, the you can write something like if (std::cin) ....
Very convenient. But must be used.
And since IO operations return mostly a reference to the stream for which they were called, you can write if (cin >> command) . . . . This will first call the extraction operator. This will return a reference to the stream and for that you can use an if statement, because of the overwritten bool-operator.
But how to overcome the nasty problem with the '\n' in the stream, which is often there? There are basically 2 functionalities:
Function ignore. Will ignore all/a number of characters, until a delimiter is hit.
Function/manipulator std::ws. Will eat all white spaces.
I recommend to add one time cin >> std::ws; at the top of your "add_entry" routine and then you must change all get functions to getline. If not, you would need to add std::ws before each get statement.
And again, for each IO function, check the status! For example if (!cin.getline(example, SIZE)) .... do something, show error
And in the future. For any transition from formatted to unformatted input, use std::ws
And, do never forget to read the documentation carefully.
Have fun!
I am reading the book 'Accelerated C++', and I am unable to reproduce the results for their read homework problem even after exactly copying their code on my machine. The basic problem is about using cin.clear() to change the failure state of the inpute stream after the use of EOF to indicate that all the grades have been entered. Authors suggest Ctrl+D on linux systems for EOF. I already saw this and this but they couldn't solve my problem.
Here is my minimal working example:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
string name, city;
vector<double> homework;
cout << "Enter your name : " ;
cin >> name;
cout << "Hello " + name + "!" << endl;
cout << endl;
cout << "Enter your grades" << endl;
if (cin)
{
homework.clear();
double x;
while (cin >> x)
{
homework.push_back(x);
}
cin.clear();
}
cout << endl;
cout << "Enter your city : " ;
cin >> city ;
cout << "You live in " + city << endl;;
return 0;
}
After entering all the homework, I hit Ctrl+D and then I expect that I would now be given chance to enter city name. But the program just ends after printing the two strings at the end of my code. What is wrong with my understanding of cin.clear()? I would also like to point out that using cin.ignore() after cin.clear() doesn't help either.
On fail you need to clear the flags and ignore all the bad input.
Include #include <limits> for std::numeric_limits.
if ( std::cin.fail( ) )
{
std::cin.clear( );
std::cin.ignore( std::numeric_limits<std::streamsize>::max( ), '\n');
}
If you want a way to exit the loop use a value that you can test for (like -1). When you receive that value, exit the loop.
double value{ 0 };
while( std::cin >> value && value != -1 )
homework.push_back( value );
if ( std::cin.fail( ) )
{
std::cin.clear( );
std::cin.ignore( std::numeric_limits<std::streamsize>::max( ), '\n');
}
Edit:
I didn't see that you were trying to end the stream with EOF.
Read this answer to figure out how to accomplish this.
How to resume input stream after stopped by EOF in C++?
I am confused with the C++ function std::get_money defined in the <iomanip> header file. What is the use of get_money as per programming concept?
I have the following code using std::get_money.
#include <iostream> // std::cin, std::cout
#include <iomanip> // std::get_money
int main ()
{
long double price;
std::cout << "Please, enter the price: ";
std::cin >> std::get_money(price);
if (std::cin.fail()) std::cout << "Error reading price\n";
else std::cout << "The price entered is: " << price << '\n';
return 0;
}
When I typed in an input of 100.25 it returned 100. What is the relation between the output and monetary format? I read this reference but cannot understand the relation. The same confusion is present with std::put_money, std::get_time, and std::put_time.
What are some examples of its actual use?
This is a part of the standard library that I didn't know existed! According to cppreference, you have to set the locale to define how time and money should be formatted. Here I'm using the en_US locale.
#include <iomanip>
#include <iostream>
int main() {
long double price;
std::cin.imbue(std::locale("en_US.UTF-8"));
std::cout << "Please enter the price: ";
std::cin >> std::get_money(price);
if (std::cin.fail()) {
std::cout << "Error reading price\n";
} else {
std::cout << "The price entered is: " << price << '\n';
}
}
Still, this seems a bit finicky to me. The number must include a . with at least two digits after it. The $ is optional.
Okey as I've recently started to read about C++ and try to go with the book I'm having Programming Principles and practice Using C++ 2nd version.
I'm a total newbie so this is probably why, but here goes.
Okey so in the book they have you implement a header .h file instead of the (iostream) etc. So it just have all those for the start as the book doesn't want us to focus on those libraries in the start of the learning.
So i implemented it and used it (not sure if this is related to the problem). Anyway at page 77, I'm getting stuck.
Basically it's a wrong value that's getting entered and it's supposed to just show -1(or 0) as the int gets a false value, etc Carlos(letters, not an integer) so the int doesn't get a correct value so the code that is supposed to work (and show 0 or -1 as it's an incorrect value that's entered) is this according to the book:
#include "std_lib_facilities.h"
using namespace std;
int main()
{
cout << "Please enter your first name and age\n";
string first_name = "???"; // string variable // ("???” means “don’t know the name”)
int age = –1; // integer variable (–1 means “don’t know the age”)
cin >> first_name >> age; // read a string followed by an integer
cout << "Hello, " << first_name << " (age " << age << ")\n";
}
and this is what i wrote:
#include "std_lib_facilities.h"
using namespace std;
int main()
{
cout << "Please enter your first name and age" << endl;
string First_Name = "???";
int Age = -1;
cin >> First_Name >> Age;
cout << "Hello, " << First_Name << "(age" << Age << ")" << endl;
keep_window_open();
return 0;
}
However, the result with visual c++ for me is a crash when i for example write 22 Carlos.
According to the book it's supposed to output Hello, 22 (age -1)
But for me it just crashes after i enter the word Carlos as value for age...
I don't get a a error or anything when i run and compile it, but it crashes after when i give the false value for age.
What am i doing wrong?
add: I know i can use a string to get it to work, however I'm just interested in why it doesn't work as I'm following this book i wish to follow it without having these kind of problems as it's intended to work.
Here is a gif when im doing it:
http://imgur.com/a/ERjhz
Solution: To use system("pause"); instead of keep_window_open();
however it's still annoying to read the book with the knowledge that the code in the book doesn't work always :(
Well it is isn't a problem but too fast to be noticed by our eyes.
i am adding the function definition of keep_window_open()
inline void keep_window_open()
{
cin.clear();
cout << "Please enter a character to exit\n";
char ch;
cin >> ch;
return;
}
As you can see it simply takes the character input from the us
Forward you will learn about input stream and its buffer
So when you input a character in place of integer there is error flagged in the stream(background) and the only one of the characters input is used(in your case 'C' is used for flagging).
I am using input as Carlos 22
So now the input stream is still having characters 'a','r','l','o','s',22
so now the 'a' is used as a input for keep_window_open function
and the program ends without waiting for a input from you
So there is no error or crash but since the character is already there for input for keep_window_open function so its kind of really fast
The problem is in keep_window_open. It's a tricky function that is very hard to get absolutely right. You can replace it with this code that sidesteps the problem but only works on Windows:
inline void keep_window_open()
{
system("pause");
}
or with this slightly more complicated code that tries to take more cases into account:
inline void keep_window_open()
{
cout << "Please enter a character to exit\n";
if (!cin)
{
cin.clear();
cin.ignore(120, '\n');
}
char ch;
cin >> skipws >> ch;
}
(This assumes you don't enter lines longer than 120 characters. Replace 120 with numeric_limits<streamsize>::max() if you want it to be free from arbitrary limits. Other functions from std_lib_facilities.h do use 120 in this situation. You many or may not have to add #include <limits> directive to your program).
I have tested in a couple of cases and it appears to work with both correct and incorrect input to the program, but use it at your own risk. It still may or may not work correctly if your program requires more complicated input.
A good rule is to always except that the end users is idiots, so you need to write the program in a way that can handles all kinds of inputs without crashing. Therefore always read input numbers as std::string and then try convert it to int, short, double, unsigned int or what ever datatype you are using.
Your code should look like:
#include <cstdlib>
#include <exception>
#include <iostream>
#include <stdexcept>
#include <string>
int main(int argc, char **argv)
{
int age;
std::string first_name;
std::string input_age;
std::cout << "Please enter your first name and age: " << std::endl;
std::cin >> first_name >> input_age; // Read the age as 'std::string'
try
{
age = std::stoi(input_age); // Try to convert age from 'std::string' to 'int'
std::cout << "Hello, " << first_name << " (" << age << ")" << std::endl;
}
catch(std::invalid_argument& ex) // 'std::stoi()' will throw 'std::invalid_argument' if it's not able to convert 'std::string' to 'int'
{
std::cerr << "Unable to convert input value ('" << input_age << "') to 'int'" << std::endl;
std::cerr << "Debug info: " << ex.what() << std::endl;
}
catch(std::out_of_range& ex) // 'std::stoi()' will throw 'std::out_of_range' if 'std::string' is too small or too big to store in a 'int'
{
std::cerr << "The input value (" << input_age << ") is out of range, please input a value inside the range" << std::endl;
std::cerr << "Debug info: " << ex.what() << std::endl;
}
return EXIT_SUCCESS;
}
So it's nothing to do with code, it's something to do with input.
when i for example write 22 Carlos.
The problem is that the code is asking for First_Name then Age, Not Age then First_Name. So when you put 22 for First_Name, the .exe got confused.
for example lets say I did this
int y = 0;
cout << "Give me INT: ";
cin >> y;
cout >> "You put: " >> y;
And when I run the program and put this for input
Give me INT: ghaisewofasd
*crashed*
This is a problem because the user is giving a string for when the code is asking for a int.
So for your case, instead of writing 22 Carlos, just write Carlos 22.
Also keep in mind, this book maybe not so correct, because it shouldn't print out Hello, (22). Now a days stuff like that crash if that happens, maybe it was a older version of C++.
I'm writing a file matching program for a project for school. The idea is that one program allows you to enter info as follows: 1000 (acct number) Jane Doe 54.50 (balance). Then allow you to enter the account number and a transaction amount for the second program to combine and update a new master file.
The programs are working together just fine (the second one takes information from the first, including any transactions and updates the new balance - searching by account number) but the problem I am running into is with the name.
---Wasn't clear here. When I ask for a name and I put in a single string of characters, the program works fine, if I try to put in a full name, like Jane Doe I go into the loop mentioned below.
I've tried char name[20] which puts me into an infinite loop and I have to 'x' out of the program and I've tried assigning first and lastName to string. That worked for the writing but the program that takes the input file oldMaster and the transaction file inTransaction then outputs a new file newMaster, doesn't recognize the name.
I've tried getline also which isn't working for me, probably programmer error.
Should this be done as an array, if that's possible for this? I think I'm getting hung up on the fact that I am editing files. Answers are fine - but I like to figure it out on my own, just looking for a little guidance on where to go from here.
Hopefully this was fairly clear - if not I'll be happy to explain again in a different way. Just frustrated that I'm this close and can't solve it.
Thanks in advance!
#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <iomanip>
using namespace std;
void createOldMaster()
{
ofstream oldMaster;
int accountNum;
double balance;
char name[15];
oldMaster.open("oldmast.dat", ios::out);
if(!oldMaster)
{
cout << "Unable to open the file." << endl;
exit(1);
} // end if
cout << "Enter the account number (0 to exit)." << endl;
while(true)
{
cout << "Account Number: ";
cin >> accountNum;
if(accountNum == 0)
break;
else
{
\\ This is where it hangs up if I use a first and last name
cout << "\nName: ";
cin >> name;
cout << "\nBalance : " << endl;
cin >> balance;
oldMaster << accountNum << " " << name << " " << balance << endl;
}
}
} //end createOldMaster
void createTransaction()
{
ofstream inTransaction;
int accountNum;
double balance;
inTransaction.open("trans.dat");
if(!inTransaction)
{
cout << "Unable to open the transaction file." << endl;
exit(1);
}
cout << "Enter the account number and balance (0 to exit): " << endl;
while(true)
{
cout << "Account Number: " << endl;
cin >> accountNum;
if(accountNum == 0)
break;
else
{
cout << "Balance: " << endl;
cin >> balance;
inTransaction << accountNum << " " << balance << endl;
}
}
} //end createTransaction
int main()
{
createOldMaster();
createTransaction();
return 0;
}
Your best bet is to use as much of the standard C++ library as you can. Have a reference handy, maybe even a copy of the C++ standard if you're so inclined, and look for shortcuts to make your work easier and your code shorter.
Avoid primitive arrays and primitive strings wherever possible. Instead of primitive arrays try to use std::vector. Instead of primitive strings try to use std::string. Instead of C's FILE* try to use std::ofstream and std::ifstream. If you need to prohibit two accounts with the same account number then choose a C++ container that guarantees unique elements. If you need to find an element in a container try to use a member function of the container for the search, and if that doesn't exist then a standard search function from the standard C++ algorithms.
Reuse and steal mercilessly.