acquiring string output when i hit enter when input is finished - c++

#include <iostream> // to generate the hexadecimal representation of a number
#include<string>
using std::string;
int main()
{
const string hexdigits("0123456789ABCDEF"); //possible hexdigits
std::cout << "enter the series of numbers between 0 and 15"
<< "separated by space. Hit enter when finished: "
<< std::endl; //line to be printed on screen
string result; // it will hold hexadecimal representation of the number
string::size_type n; // undefined string variable will hold numbers
while (std::cin >> n) // input number with just spaces
{
if (n < hexdigits.size()) // compares n with hexdigits size
{
result += hexdigits[n]; // storing string output in result
}
}
std::cout << "your hex number is: " << result << std::endl; //output result
return 0;
}
when I press ENTER after input, the output hex is not automatically generated. I have to use escape sequence \n after input, to proceed to output. how can I get my output with just hitting ENTER after give input numbers?
I tried using getline to get the whole line and exit, as given below
while(std::getline(std::cin, n))
but it gave error E0304
no instance for overloaded function 'std::getline' matches the argument list".

You need to provide a std::string argument to getline. The conversion is not correct either in several ways, but there are a lot of examples that show how to convert a hex string to a number. For example:
#include <iostream>
#include <string>
#include "stdlib.h"
int main()
{
std::string line;
if (std::getline(std::cin, line))
{
unsigned int value = strtoul(line.c_str(), NULL, 16);
std::cout << "your hex number is: " << value << std::endl; //output result
}
return 0;
}

You're a bit confused about types and logic. Firstly while(std::getline(std::cin, n)) does not work because n is not a string, getline only works with strings. Secondly even if getline worked with numbers the logic would not be correct because you want to input a single line but a while loop with getline would input multiple lines.
The answer is to use getline once to input a single line and then use a while loop to convert each of the numbers in the single line. To do this you have to know how to read numbers from a string (instead of from the console). I guess this is the part you are missing.
Here's some sample code (untested)
#include <iostream>
#include <sstream>
#include <string>
int main()
{
const std::string hexdigits("0123456789ABCDEF"); //possible hexdigits
std::cout << "enter the series of numbers between 0 and 15"
<< "separated by space. Hit enter when finished: "
<< std::endl;
std::string line;
if (getline(std::cin, line)) // read a line
{
std::istringstream buf(line);
unsigned result = 0, n;
while (buf >> n) // read numbers from the line
{
if (n < hexdigits.size())
{
result += hexdigits[n];
}
}
std::cout << "your hex number is: " << result << std::endl;
}
return 0;
}
BTW try to avoid commenting the obvious, comments like // compares n with hexdigits size add nothing to your code.

Related

If an integer is entered into the StringStream, double it and print it

I need to be able to enter a sentence and have it spit back out. However, if a number is entered in the sentence, it should be output along with the words but it must be doubled.
I've tried implementing an if statement into my code to see if I could check if a number was entered, and if so print out that value in the stream *2, however this doesn't work because if I enter a number first then some text it breaks, if I don't enter the number as the second value of the sentence than it only prints the first word entered.
#include <string> // std::string
#include <iostream> // std::cout
#include <sstream>
using namespace std;
int main()
{
string sentence;
string word;
float val=0;
cout<<"Enter a sentence: ";
getline(cin, sentence);
stringstream ss;
ss.str(sentence);
while (ss >> word || ss >> val)
{
if (ss >> val)
{
cout << val * 2;
}
else
{
cout << word << endl;
}
}
return 0;
}
If I enter a sentence like "I walked 2 times today" then it should output it as:
I
walked
4
times today
But this would only be output as:
I
Solved the issue, had to use ss.eof() method to go to the end of the StreamString and stop and if a value that was entered into the string was a number, it would be printed out. My program was stopping when a certain if statement was met.

Checking if a string is a number, then converting that number to an int?

