This may be a total beginner's question, but I have yet to find an answer that works for me.
Currently, I'm writing a program for a class that takes in a user's input (which can be one or more numbers separated by spaces), then determines whether the number is prime, perfect, or neither. If the number is perfect, then it will display the divisors.
Thus far, I've already written the code for the prime, perfect, and listing the divisors. I'm stuck on the input portion of my program. I don't know how to get the input that's separated by spaces to go through my loops one at a time.
This is my current program:
cout<<"Enter a number, or numbers separated by a space, between 1 and 1000."<<endl;
cin>>num;
while (divisor<=num)
if(num%divisor==0)
{
cout<<divisor<<endl;
total=total+divisor;
divisor++;
}
else divisor++;
if(total==num*2)
cout<<"The number you entered is perfect!"<<endl;
else cout<<"The number you entered is not perfect!"<<endl;
if(num==2||num==3||num==5||num==7)
cout<<"The number you entered is prime!"<<endl;
else if(num%2==0||num%3==0||num%5==0||num%7==0)
cout<<"The number you entered is not prime!"<<endl;
else cout<<"The number you entered is prime!"<<endl;
return 0;
It works, but only for a single number. If anyone could help me to get it to be able to read multiple inputs separated by spaces, it'd be greatly appreciated. Also, just a side note, I do not know how many numbers will be entered, so I can't just make a variable for each one. It will be a random amount of numbers.
Thanks!
By default, cin reads from the input discarding any spaces. So, all you have to do is to use a do while loop to read the input more than one time:
do {
cout<<"Enter a number, or numbers separated by a space, between 1 and 1000."<<endl;
cin >> num;
// reset your variables
// your function stuff (calculations)
}
while (true); // or some condition
I would recommend reading in the line into a string, then splitting it based on the spaces. For this, you can use the getline(...) function. The trick is having a dynamic sized data structure to hold the strings once it's split. Probably the easiest to use would be a vector.
#include <string>
#include <vector>
...
string rawInput;
vector<String> numbers;
while( getline( cin, rawInput, ' ' ) )
{
numbers.push_back(rawInput);
}
So say the input looks like this:
Enter a number, or numbers separated by a space, between 1 and 1000.
10 5 20 1 200 7
You will now have a vector, numbers, that contains the elements: {"10","5","20","1","200","7"}.
Note that these are still strings, so not useful in arithmetic. To convert them to integers, we use a combination of the STL function, atoi(...), and because atoi requires a c-string instead of a c++ style string, we use the string class' c_str() member function.
while(!numbers.empty())
{
string temp = numbers.pop_back();//removes the last element from the string
num = atoi( temp.c_str() ); //re-used your 'num' variable from your code
...//do stuff
}
Now there's some problems with this code. Yes, it runs, but it is kind of clunky, and it puts the numbers out in reverse order. Lets re-write it so that it is a little more compact:
#include <string>
...
string rawInput;
cout << "Enter a number, or numbers separated by a space, between 1 and 1000." << endl;
while( getline( cin, rawInput, ' ') )
{
num = atoi( rawInput.c_str() );
...//do your stuff
}
There's still lots of room for improvement with error handling (right now if you enter a non-number the program will crash), and there's infinitely more ways to actually handle the input to get it in a usable number form (the joys of programming!), but that should give you a comprehensive start. :)
Note: I had the reference pages as links, but I cannot post more than two since I have less than 15 posts :/
Edit:
I was a little bit wrong about the atoi behavior; I confused it with Java's string->Integer conversions which throw a Not-A-Number exception when given a string that isn't a number, and then crashes the program if the exception isn't handled. atoi(), on the other hand, returns 0, which is not as helpful because what if 0 is the number they entered? Let's make use of the isdigit(...) function. An important thing to note here is that c++ style strings can be accessed like an array, meaning rawInput[0] is the first character in the string all the way up to rawInput[length - 1].
#include <string>
#include <ctype.h>
...
string rawInput;
cout << "Enter a number, or numbers separated by a space, between 1 and 1000." << endl;
while( getline( cin, rawInput, ' ') )
{
bool isNum = true;
for(int i = 0; i < rawInput.length() && isNum; ++i)
{
isNum = isdigit( rawInput[i]);
}
if(isNum)
{
num = atoi( rawInput.c_str() );
...//do your stuff
}
else
cout << rawInput << " is not a number!" << endl;
}
The boolean (true/false or 1/0 respectively) is used as a flag for the for-loop, which steps through each character in the string and checks to see if it is a 0-9 digit. If any character in the string is not a digit, the loop will break during it's next execution when it gets to the condition "&& isNum" (assuming you've covered loops already). Then after the loop, isNum is used to determine whether to do your stuff, or to print the error message.
You'll want to:
Read in an entire line from the console
Tokenize the line, splitting along spaces.
Place those split pieces into an array or list
Step through that array/list, performing your prime/perfect/etc tests.
What has your class covered along these lines so far?
int main() {
int sum = 0;
cout << "enter number" << endl;
int i = 0;
while (true) {
cin >> i;
sum += i;
//cout << i << endl;
if (cin.peek() == '\n') {
break;
}
}
cout << "result: " << sum << endl;
return 0;
}
I think this code works, you may enter any int numbers and spaces, it will calculate the sum of input ints
std::vector<int> num{};
int buf;
do{
std::cin >> buf;
num.push_back(buf);
}while(std::cin.peek() == ' ');
In C language you can to it using scanf like this:
scanf('%d %d',&a,&b);
Related
I was using character arrays to get inputs from the user then display the output afterwards. However, every time I enter values with spaces in between, only the first word before the space is printed.
For instance, this is what I typed:
Customer No.: 7877 323 2332
This will be the output:
Customer No.: 7877
I already searched for possible solutions but I can't seem to find the right solution.
This is my code for reference:
#include<iostream>
using namespace std;
int main()
{
char custNum[10] = " "; // The assignment does not allow std::string
cout << "Please enter values for the following: " << endl;
cout << "Customer No.: ";
cin >> custNum;
cout << "Customer No.: " << custNum << endl;
}
Another option is to use std::basic_istream::getline to read the entire string into the buffer and then remove the spaces with a simple for loop. But when using plain-old character arrays don't skimp on buffer size. It is far better to be 1000-characters too long than one-character too short. With your input, your absolute minimum size of custNum is 14 characters (the 13 shown plus the '\0' (nul-terminating) character. (rough rule-of-thumb, take your longest estimated input and double it -- to allow for user-mistake, cat stepping on keyboard, etc...)
In you case you can simply do:
#include <iostream>
#include <cctype>
int main() {
char custNum[32] = " "; // The assignment does not allow std::string
int wrt = 0;
std::cout << "Please enter values for the following:\nCustomer No.: ";
if (std::cin.getline(custNum, 32)) { /* validate every input */
for (int rd = 0; custNum[rd]; rd++)
if (!isspace((unsigned char)custNum[rd]))
custNum[wrt++] = custNum[rd];
custNum[wrt] = 0;
std::cout << "Customer No.: " << custNum << '\n';
}
}
The two loop counters rd (read position) and wrt (write position) are simply used to loop over the original string and remove any whitespace found, nul-terminating again when the loop is left.
Example Use/Output
$ ./bin/readcustnum
Please enter values for the following:
Customer No.: 7877 323 2332
Customer No.: 78773232332
Also take a look at Why is “using namespace std;” considered bad practice? and C++: “std::endl” vs “\n”. Much easier to build good habits now than it is to break bad ones later... Look things over and let me know if you have questions.
Apart from std::getline, if you are going to use C-style strings, try the following code:
int main() {
char* str = new char[60];
scanf("%[^\n]s", str); //accepts space a a part of the string (does not give UB as it may seem initially
printf("%s", str);
return 0;
}
Also, if you absolutely need it to be a number, then use atoi
int ivar = std::atoi(str);
PS Not to forget gets (!!dangerous!!)
char* str;
gets(str);
puts(str);
cin >> int_variable will stop reading input when it reaches the first character that isn't a valid part of a number. C++ does not consider spaces part of a number, so it stops reading as soon as it encounters one.
You could use std::getline to read into a string instead, then remove the spaces from the string before converting to an integer. Or maybe in this case you don't even need the integer and can leave it as a string.
I am trying to skip the spaces in my code using getline();
I think I solved the spacing problem, but I'm trying to make the code check from the beginning of the word and the end of the word at the same time, so that when I type sentences like "ufo tofu" it will come back as a palindrome.
I've tried removing the spaces, but it only causes the system to return me an error.
#include <iostream>
#include <string>
#include <cctype>
using namespace std;
int main() {
string userInput;
int startInput;
int endInput;
bool isPalindrome = true;
startInput = userInput.length();
getline (cin, userInput);
cin.ignore();
for (int i = 0; i<(startInput/2); i++){
if (userInput[i] != userInput[(startInput -1) -i])
isPalindrome = false;
}
if (isPalindrome){
cout << userInput << " is a palindrome" << endl;
}
else {
cout << userInput << " is not a palindrome" << endl;
}
return 0;
}
I am trying to make the output come back as "is not a palindrome" when I submit my code to be graded.
These are the two errors that are coming back;
4: Compare output
0 / 2
Output differs. See highlights below.
Special character legend
Input
statistics
Your output
statistics is a palindrome
Expected output
statistics is not a palindrome
6: Compare output
0 / 2
Output differs. See highlights below.
Special character legend
Input
evil is alive
Your output
evil is alive is a palindrome
Expected output
evil is alive is not a palindrome
string s;
do {
getline(cin, s);
}while(s.empty());
s.erase((remove(s.begin(),s.end(),' ')),s.end());
cout<<s<<endl;
Let's say your string s is ufo tofu. It will after erasing all spaces become ufotofu. That way you can easily check if it's palindrome or not.
How does this thing work ?
Well we declare a string called s. In that string, we will store our ufo tofu input.
We use do-while loop to input our "sentence" into a string. We could use just getline(cin, s);, but if you pressed enter-key once, it would stop your program.
Next thing, we use function combination of functions remove and erase: As the beginning parameter we use function remove, which finds all the spaces in the string, pushes them to the end of the container (in our case string s), and returns beginning iterator of that "pushing", and the second parameter tells us to remove every single element of container from that beginning iterator to the end.
We just print out the string, but now without spaces!
I think this is really simple way to do it, but if it can't be useful to you, I am sorry for wasting your time reading all of this! :)
I am learning C++ using the book C++ Primer.
In Section 1.4.3, the following example code about reading the unknown number of inputs is given.
#include <iostream>
int main()
{
int sum = 0, value = 0;
// read until end-of-file, calculating a running total of all values read
while (std::cin >> value)
sum += value; // equivalent to sum = sum + value
std::cout << "Sum is: " << sum << std::endl;
return 0;
}
According to the book, if we give an input of 3 4 5 6, the output will be Sum is: 18
But when I try this on my computer(Windows 10 with MinGW), The code does not end. It just keeps on asking for input even if I enter a newline. It works only when I enter a non-int input like f.
Is this expected? If yes, is there any code that stops after inputting a newline?
I am quite new to c++ and I have already learned python, so getting stuck so early on is quite frustrating.
Thanks and regards.
You need to terminate your input by an End-Of-File-character (i.e. CTRL-Z on Windows, CTRL-D on Mac/Unix), not just by an End-Of-Line (i.e. Enter).
A simple Enter is interpreted as white space, which will be simply ignored by operator>> when reading into an integral data type.
CTRL-Z / End-Of-File, in contrast, makes any operator>> fail with an error.
See also this SO answer.
Note: Entering f will also terminate your loop, since f is not considered a valid integral number; Hence, std::cin >> value with value being of type int and an input like f will fail as well. To be more accurate: operator>> actually returns a reference to the input stream, but if reading in a value fails, failbit is set on the stream, and then interpreting the stream object in a boolean expression (implicitly calling basic_istream::operator bool()) returns false; So maybe the author of the book did not want to explain these details at the respective section in the book :-)
Is this expected?
Yes, as operator>> ignores leading whitespace by default, which includes line breaks.
If yes, is there any code that stops after inputting a newline?
Use std::cin.getline() or std::getline() instead of operator>>. You can then use operator>> with a std::istringstream to parse values from each line, eg:
#include <iostream>
#include <string>
#include <sstream>
int main()
{
std::string line;
int sum, value;
do
{
std::cout << "Enter a set of numbers, or a blank line to exit: ";
if (!std::getline(std::cin, line) || line.empty())
break;
// read until end-of-line, calculating a running total of all values read
std::istringstream iss(line);
sum = 0;
while (iss >> value)
sum += value; // equivalent to sum = sum + value
std::cout << "Sum is: " << sum << std::endl;
}
while (true);
return 0;
}
Live Demo
Is this expected?
Yes, Thats what while (std::cin >> value) does. See this answer for more explanations: How is "std::cin>>value" evaluated in a while loop?
is there any code that stops after inputting a newline?
No, as >> simply ignore a white space(also #StephanLechner mentioned it)
What you can do instead is:
Just give a condition; if it satisfies just break the loop. you
can also provide a console out to make it more understandable to the
user. For example:
std::cout << "Enter value to sum or press -1 to exit" << std::endl;
while (std::cin >> value && value != -1) // if value == -1, loop stops.
{
sum += value;
}
You can simply terminate by the end of character:
CTRL-Z on Windows
CTRL-D on Mac/Unix
I'm supposed to make a program that counts the number of people in each age group:
0-16 (including 16) is infant
16-29 is young
29-55 is middle
55-75 is old
75+ is really old
The intervals are closed to the left and open to the right.
I wrote a program that compiles, but does not give me the correct values. I'm new at coding so can anyone point me in the right direction? Here is what I have:
#include <iostream>
using namespace std;
main()
{
int countinfant, countyoung, countmiddle, countold, countreallyold;
char age;
countinfant=0;
countyoung=0;
countmiddle=0;
countold=0;
countreallyold=0;
cout<< "Please Enter Ages. To end, enter *\n";
cin.get(age);
while (age>0 && age != '*')
{
if (age>=0 && age<=16) countinfant = countinfant + 1;
if (age>16 && age<=29) countyoung = countyoung + 1;
if (age>29 && age<=55) countmiddle = countmiddle + 1;
if (age>55 && age<=75) countold = countold + 1;
if (age>75 && age>=76) countreallyold = countreallyold + 1;
cin.get(age);
}
cout<< "\n The Number of Infant's Are: " << countinfant;
cout<< "\n The Number of Young's Are: " << countyoung;
cout<< "\n The Number of Middle's Are: " <<countmiddle;
cout<< "\n The Number of old's Are: " <<countold;
cout<< "\n The Number of Really Old's Are: " <<countreallyold;
cout<<endl;
return 0;
}
Actually your problem is very easy to figure out once I looked closer at the code.
The get function of input streams read a single character and not numbers. So if you enter the character 5 as input it will be read and stored in age as a character, and if the encoding used on your system is ASCII encoding (which is the most common these days) then the value for the character '5' is the integer 53.
You then proceed to use the character you have read as an integer, which as it is encoded will give you the wrong results.
To get the correct values you need to read an integer, however since you want to check for the asterisk to end the input you can't use normal integer input with the >> operator, which is why you used get I guess. The solution is to use strings and check the string for the asterisk, and if not an asterisk convert the string to an integer.
Something like
std::string input;
while (std::cin >> input && input != "*")
{
int age = std::stoi(input);
...
}
It does not work because you declared age as a char. The program reads the input as a char, so if you enter 0, the value in age will be the ASCII code of the character 0, which is 48 (0x30). You need to declare it as int age; and for the exit condition simply enter a negative value, e.g. -1, don't use the '*'.
I am fairly new to programming and have to create a program which reads the prompt: "I have 8 dollars to spend." It then needs to print out with each word on a separate line, and then if any of the strings is numeric, it needs to be divided by 2. Therefore it should end up printing out as:
I
have
4
dollars
to
spend.
I have managed to do everything, except finding the numeric value and dividing it by 2. So far I have this:
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int main()
{
string prompt;
string word;
cout << "Prompt: ";
getline(cin, prompt);
stringstream ss;
ss.str(prompt);
while (ss >> word)
{
cout << word << endl;
}
return 0;
}
After looking through various other posts, I cannot manage to get this to work. I'm assuming its an if/else statement within the while loop along the lines of, if numeric, set int num to num / 2 then cout << num << endl;, else cout << word << endl;, but I can't figure it out.
Thanks in advance.
You can use the stringstream class, which handles conversions between strings and other data types, to attempt to convert a given string to a number. If the attempt is successful, you know
The stringstream object allows you to treat a string as though it is a stream similar to cin or cout.
Incorporate this into your while loop, like so:
while (ss >> word)
{
int value = 0;
stringstream convert(word); //create a _stringstream_ from a string
//if *word* (and therefore *convert*) contains a numeric value,
//it can be read into an _int_
if(convert >> value) { //this will be false if the data in *convert* is not numeric
cout << value / 2 << endl;
}
else
cout << word << endl;
}
The strtol (C++11 version that works on std::string directly: std::stol) function is really good for testing whether a string holds a number, and if so, what the numeric value is.
Or you could continue using iostreams like you have been... try extracting a number (int or double variable), and if that fails, clear the error bit and read a string.
I dont have 50 rep so I cant comment, thats why I'm writing it as answer.
I think you can check it character by character, using Ascii value of each char, & if there are ascii values representing numbers between two spaces(two \n in this case as you've already seperated each word), then you have to divide the number by 2.