i wrote a code in C++ where it opens a .txt file and reads its contents, think of it as a (MAC address database), each mac address is delimited by a (.), my problem is after i search the file for total number of lines , iam unable to return the pointer to the initial position of the file in here i use seekg() and tellg() to manipulate the pointer to the file.
here is the code:
#include <iostream>
#include <fstream>
#include <conio.h>
using namespace std;
int main ()
{
int i = 0;
string str1;
ifstream file;
file.open ("C:\\Users\\...\\Desktop\\MAC.txt");
//this section calculates the no. of lines
while (!file.eof() )
{
getline (file,str1);
for (int z =0 ; z<=15; z++)
if (str1[z] == '.')
i++;
}
file.seekg(0,ios::beg);
getline(file,str2);
cout << "the number of lines are " << i << endl;
cout << str2 << endl;
file.close();
getchar();
return 0;
}
and here is the contents of the MAC.txt file:
0090-d0f5-723a.
0090-d0f2-87hf.
b048-7aae-t5t5.
000e-f4e1-xxx2.
1c1d-678c-9db3.
0090-d0db-f923.
d85d-4cd3-a238.
1c1d-678c-235d.
here the the output of the code is supposed to be the first MAC address but it returns the last one .
file.seekg(0,ios::end);
I believe you wanted file.seekg(0,ios::beg); here.
Zero offset from the end (ios::end) is the end of the file. The read fails and you're left with the last value you read in the buffer.
Also, once you've reached eof, you should manually reset it with file.clear(); before you seek:
file.clear();
file.seekg(0,ios::beg);
getline(file,str2);
The error would have been easier to catch if you checked for errors when you perform file operations. See Kerrek SB's answer for examples.
Your code is making all sorts of mistakes. You never check any error states!
This is how it should go:
std::ifstream file("C:\\Users\\...\\Desktop\\MAC.txt");
for (std::string line; std::getline(file, line); )
// the loop exits when "file" is in an error state
{
/* whatever condition */ i++;
}
file.clear(); // reset error state
file.seekg(0, std::ios::beg); // rewind
std::string firstline;
if (!(std::getline(file, firstline)) { /* error */ }
std::cout << "The first line is: " << firstline << "\n";
Related
{
const char* fname = "myfile"; //or string fname ("str.txt") in C++11
string input; //our first look at the C++ string object
fstream myfile; //construct fstream object for file i/o
openfile(myfile, fname, ios_base::out); //open file for output (current contents lost)
std::transform(myfile.open(), myfile.end(), myfile.open(), ::toupper);
while (cout << "Enter a line ('q' to quit): " && getline(cin, input))
{
if (input == "q")
break;
else //exit while loop
myfile << input << endl; //pipe string we read file add new line character
}
myfile.close(); //close our file
std::transform(myfile.open(), myfile.end(), myfile.open(), ::toupper);
openfile(myfile, fname, ios_base::in); //reopen it for input
cout << "\nHere's whats in " << fname << ":\n";
while (getline(myfile, input)) //get and print all the lines
cout << input << endl;
system("pause");
}
Severity Code Description Project File Line Suppression State
Error (active) E0304 no instance of overloaded function "std::basic_fstream<_Elem, _Traits>::open [with _Elem=char, _Traits=std::char_traits<char>]" matches the argument list fileio2 C:\Users\burnsk\source\repos\Hello\fileio2\fileio2.cpp 14
Severity Code Description Project File Line Suppression State
Error (active) E0109 expression preceding parentheses of apparent call must have (pointer-to-) function type fileio2 C:\Users\burnsk\source\repos\Hello\fileio2\fileio2.cpp 14
std::transform(myfile.open()
That's not going to work. std::transform expects an input iterator range, typically some begin/end range. std::fstream::open doesn't return an iterator.
You probably want to look at std::istream_iterator<char>.
We'll do a quick code review of what you've posted. I've removed most of your comments, and we'll actually use that as our first critique. The comments don't help readability at all. You're just restating the line of code, which isn't a great comment. Comments that explain 'why' or fill in the information gaps that the code alone cannot explain are much better.
// Missing includes and main()
// This does not qualify as a Minimal, Reproducible Example
// Specifically, it's not reproducible, as it cannot be copy/pasted
// and ran by the people you want to get help from.
// https://stackoverflow.com/help/minimal-reproducible-example
{
const char* fname = "myfile"; // Hard-coded file name is meh, C-string also
string input; // Prefer this EVERYWHERE
fstream myfile;
openfile(myfile, fname, ios_base::out); // No explanation of this function
// It's not standard, you should
// have posted its code.
// Bad syntax, as explained. Refer to the documentation
// https://en.cppreference.com/w/cpp/algorithm/transform
std::transform(myfile.open(), myfile.end(), myfile.open(), ::toupper);
// Clever, but the user likely doesn't need to be prompted before
// every line. Instead, you could have checked for the end condition.
while (cout << "Enter a line ('q' to quit): " && getline(cin, input))
{
if (input == "q")
break; // This is the line that exits the loop
else //exit while loop
myfile << input << endl; // Premature write
}
myfile.close();
// See above about transform syntax being bad. But why write data
// you don't want, close the file, re-open the file, try to
// re-write the data, and close the file again?
std::transform(myfile.open(), myfile.end(), myfile.open(), ::toupper);
openfile(myfile, fname, ios_base::in); //reopen it for input
cout << "\nHere's whats in " << fname << ":\n";
while (getline(myfile, input)) //get and print all the lines
cout << input << endl;
system("pause");
}
Since you are reading the strings in, and not caring about the original contents, why not manipulate the string to look the way you want, and then write it to the file. It's a lot simpler.
My code below does that, and uses a few other tricks to avoid copy/pasta.
The biggest change is that the user is only told what to do once, and the while() loop Boolean expression grabs the line and ensures it's not the quit condition.
The string is then run through std::transform() and fully capitalized. And then it is written to the file. This writes the data we want one time, instead of writing a bunch of bad data and then doubling back and trying to fix it.
For printing the contents of the file to the screen, we create a new class that holds a string and changes how it can be read in, essentially reading an entire line at a time instead of a word. This is not necessary, but like I said, I put some stuff in to avoid a straight copy/paste/submit situation.
#include <algorithm>
#include <cctype>
#include <fstream>
#include <iostream>
#include <iterator>
#include <string>
namespace detail {
class Line {
std::string m_line;
public:
friend std::istream& operator>>(std::istream& sin, Line& line) {
std::getline(sin, line.m_line);
return sin;
}
operator std::string() const { return m_line; }
};
} // namespace detail
int main(int argc, char* argv[]) {
if (argc != 2) return 1;
std::ofstream fout(argv[1]);
if (!fout) {
std::cerr << "Error opening file for writing.\n";
return 2;
}
std::cout << "Type lines. Type \"q\" on its own line to quit.\n";
std::string line;
while (std::getline(std::cin, line) && line != "q") {
std::transform(line.begin(), line.end(), line.begin(),
[](const auto& c) { return std::toupper(c); });
fout << line << '\n';
}
fout.close();
std::ifstream fin(argv[1]);
if (!fin) {
std::cerr << "Error opening file for reading.\n";
return 3;
}
std::copy(std::istream_iterator<detail::Line>(fin),
std::istream_iterator<detail::Line>(),
std::ostream_iterator<std::string>(std::cout, "\n"));
fin.close();
}
Output:
❯ ./a.out text.txt
Type lines. Type "q" on its own line to quit.
You'll be back, time will tell
You'll remember that I served you well
Oceans rise, empires fall
We have seen each other through it all
And when push comes to shove
I will send a fully armed battalion to remind you of my love!
q
YOU'LL BE BACK, TIME WILL TELL
YOU'LL REMEMBER THAT I SERVED YOU WELL
OCEANS RISE, EMPIRES FALL
WE HAVE SEEN EACH OTHER THROUGH IT ALL
AND WHEN PUSH COMES TO SHOVE
I WILL SEND A FULLY ARMED BATTALION TO REMIND YOU OF MY LOVE!
I am trying to open a file and parse a file with separate functions.
when i parse the file, i want to read each line in my input file and i want to ignore any punctuation and make everything lowercase so that i can then print it out to a separate file into strings with no spaces or punctuation.
i have tried to implement it but i cannot figure out what i am doing wrong. I am not getting an error but my output is not correct.
this is my code:
#include <iostream>
#include <fstream>
#include <ostream>
#include <sstream>
#include <string>
using namespace std;
void processFile();
void parseFile(ifstream&, ofstream&);
int main()
{
//call function to open file and process
cout << "processing file" << endl;
processFile();
return 0;
}
void processFile()
{
string newString;
ifstream inFile;
ofstream outFile;
cout << "opening files" << endl;
// open files
inFile.open("inFile.txt");
outFile.open("outFile.txt");
cout << "parsing file" << endl;
//parse file for capitalization & punctuation
parseFile(inFile, outFile);
//close files
outFile.close();
inFile.close();
}
void parseFile(ifstream &inFile, ofstream &outFile)
{
//create and initialize variables
string newString;;
int i = 0;
if(!inFile)
{
cout << "ERROR!!! Cannot read file.";
}
else
{
do
{
//read each line in the input file until EOF
getline(inFile, newString, '\n');
//parse each string for punctuation
while(newString[i])
{
if(isalpha(newString[i])) //check each char in each
//string for punctuation
{
if(isupper(newString[i])) //check each string for
//capitalization
{
newString[i] = tolower(newString[i]); //convert
//string to
//lower case
}
outFile << newString[i]; //output each line to file
cout << newString[i];
}
i++;
if(newString[i] == '\n')
break;
}
} while(!inFile.eof());
}
}
this is my input:
racecar
RACEcar
rotator
rotor
civic
Red rum, sir, is murder!
Rats live on no evil star.
Neil, a trap! Sid is part alien!
Step on no pets.
Dammit, I’m mad!
my expected output is everything in the input printed in lowercase, without punctuation and spaces
this is my actual output:
racecarsirismurderraliena
You will need to initialize i after getline() . This is because each call of getline() will cause each line of data read from input file be overwritten (not appended) to the newString.
do
{
//read each line in the input file until EOF
getline(inFile, newString, '\n');
i = 0; // <== initialize 'i' to zero
//parse each string for punctuation
while(newString[i])
{
You need to reinitialize i after each call to getline(), otherwise it will continue at the offset where the previous string ended. getline() overwrites newString every time it's called.
do
{
//read each line in the input file until EOF
getline(inFile, newString, '\n');
i = 0;
//parse each string for punctuation
If you compare your input with your output it makes sense.
The first string "racecar" is parsed without problem. Now i is 7.
The next 4 calls to getline() get strings that are shorter than 7 so you get no new output in outFile.txt.
The call to getline() after that gets "Red rum, sir, is murder!", starting from 7 you get "sirismurder" and i is now 24.
The next call to getline() gets "Rats live on no evil star.", starting from 24 you get "r" and i is is now 26
The last call to getline() gets "Neil, a trap! Sid is part alien!", starting from 26 you get "alien".
I'm just learning about text file input/output. I have outputted a file which contains a header and 10 rows of data underneath it.
I now want to read this back to the main function. This works for me if I leave out the header in the text file, but if I leave the header in, I get an infinite loop.
How can I skip the 1st line (the header line) in reading this data back, or if possible, read back the header as well as the data?
Here is what I have so far:
void fileRead(int x2[], double y2[], int& n, char filename)
{
ifstream fin ("pendulum.txt"); // fin is an input file stream
if(!fin) //same as fin.fail()
{
cerr << "Failure to open pendulum.txt for input" << endl;
exit(1);
}
int j = 0, dummy = 0; //index of the first value j and dummy value
while(!fin.eof()) //loop while not end of file
{
fin >> dummy >> x2[j] >> y2[j];
cout << setw(5) << fixed << j
<< setw(12) << scientific << x2[j] << " "
<< setw(12) << y2[j] << endl; //print a copy on screen
j += 1;
}
fin.close(); //close the input file
}
You can first read the header of the file then the real contents you want as follows:
string line;
getline(fin, line);//just skip the line contents if you do not want header
while (fin >> dummy >> x2[j] >> y2[j] )
{ //^^if you do not always have a dummy at the beginning of line
//you can remove dummy when you read the rest of the file
//do something
}
Your best bet would be to use
fin.ignore(10000,'\n');
http://www.cplusplus.com/reference/istream/istream/ignore/
This will ignore the first 10000 character in the file, or ignore the characters until a newline is reached. The 10000 is fairly arbitrary and should be a number that will always be longer than the maximum line length.
man, this gentleman over there helped me quite a lot. You see, everyone says to use getline(); to skip one line, but the problem is that sometimes you dont want to store anything in a buffer, so ignore() makes much more sense to me. Well so I would like to back up our fella's answer by adding that, you could use " numeric_limits::max()" which will make it have no limit, it will ignore until it finds the delimiter...
`
#include <iostream>
#include <fstream>
#include <limits>
using std::streamsize;
int main() {
ifstream fin ("pendulum.txt");
fin.ignore(numeric_limits<streamsize>::max(),'\n');
}
`
http://www.cplusplus.com/reference/limits/numeric_limits/
I'm trying to create a word sorting program that will read the words in a .txt file and then write them to a new file in order from shortest words to longest words. So, for instance, if the first file contains:
elephant
dog
mouse
Once the program has executed, I want the second file (which is initially blank) to contain:
dog
mouse
elephant
Here's the code:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
string word;
ifstream readFrom;
ofstream writeTo;
readFrom.open("C:\\Users\\owner\\Desktop\\wordlist.txt");
writeTo.open("C:\\Users\\owner\\Desktop\\newwordlist.txt");
if (readFrom && writeTo)
{
cout << "Both files opened successfully.";
for (int lettercount = 1; lettercount < 20; lettercount++)
{
while (readFrom >> word)
{
if (word.length() == lettercount)
{
cout << "Writing " << word << " to file\n";
writeTo << word << endl;
}
}
readFrom.seekg(0, ios::beg); //resets read pos to beginning of file
}
}
else
cout << "Could not open one or both of files.";
return 0;
}
For the first iteration of the for loop, the nested while loop seems to work just fine, writing the correct values to the second file. However, something goes wrong in all the next iterations of the for loop, because no further words are written to the file. Why is that?
Thank you so much.
while (readFrom >> word)
{
}
readFrom.seekg(0, ios::beg); //resets read pos to begin
The while loop will continue until special flags are set on readFrom, namely, the EOF flag. Seeking to the beginning does not clear any flags, including EOF. Add the following line right before the seek to clear the flags and your code should work fine.
readFrom.clear();
After seek, clear the EOF flag.
readFrom.clear();
I am having problems with the code bellow.
It can write fine if i kill the read section.
It can read fine if i kill the write section and the file has already been written.
The 2 don't like each other. It is like the write stream is not closed... though it should be.
What is wrong?
#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
using namespace System;
int main(array<System::String ^> ^args)
{
string a[5];
a[0]= "this is a sentence.";
a[1]= "that";
a[2]= "here";
a[3]= "there";
a[4]= "why";
a[5]= "who";
//Write some stuff to a file
ofstream outFile("data.txt"); //create out stream
if (outFile.is_open()){ //ensure stream exists
for (int i=0; i< 5; i++){
if(! (outFile << a[i] << endl)){ //write row of stuff
cout << "Error durring writting line" << endl; //ensure write was successfull
exit(1);
}
}
outFile.close();
}
//Read the stuff back from the file
if(!outFile.is_open()){ //Only READ if WRITE STREAM was closed.
string sTemp; //temporary string buffer
int j=0; //count number of lines in txt file
ifstream inFile("data.txt");
if (inFile.is_open()){
while (!inFile.eof()){
if(! (getline(inFile, sTemp)) ){ //read line into garbage variable, and ensure read of line was
if(!inFile.eof()){ //successfull accounting for eof fail condition.
cout << "Error durring reading line" << endl;
exit(1);
}
}
cout << sTemp << endl; //display line on monitor.
j++;
}
inFile.close();
}
cout << (j -1) << endl; //Print number lines, minus eof line.
}
return 0;
}
You have a memory overwrite.
You have six strings, but dimension only for five strings
string a[5];
a[0]= "this is a sentence.";
a[1]= "that";
a[2]= "here";
a[3]= "there";
a[4]= "why";
a[5]= "who";
this can cause the rest of your program have unexpected behavior.
G... bows head in shame. Was playing with file streams and wasn't paying attention to the array initializations that i rushed through.
What is interesting is that MS VS 2005 did not complain about the array value assignment a[5]= "who". It let me get away with it. So I didn't even consider that durring debugging. I can kind of see why that is ok... I wrote it out of bounds in the next contiguous spot in memory and the MS compiler let me get away with it. As far as I remember Linux does complain about this type of error. No?
Thinking it was the read file back section that was wrong i commented out all of the read section except the line ifstream inFile("data.txt"). This cause the app to crash, leading me to think the write stream was somehow not closed. I take it that the
ifstream inFile("data.txt") line alone has little to do with the array in question when the rest of the read section is commented out. Yet that is what caused it to crash in VS 2005.
At any rate, thanks!
Works fine.