The 'program' is to take input in then spit the string back out on seperate lines and all numbers are to be multiplied by two in this case.
My issue occurs when a number is input after a white space.
Example
Sentence: 12 fish
Outputs:
24
fish
But...
Sentence: there are 12
Outputs:
there
are
0
The program I have written:
#include <iostream>
#include <string>
#include <sstream>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
using namespace std;
int main()
{
string str;
int number = 811;
cout << "Sentence: ";
getline(cin,str);
istringstream iss(str);
while(iss)
{
bool ree = 0;
string word;
iss >> word;
if(isdigit(word[0]))
{
stringstream(str) >> number;
number = (number * 2);
cout << number << endl;
ree = 1;
number = 911;
}
if(!ree)
{
cout << word << endl;
}
ree = 0;
}
}
Hopefully it's something small I am not seeing!
Thanks for the help in advanced.
The problem is that
stringstream(str) >> number;
creates a fresh string stream from the initial sentence, then tries to extract from it into number. Of course that will fail (as the first word in the sentence is not a number). If you wonder why number was set to 0, that's because on failure, the stringstream::operator>> zeros the argument (since C++11).
"If extraction fails, zero is written to value and failbit is set." ...
Before C++11, it left the argument unchanged. See the documentation for more details.
The correct way is to use a conversion from string to int (or long), namely std::stoi, and replace that line by
try{
number = std::stoi(word);
}
catch(std::exception& e){
std::cout << "error converting" << '\n';
}
Use stoi to parse the input like this:
int num = std::stoi(input);
using stoi is easy, and you can lazily catch the exception by the following:
if(!stoi(string)){
std::cout << "caught a non integer string" << endl;
}

Cannot Print All Integer Values

I would like to print integer values in a file by reading it.
The code:
int temp;
char* trainname;
trainname="dfg.txt";
ifstream trainfile;
trainfile.open(trainname);
if(!trainfile){
cout<<"Cannot open file!"<<'\n';
exit(1);
}
while(trainfile >> temp)
cout << temp << " ";
trainfile.close();
dfg.txt: 1 2 we er rf 5
output: 1 2
The problem is that it does not print 5.
Read to a temporary string first and then use std::stoi to try to parse an integer from it, and if it succeeds, output it:
std::string temp;
while(trainfile >> temp) {
try {
std::cout << std::stoi(temp) << " ";
}
catch(const std::invalid_argument&) {
// not a valid number
}
}
while(trainfile >> temp)
cout << temp << " ";
The above sets the failbit on trainfile on encountering any character that isn't whitespace or a digit. That terminates the loop. This is one reason I tend not to use formatted I/O that can fail on a input stream. I find it better to read text as text (not numbers) and then process the string that was just read. For example, see zenith's answer.
If you insist on doing everything from the input stream, you'll need an outer loop that clears the stream's failbit. For example,
while (! std::cin.eof())
{
while (std::cin >> temp)
{
std::cout << temp << " ";
}
std::cin.clear();
std::cin.ignore();
}
Given an input file containing 1 2 we er rf 5, the above will print 1 2 5. If the input file contains 1 2 abc345def 6, the above will print 1 2 345 6. Note that zenith's approach will print 1 2 6. Whether that 345 sandwiched between abc and def counts as an integer is up to you.
I'd recommend using zenith's solution over mine.
Update:
The above interprets abc345def as representing the integer 345. Both Zenith's solution and the above interpret 345def as representing the integer 345. To me, both abc345def and 345def should be rejected as representing an integer. So should 6.1 , but there's nothing wrong with 0x abc345def. There's nice tool in the C standard library, strtol, that nicely parses integers. It also indicates what made the parse stop. For a valid integer, it should stop at the end of the input string. With that,
#include <iostream>
#include < fstream>
#include <string>
#include <cstdlib>
int main ()
{
std::ifstream trainfile("dfg.txt");
if (!trainfile)
{
std::cerr << "Cannot open file!\n";
exit(1);
}
std::string s;
while(trainfile >> s)
{
char* end;
long num = std::strtol (s.data(), &end, 0);
if (!*end)
{
std::cout << num << " ";
}
}
trainfile.close();
std::cout << "\n";
}
string temp;
if( '0' <= temp[0] && temp[0]<='9' )
cout << temp << " ";
it will work i suppose.
Here is another way you can consider-
#include <iostream>
#include <sstream>
#include <fstream>
using namespace std;
int main()
{
ifstream trainname("dfg.txt",ios::in);
string temp;
getline(trainname,temp);
stringstream str;
str<<temp;
int extract_int;
while(getline(str, temp,' '))
{
if(stringstream(temp)>>extract_int)
cout<<extract_int<<" ";
}
return 0;
}
Or according to David Hammen's answer, you can solve it the following way-
#include <iostream>
#include <sstream>
#include <fstream>
using namespace std;
int main()
{
int temp;
char* trainname;
trainname="dfg.txt";
ifstream trainfile;
trainfile.open(trainname);
if(!trainfile){
cout<<"Cannot open file!"<<'\n';
exit(1);
}
while (!trainfile.eof())
{
while (trainfile>>temp)
cout<<temp<< " ";
trainfile.clear();
trainfile.ignore();
}
return 0;
}

