How to read multiple files on C++ - c++

My problem is :
First read a file named symbols.txt. This file consist of many
lines, each line consist of 2 elements : an uppercase letter and a
string, this file is ended by a hash(#).
Second read a file named dict.txt. This file consist of many
words(string) . Ended by a hash(#)
Third read a file named handin.txt. This file consist of some
numbers which you're gonna working on it. Ended by a hash(#)
Print your output in a file named handout.txt
This is my code but I'm not sure that I let in read the input right. Please check it for me. Thanks a lot.
#include<bits/stdc++.h>
using namespace std;
int main() {
freopen("symbols.txt" , "r" , stdin);
// input the letter and the string
char X ; string Y ;
while(cin >> X >> Y && X != '#' ) {
// my code goes here
}
freopen("dict.txt" , "r" , stdin) ;
// input the strings here
freopen("handin.txt", "r" , stdin);
// input the numbers here
/ *
Here is my code
* /
freopen("handout.txt" , "w" , stdout);
// let in print the output here
}

#include<bits/stdc++.h>
Don't do this. Here's why
using namespace std;
Don't do this either. Here's why
freopen("symbols.txt" , "r" , stdin);
This is very bad! You're using std::freopen to associate a file with stdin. Then later on, you're using std::cin to read from the file. What you're doing is very "hacky" and this might work sometimes but not always. stdin (from C) and std::cin (from C++) are not required to be linked like this. freopen is a C API so you shouldn't use it in C++ anyway.
What you should do is open an input file stream (std::ifstream) and read from that. That might look a little bit like this:
#include <string> // std::string
#include <fstream> // std::ifstream std::ofstream
#include <iostream> // std::cerr
int main() {
std::ifstream symbols("symbols.txt");
if (!symbols.is_open()) {
// There was a problem opening the symbols file
// Maybe it was missing
// You should end the program here and write an error message
std::cerr << "Failed to open \"symbols.txt\"\n";
// returning an error code of 0 means "everything is fine"
// returning anything else means "something went wrong"
return 1;
}
// Try to choose more descriptive names than "X" and "Y"
char X;
std::string Y;
while (symbols >> X >> Y && X != '#') {
// ...
}
// ...
}
You code will be clearer if you create a new std::ifstream for each file you open (rather than reusing the same one). Error checking is important. You should make sure to check that the file actually opened before using it. To write your output to "handout.txt", you would use an output file stream (std::ofstream) instead.
There's something that might trip you up. Take this "symbols.txt" file:
A many words
B on the same line
C could cause problems
#
If we try to read it using the current code, we run into trouble:
symbols >> X >> Y;
// X is 'A'
// Y is "many" rather than "many words" as you might expect
If there's only one word on each line then this shouldn't be an issue, but if there are multiple words, then you might need to use std::getline. std::getline does what it says on the tin. It reads the whole line and writes it to the given string.
You'd use it like this:
while (symbols >> X && X != '#' && std::getline(symbols, Y)) {
// ...
}
Please make sure you understand the code (read some of the links) before you copy it off of StackOverflow.

Related

Filling a cstring using <cstring> with text from a textfile using File I/O C++

I began learning strings yesterday and wanted to manipulate it around by filling it with a text from a text file. However, upon filling it the cstring array only prints out the last word of the text file. I am a complete beginner, so I hope you can keep this beginner friendly. The lines I want to print from the file are:
"Hello World from UAE" - First line
"I like to program" - Second line
Now I did look around and eventually found a way and that is to use std::skipary or something like that but that did not print it the way I had envisioned, it prints letter by letter and skips each line in doing so.
here is my code:
#include <fstream>
#include <iostream>
#include <cstring>
#include <cctype>
using namespace std;
int main() {
ifstream myfile;
myfile.open("output.txt");
int vowels = 0, spaces = 0, upper = 0, lower = 0;
//check for error
if (myfile.fail()) {
cout << "Error opening file: ";
exit(1);
}
char statement[100];
while (!myfile.eof()) {
myfile >> statement;
}
for (int i = 0; i < 30; ++i) {
cout << statement << " ";
}
I'm not exactly sure what you try to do with output.txt's contents, but a clean way to read through a file's contents using C++ Strings goes like this:
if (std::ifstream in("output.txt"); in.good()) {
for (std::string line; std::getline(in, line); ) {
// do something with line
std::cout << line << '\n';
}
}
You wouldn't want to use char[] for that, in fact raw char arrays are hardly ever useful in modern C++.
Also - As you can see, it's much more concise to check if the stream is good than checking for std::ifstream::fail() and std::ifstream::eof(). Be optimistic! :)
Whenever you encounter output issues - either wrong or no output, the best practise is to add print (cout) statements wherever data change is occurring.
So I first modified your code as follows:
while (!myfile.eof()) {
myfile >> statement;
std::cout<<statement;
}
This way, the output I got was - all lines are printed but the last line gets printed twice.
So,
We understood that data is being read correctly and stored in statement.
This raises 2 questions. One is your question, other is why last line is printed twice.
To answer your question exactly, in every loop iteration, you're reading the text completely into statement. You're overwriting existing value. So whatever value you read last is only stored.
Once you fix that, you might come across the second question. It's very common and I myself came across that issue long back. So I'm gonna answer that as well.
Let's say your file has 3 lines:
line1
line2
line3
Initially your file control (pointer) is at the beginning, exactly where line 1 starts. After iterations when it comes to line3, we know it's last line as we input the data. But the loop control doesn't know that. For all it knows, there could be a million more lines. Only after it enters the loop condition THE NEXT TIME will it come to know that the file has ended. So the final value will be printed twice.

How to read data from an open pipe: example needed

could anyone provide a small example or direct me to proper reading material in order to solve the following problem:
ls | ./myprog
What I would like to achieve is that my program reads information from ls and just print it on the screen.
I need c++ example, and if possible to do this through boost lib
thnx
P.S.
Thank you all it worked
In C, all you need to do is read the file descriptor 0:
read(0, …, …);
In C++, you can do this by using std::cin:
#include <iostream>
int main() {
std::cin >> /* a variable you want to direct the input to */
return 0;
}
That's standard C++ that is fully compatible with boost. For the way to use it, I leave it to you to read more on the manual and the plethora of examples you can find online.
for opening a file or reading from stdin you can do something in the following fashion:
shared_ptr<istream> input;
if (filename == "-" || filename == "")
input.reset(&cin, [](...){});
else
input.reset(new ifstream(filename.c_str()));
// ...
(answer copied from https://stackoverflow.com/a/2159469/1290438)
Basically, if you don't give a filename parameter, you consider data comes from stdin. That's the way cat works.
this code matches exactly your Problem:
#include <iostream>
using namespace std;
int main()
{
while (true)
{
string x;
cin >> x;
cout << x << endl;
}
}
you have to put this code into your "myprog" cpp file and then type the command you've mentioned.
It simply puts the input from the ls program to your screen

C++ File I/O Tab separated data

I have a text file with numbers as follows:
num1 TAB num2 TAB.... num22 newline
.
.
.
I would like to read num1 check to see if it is equal to 3 and if yes copy the entire row to a new file. What is the fastest way to do this? The file is quite big 80Mb+. Also, num 1 is repetitive, i.e it goes from 0 to 3 in steps of 0.001. So I just have to read every so many steps. I am not sure how to tell the computer to a-priori skip x-lines?
Thanks.
Given you've said that runtime performance is not a primary concern, then the following is clear and concise:
#include <string>
#include <fstream>
void foo(std::string const& in_fn, std::string const& out_fn)
{
std::ifstream is(in_fn);
std::ofstream os(out_fn);
std::string line;
while (std::getline(is, line))
if (line.size() && std::stoi(line) == 3)
os << line << '\n';
}
(C++11 support assumed; error handling omitted for brevity.)
pseudo code can looks like this:
while (not eof) {
fgets(...);
find TAB symbol or end of line
get string between two marks
cleain it from spaces and other unnecessary symbols
float fval = atof(...);
if (fval == 3) {
write the string into new file
}
}

What's the correct way to read a text file in C++?

I need to make a program in C++ that must read and write text files line by line with an specific format, but the problem is that in my PC I work in Windows, and in College they have Linux and I am having problems because of line endings are different in these OS.
I am new to C++ and don't know could I make my program able read the files no matter if they were written in Linux or Windows. Can anybody give me some hints? thanks!
The input is like this:
James White 34 45.5 10 black
Miguel Chavez 29 48.7 9 red
David McGuire 31 45.8 10 blue
Each line being a record of a struct of 6 variables.
Using the std::getline overload without the last (i.e. delimiter) parameter should take care of the end-of-line conversions automatically:
std::ifstream in("TheFile.txt");
std::string line;
while (std::getline(in, line)) {
// Do something with 'line'.
}
Here's a simple way to strip string of an extra "\r":
std::ifstream in("TheFile.txt");
std::string line;
std::getline(input, line));
if (line[line.size() - 1] == '\r')
line.resize(line.size() - 1);
If you can already read the files, just check for all of the newline characters like "\n" and "\r". I'm pretty sure that linux uses "\r\n" as the newline character.
You can read this page: http://en.wikipedia.org/wiki/Newline
and here is a list of all the ascii codes including the newline characters:
http://www.asciitable.com/
Edit: Linux uses "\n", Windows uses "\r\n", Mac uses "\r". Thanks to Seth Carnegie
Since the result will be CR LF, I would add something like the following to consume the extras if they exist. So once your have read you record call this before trying to read the next.
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
If you know the number of values you are going to read for each record you could simply use the ">>" method. For example:
fstream f("input.txt" std::ios::in);
string tempStr;
double tempVal;
for (number of records) {
// read the first name
f >> tempStr;
// read the last name
f >> tempStr;
// read the number
f >> tempVal;
// and so on.
}
Shouldn't that suffice ?
Hi I will give you the answer in stages. Please go trough in order to understand the code.
Stage 1: Design our program:
Our program based on the requirements should...:
...include a definition of a data type that would hold the data. i.e. our
structure of 6 variables.
...provide user interaction i.e. the user should be able to
provide the program, the file name and its location.
...be able to
open the chosen file.
...be able to read the file data and
write/save them into our structure.
...be able to close the file
after the data is read.
...be able to print out of the saved data.
Usually you should split your code into functions representing the above.
Stage 2: Create an array of the chosen structure to hold the data
...
#define MAX 10
...
strPersonData sTextData[MAX];
...
Stage 3: Enable user to give in both the file location and its name:
.......
string sFileName;
cout << "Enter a file name: ";
getline(cin,sFileName);
ifstream inFile(sFileName.c_str(),ios::in);
.....
->Note 1 for stage 3. The accepted format provided then by the user should be:
c:\\SomeFolder\\someTextFile.txt
We use two \ backslashes instead of one \, because we wish it to be treated as literal backslash.
->Note 2 for stage 3. We use ifstream i.e. input file stream because we want to read data from file. This
is expecting the file name as c-type string instead of a c++ string. For this reason we use:
..sFileName.c_str()..
Stage 4: Read all data of the chosen file:
...
while (!inFile.eof()) { //we loop while there is still data in the file to read
...
}
...
So finally the code is as follows:
#include <iostream>
#include <fstream>
#include <cstring>
#define MAX 10
using namespace std;
int main()
{
string sFileName;
struct strPersonData {
char c1stName[25];
char c2ndName[30];
int iAge;
double dSomeData1; //i had no idea what the next 2 numbers represent in your code :D
int iSomeDate2;
char cColor[20]; //i dont remember the lenghts of the different colors.. :D
};
strPersonData sTextData[MAX];
cout << "Enter a file name: ";
getline(cin,sFileName);
ifstream inFile(sFileName.c_str(),ios::in);
int i=0;
while (!inFile.eof()) { //loop while there is still data in the file
inFile >>sTextData[i].c1stName>>sTextData[i].c2ndName>>sTextData[i].iAge
>>sTextData[i].dSomeData1>>sTextData[i].iSomeDate2>>sTextData[i].cColor;
++i;
}
inFile.close();
cout << "Reading the file finished. See it yourself: \n"<< endl;
for (int j=0;j<i;j++) {
cout<<sTextData[j].c1stName<<"\t"<<sTextData[j].c2ndName
<<"\t"<<sTextData[j].iAge<<"\t"<<sTextData[j].dSomeData1
<<"\t"<<sTextData[j].iSomeDate2<<"\t"<<sTextData[j].cColor<<endl;
}
return 0;
}
I am going to give you some exercises now :D :D
1) In the last loop:
for (int j=0;j<i;j++) {
cout<<sTextData[j].c1stName<<"\t"<<sTextData[j].c2ndName
<<"\t"<<sTextData[j].iAge<<"\t"<<sTextData[j].dSomeData1
<<"\t"<<sTextData[j].iSomeDate2<<"\t"<<sTextData[j].cColor<<endl;}
Why do I use variable i instead of lets say MAX???
2) Could u change the program based on stage 1 on sth like:
int main(){
function1()
function2()
...
functionX()
...return 0;
}
I hope i helped...

getline() returns empty line in Eclipse but working properly in Dev C++

Here is my code:
#include <iostream>
#include <stdlib.h>
#include <fstream>
using namespace std;
int main() {
string line;
ifstream inputFile;
inputFile.open("input.txt");
do {
getline(inputFile, line);
cout << line << endl;
} while (line != "0");
return 0;
}
input.txt content:
5 9 2 9 3
8 2 8 2 1
0
In Enclipse, it goes to infinite-loop. I'm using MinGW 5.1.6 + Eclipse CDT.
I tried many things but I couldn't find the problem.
Since you are on windows try:
} while (line != "0\r");
The last line is stored as "0\r\n". The \n is used as the line delimiter by getline so the actual line read will be "0\r"
or
you can convert the dos format file to UNIX format using command
dos2unix input.txt
Now your original program should work. The command will change the \r\n at the end of the line to \n
Also you should always do error checking after you try to open a file, something like:
inputFile.open("input.txt");
if(! inputFile.is_open()) {
cerr<< "Error opening file";
exit(1);
}
It will create an infinite loop if no line contains exactly 0. For example 0\n is not the same thing as 0. My guess is that that is your problem.
EDIT: To elaborate, getline should be discarding the newline. Perhaps the newline encoding of your file wrong (i.e. windows vs. unix).
Your main problem is working directory.
Because you are specifying a file using a relative path it searches for the file from the current working directory. The working directory can be specified by your dev environment. (Note: The working directory is not necessarily the same directory where the executable lives (this is a common assumption among beginners but only holds in very special circumstances)).
Though you have a special end of input marker "0" you should also check that the getline() is not failing (as it could error out for other reasons (including beady formatted input). As such it is usually best to check the condition of the file as you read it.
int main()
{
string line;
ifstream inputFile;
inputFile.open("input.txt");
while((getline(inputfile, line)) && (line != "0"))
{
// loop only entered if getline() worked and line !="0"
// In the original an infinite loop is entered when bad input results in EOF being hit.
cout << line << endl;
}
if (inputfile)
{
cout << line << endl; // If you really really really want to print the "0"
// Personally I think doing anything with the termination
// sequence is a mistake but added here to satisfy comments.
}
return 0;
}