I have written the following code. What I did is this
opened a file "Numbers.dat" and asked input from console
then separated the numbers in separate even and odd files
#include <fstream>
#include <iostream>
int main() {
std::ofstream numWrite("Numbers.dat");
int temp;
while(std::cin>>temp){
numWrite<<temp<<std::endl;
}
numWrite.close();
std::ofstream even("Even.dat"), odd("Odd.dat");
std::ifstream num("Numbers.dat");
while(num){
num>>temp;
if(temp%2==0)
even<<temp<<std::endl;
else
odd<<temp<<std::endl;
}
num.close();
even.close();
odd.close();
return 0;
}
I used newlines after every input, therefore I am having the extra newline in Numbers.dat file and when my program is reading that, it is giving an extra output to the even/odd files.
I can eliminate them by either removing newline from the numbers.dat file, or some check on the other code.
But I am unable to do that, please help!
Or if there is a better way, tell me that too!
Inputs:
1 2 3 4 5 6 7 8 9 10 a
OUTPUTS:
even.dat
2
4
8
10
10
odd.dat
1
3
5
7
9
Problem is this:
while(num){
num>>temp;
This should be done this way:
while(num>>temp){
For details see eof() bad practice?
Fancy way to address this is, by use of iterators and std::partition_copy
#include <fstream>
#include <iostream>
#include <iterator>
#include <algorithm>
int main() {
std::ifstream in("Numbers.dat");
std::ofstream even("Even.dat");
std::ofstream odd("Odd.dat");
std::partition_copy(
std::istream_iterator<int>{in}, {},
std::ostream_iterator<int>{even, " "},
std::ostream_iterator<int>{odd, " "},
[](auto x) { return x % 2 == 0; });
return 0;
}
https://godbolt.org/z/z4qcErPWd
I have the following code in VS:
#include <iostream>
#include <fstream>
using namespace std;
int main() {
ifstream inData;
int temp;
inData.open("test_file.txt");
do {
inData >> temp;
cout << temp << " ";
} while (!(inData.eof()));
inData.close();
return 0;
}
test_file.txt contains the following data (it's a single line):
1 2 3 4 5 6 7 8 9 0 10 11
When I built and ran this in VS, it worked fine. Today, when I tried to run it on CLion, it gives me garbage data. I tried creating a new project from scratch in CLion and copy-pasting just the code in main.cpp, but still gives me random data. And now I'm wasting my Saturday wrestling with my IDE instead of just finishing my homework. Any help?
I figured out what the issue is. CLion doesn't recognize the parameter as a path, whereas VS does.
I have an ASCII file (students.txt) that looks as follows (Ignore empty lines, they're an artifact of my unfamiliarity with this formatting tool):
stella 10 4.4 ...
peter 1.1 5 ...
That is, each line starts with a name, followed by one or more numbers.
The code snippet below is meant to read this file line by line, reading the name into a string and the numbers into a double, printing each of these in turn. When I run this on Ubuntu, it works fine and I get
stella 10 4.4
peter 1.1 5
However, when I run it on a Mac, I get the following:
stella 10 4.4
ter 1.1 5
When I change 'peter' to 'speter', however, it works fine...:
stella 10 4.4
speter 1.1 5
Any thoughts...?
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main() {
ifstream infile("students.txt");
string name;
double x;
while ( !infile.eof() ) {
infile >> name;
cout << name << ' ';
while ( infile >> x ){
cout << x << ' ';
}
cout << endl;
if (! infile.eof() )
infile.clear();
}
return 0;
}
When the input starts out divided into lines, it's usually easiest to read it by lines, then split those into the component pieces:
std::string line;
std::string name;
std::vector<double> values;
while (std::getline(infile, line)) {
std::istringstream buffer(line);
double temp;
buffer >> name;
while (buffer >> temp)
values.push_back(temp);
}
I'd be particularly interested why my snippet produces a different result on linux and mac...
I think this behavior is due to differences in how floating point inputs are handled in input streams in Libc++ vs. Libstdc++ (rather than Mac vs. Ubuntu)
You're most likely using Libc++ (LLVM/Clang's standard C++ library) on Mac since Apple deprecated Libstdc++ (the GNU standard C++ library that comes standard in Linux).
In this case, Libc++ will "eat" any characters that could potentially be converted into a double, while Libstdc++ will not (e.g. it "eats" the pe in peter because p and e could potentially be part of the representation of a double).
For example, if your students.txt looked like this:
0x1a 90.2 84.3
0x1a 1.5 56.4
When you compile your original program with Libstdc++ and run it, you get:
0x1a 90.2 84.3 0
x1a 1.5 56.4
While compiling it with Libc++ and running gives:
0x1a 90.2 84.3 26 1.5 56.4
Libc++ recognizes 0x1a as a hex number (26), while Libstdc++ only converts the 0 in 0x1a and parses x1a into the string name.
For a much more detailed explanation including examples, see https://github.com/tardate/LittleCodingKata/blob/master/cpp/DoubleTrouble/README.md
I have the following code that read input from txt file as follow
Paris,Juli,5,3,6
Paris,John,24,2
Canberra,John,4,3
London,Mary,29,4,1,2
my code is to load the data into map then I want to print the map content to make sure that it has been inserted correctly, I check the vaue of m as it is used during splitting the line. However, during the execution I get this as continues 0s which means it is never enter the while loop. I have used this part of code before and it works. I could not find where I've made the mistake.
#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>
#include <vector>
#include<map>
using namespace std;
struct info {
string Name;
int places;// i will use the binary value to identfy the visited places example 29 is 100101
// this means he visited three places (London,LA,Rome)
vector<int> times; // will represent the visiting time,e.g. 1,2,5 means london 1 time, LA
// twice and Rome five times
};
map<string,vector<info> > log;
map<string,vector<info> >::iterator i;
fstream out;
int main() {
out.open("log.txt", std::ios::in | std::ios::out | std::ios::app);
string line;
char* pt;
string temp[19];
// for each line in the file
while (!out.eof())
{
getline(out,line);//read line from the file
pt=strtok(&line[0],"," );//split the line
int m=0;
while (pt != NULL)
{
temp[m++] = pt; // save the line info to the array
cout<<m<<" ";
pt = strtok (NULL, ",");
}
cout<<m<<" "; // during the execution I get this as continues 0s which means it is never enter the while loop
info tmp;
// read the other data
tmp.Name=temp[1];
tmp.places=atoi(temp[2].c_str());
for ( int i=3;i<=m;i++)
{
tmp.times.push_back(atoi(temp[i].c_str()));
}
// create a new object
log[temp[0]].push_back(tmp);
}
vector<int>::iterator j;
for(i=log.begin();i!=log.end();i++) {
cout<< "From "<< i->first<<" city people who travels: "<<endl;
for (size_t tt = 0; tt < (i->second).size(); tt++) {
cout<< (i->second[tt]).Name<< " went to distnations "<< (i->second)[tt].places<<" \nwith the folloing number of visiting time ";
for (j=((i->second[tt]).times).begin();j!= ((i->second[tt]).times).end();j++)
cout<<*j<<" ";
}
}
system("PAUSE");
return 0;
}
This is an error
// for each line in the file
while (!out.eof())
{
getline(out,line);//read line from the file
should be
// for each line in the file
while (getline(out,line))
{
I find it frankly incredible how often this error is repeated. eof does not do what you think it does. It tests if the last read failed because of end of file. You are using it to try and predict whether the next read will fail. It simply doesn't work like that.
This line is an error
pt=strtok(&line[0],"," );//split the line
strtok works on C strings, there's no guarantee it will work on std::string.
But neither of these are likely to be your real error. I would suggest opening the file with ios::in only. After all you only want to read from it.
Your fstream should not open in app mode. That will seek the file to the end of file. Delete std::ios::app from it.
You can't tokenize an std::string using strtok. Use getline instead:
std::string str("some,comma,separated,data");
std::string token;
while (getline(str, token, ',')) {
cout << "Token: " << token << end;
}
At each iteration, token contains the next parsed token from str.
This is wrong temp[m++] = pt; // save the line info to the array
Switch to something like this, instead of "temp"
std::vector<std::string> vTemp;
pt=strtok(&line[0],"," );//split the line
while (pt != NULL)
{
vTemp.push_back(pt); // save the line info to the array
pt = strtok (NULL, ",");
}
Also consider using something like this to do the split.
std::vector<std::string> SplitString(const std::string &strInput, char cDelimiter)
{
std::vector<std::string> vRetValue;
std::stringstream ss(strInput);
string strItem;
while(std::getline(ss, strItem, cDelimiter))
{
// Skip Empty
if(strItem.size()==0)
continue;
vRetValue.push_back(strItem);
}
return vRetValue;
}
#halfelf really great solution for my simple error, it works but the problem is now when I print the data I got this
From Paris city people who travels:
Juli went to distnations 5
with the folloing number of visiting time 3 6 0
John went to distnations 24
with the folloing number of visiting time 2 6
From Canberra city people who travels:
Johnwent to distnations 4
with the folloing number of visiting time 3 6
From London city people who travels:
Mary went to distnations 29
with the folloing number of visiting time 4 1 2 0
This is not correct as 6 is added to John from Canberra and Paris and 0 is added to Juli and Mary.
any idea of where I get it wrong ,, its about the times vector , its seems that I need to reset the value for each line or clear the content after the insertion. what about the extra 0?
Example of Textfile:
5 <- I need to edit this number.
0
1
0
6
(Sample Code Not Whole Program)
#include <fstream>
#include <iostream>
using namespace std;
int main() {
int i;
cin>>i;
std::fstream file("example.txt", std::ios::in | std::ios::out | std::ios::app);
file.seekp(0);
file << i;
return 0;
}
With this code the number is added here:
(example.txt)
5
0
1
0
67 <<
Please note that from the bottom the numbers will keep increasing so it has to be always the first line not that specific 5.
Please Help
Thanks
You have opened the file in a mode that requests that all new data is appended to the end of the file (std::ios::app). Don't specify that flag if you don't want to always append.
Note that you will encounter problems if the new line you're writing is not exactly the same length as the existing line. In the case where it's a different length, you will have to copy and rewrite the entire remainder of the file.