How do I separate chars and integers from a string/file?

Assume that we are given input file in the following form:
12 a -5
T 23 -1 34 R K s 3 4 r
a a 34 12 -12 y
Now, we need to read the entire file and print the following:
number of integers
number of lowercase char
number of uppercase char
sum of all integers
Questions like this have always been a thorn in my flesh and I want to get this over with once and for all.
You need to parse the file:
1) separate raw text into tokens, then
2) "decide" if the token is a string, an integer, or "something else".
3) Count the results (#/integers, #/strings, etc)
Here's an example: Parse A Text File In C++
Here's the canonical textbook on the subject: The Dragon Book
Basically you want to parse the command line, open the file, parse each line token by token, and check the requirements for each token. I hope this helps.
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <stdlib.h>
using namespace std;
int main(int argc, char* argv[]) {
ifstream in(argv[1]);
string line, ch;
int int_count = 0, upper_count = 0, lower_count = 0, sum = 0;
/* Grab each line from file and place contents into line */
while(getline(in, line)) {
istringstream ss(line);
/* Parse each token in line */
while(ss >> ch) {
/* Is it a digit? */
if(isdigit(ch[0])) {
int_count++;
sum += atoi(ch.c_str());
}
/* If it's not, then it must be a char */
else {
if(isupper(ch[0]))
upper_count++;
else
lower_count++;
}
}
}
in.close();
cout << "Number of integers: " << int_count << endl;
cout << "Number of lowercase char: " << lower_count << endl;
cout << "Number of uppercase char: " << upper_count << endl;
cout << "Sum of all integers: " << sum << endl;
return 0;
}
Split by space
Check that it contains only 0-9, '-' and '.', if it does, it's probably a number. If it doesn't; probably some text.
Tally up as you go along.

Why is the C++ StringStream skipping the first number from an input file, but showing the rest?

Okay, so I have an input file input.txtthat contains a CSV sequence: 1,1,1,2,2,3,3,4,4
and I am trying to separate it at the commas using a stringstream; however I'm getting a little problem here. For some reason the first number from the sequence is not even getting read by the stream. To show this, I created a some debugging code to see what is happening and I found out that the first number is being stored inside csvLine and every other number is being read and coverted just fine. I don't understand why just the first number is being omitted. Below is an example pic showing exactly what I mean. num should have the same exact values and Line, but it's not. It has all the values except the first one, which is being stored inside csvLine. Why is this happening?!
#include <iostream>
#include <fstream>
#include <sstream>
using namespace std;
int main(int argc, const char * argv[]) {
ifstream file;
string line;
string csvLine; //comma seperated value line
int num = 0;
file.open(argv[1]);
if(file.is_open()) {
while(getline(file, line)) { //get the whole line and use string stream to break at commas
cout << "\nLine: " << line << endl;
//using stringstream to seperate at commas
stringstream ss(line);
while(getline(ss, csvLine, ',')) {
cout << "csvLine: " << csvLine << " " << endl;
//using stringstream to convert to int
ss >> num;
cout << "num: " << num << " " << endl;
}
}
}
return 0;
}
The problem arises since you're using getline and then extracting integer from your stringstream
You should only use getline
while(getline(ss, csvLine, ','))
{
cout << "csvLine: " << csvLine << " " << endl;
num = std::stoi( csvLine ) ;
}
When you read getline(ss, csvLine, ',') the first time it reads the number followed by the the ','. For the next numbers it just reads the comma as the number was already extracted using ss >> num. That is, the simplest fix is to only read everything up to and including the comma after the loop was executed. Since the value of string extracting the comma isn't used it makes sense to use ignore() instead of std::getline():
for (; ss >> num; ss.ignore(std::numeric_limits<std::streamsize>::max(), ',')) {
// do something with the number
}
Restructuring the loop this way has the added benefit that it is checked whether reading the number was successful.