Cannot Print All Integer Values - c++

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;
}

Related

sstream string wrong output

I am trying to read a string of three number using sstream but when I try to print them, I am getting a wrong output with four numbers.
Code:
#include <iostream>
#include <sstream>
using namespace std;
int main() {
string a("1 2 3");
istringstream my_stream(a);
int n;
while(my_stream) {
my_stream >> n;
cout << n << "\n";
}
}
Output:
1
2
3
3
Why I get four numbers in the output compared to three numbers in input string?
Here
while ( my_stream )
my_stream is convertible to bool and returns true if there's no I/O error.
See: https://en.cppreference.com/w/cpp/io/basic_ios/operator_bool
So, after the last reading, there's no I/O error yet, so it iterates again and there's an error and nothing is read into n in this statement:
my_stream >> n;
And, std::cout prints the last extracted value again i.e. 3.
The solution could be to directly check I/O error after reading in while (preferred):
while ( my_stream >> n )
{
std::cout << n << '\n';
}
or, print only if the reading is successful using an if:
while ( my_stream )
{
if ( my_stream >> n ) // print if there's no I/O error
{
std::cout << n << '\n';
}
}
Example (live):
#include <iostream>
#include <sstream>
int main()
{
std::string a { "1 2 3" };
std::istringstream iss{ a };
int n {0};
while ( iss >> n )
{
std::cout << n << '\n';
}
return 0;
}
Output:
1
2
3
Relevant: Why is "using namespace std;" considered bad practice?
You are printing the data before checking if readings are successful.
while(my_stream) {
my_stream >> n;
should be
while(my_stream >> n) {
Related (doesn't seem duplicate because eof() isn't used here):
c++ - Why is iostream::eof inside a loop condition (i.e. while (!stream.eof())) considered wrong? - Stack Overflow

File reading and Manipulation

I have a text file:
1
2
3
stop
4
The code has to add each number to the previous number to get a new value and it needs to stop when it reads the "stop" in the file.
For example output would be:
1
3
5
Reading has stopped
How can I break the code for my output to be like this?
The "reading has stopped", only has to appear when there is a 'stop' in the file. otherwise the output should just be numbers.
You can read each piece of the file into a string and end if the input is "stop". If the input isn't "stop" you can convert it to an int using std::stoi
#include <string>
#include <iostream>
#include <fstream>
int main() {
std::string numberString;
std::ifstream file{ "filename.txt" };
int previousNumber = 0;
while (file >> numberString)
{
if(numberString == "stop")
{
break;
}
try {
int number = std::stoi(numberString);
std::cout << (number + previousNumber) << " ";
previousNumber = number;
} catch(...) {
std::cout << "invalid number" << std::endl;
}
}
file.close();
std::cout << "Reading has stopped" << std::endl;
}
If your text file has only one string "stop", then there's a very easy solution: you just keep reading integers until the reading fails
int main() {
ifstream ifs("test.txt");
int first = 0;
int second;
while (ifs >> second) {
cout << first + second << ' ';
first = second;
}
cout << "Reading has stopped" << endl;
return 0;
}
The problem with this solution is that if you have other strings in the text file and you want to handle them in a different way, this solution will fail.
Hope it helps.

acquiring string output when i hit enter when input is finished

#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.

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;
}

how can I change a file content in c++?

I have this program that changes negative numbers to positive in my file.
It works, but negative numbers in the file don't change.
for example, if I have this numbers in my file : 12 2 -3 -1
when I run the program, the sum of numbers will be 18, but when I open my file again, I see
12 2 -3 -1 . What should I do to see 12 2 3 1 ?
here is my code:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
string name;
cin >> name;
int number;
int num=0;
ifstream myFile(name, ios::in);
ofstream mine(name, ios::app);
while(myFile >> number)
{
num += (number<0 ? -number : number);
mine << num;
}
cout << "num = " << num << endl;
system("pause");
return 0;
}
Opening the file for reading and writing for the same time is generally not a bad idea. You probably got an I/O error during opening mine, but since you didn't check it, the program ignored your writes silently. Try reading the file contents first (to a vector for example), then close the file for reading and open again for writing (not appending, because that would leave the old contents in the file).
When writing the values back to the file, also write whitespace after the number, otherwise you'll just get a string of digits in the file but you won't know where one begins and another ends.
Your program now doesn't "change negative numbers to positive" but it prints the cumulative sum of absolute values to the file.
Try writing to the standard output first so you won't ruin your file while you are testing. If it works, then change cout to your output stream.
Here is the code.
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <cstdlib>
using namespace std;
int main()
{
string name;
cin >> name;
int number;
int num=0;
ifstream myFile(name, ios::in);
vector<int> vec;
while(myFile >> number)
{
vec.push_back(abs(number));
}
ofstream mine(name, ios::out);
for (vector<int>::iterator it = vec.begin(); it != vec.end(); ++it) {
num += *it;
mine << *it << " ";
}
cout << "num = " << num << endl;
return 0;
}
Opening a read and write file streams for the same file and process at the same time is inviting file corruption. Use ostringstream to store the values read from the file. The values
from the file are read, and the values stored in the ostringstream
buffer. The ifstream object is closed before re-opening the file with
an ofstream object so that the buffer contents can be saved.
Note the ios::app flag has been removed. Otherwise the new values
will append to the existing values.
abs() function is used to write back the absolute values - this
forces all values positive.
#include<sstream>
int main()
{
string name;
cin >> name;
int number;
int num=0;
ifstream myfile(name.c_str(), ios::in);
ostringstream oss;
while (myfile >> number)
{
num += (number<0 ? -number : number);
oss << abs(number) << " ";
}
myfile.close();
ofstream mine(name.c_str());
cout << "num = " << num << endl;
mine << oss.str();
return 0;
}
string name;
cin >> name;
int number=0;
int sum=0;
string outname=name+".pos.txt";
ifstream myFile(name,ifstream::in);
ofstream mine(outname, ofstream::out );
while(myFile >> number)
{
number= (number<0 ? -number : number);
sum+=number;
mine << number<<' ';
}
myFile.close();
mine.close();
cout << "sum = " << sum << endl;
system("pause");