why I cant read a file to an integer vector? - c++

well! I have a text file including some integer values and non-integers like character strings and white spaces so I want only to read integers values so I used a vector of integers but when I read the file the opining is ok but it seems the first input fails thus breaks the loop!!!
here is my main example:
ifstream in("file.txt");
if(in.fail())
cout << "opening failed!" << endl;
//opening is fine!
int value;
vector<int> v;
while(in >> value) // the problem here; it fails why?
{
cout << "ok"; // not printed
v.push_back(value);
}
cout << v.size() << endl; // 0??!!
this is the content of file.txt:
32 43 24 32
15 23
57
77 81
if I make a vector of chars it's ok but I want only to use one of integers
*** I already used a code like this and worked fine but now I don't know what happened??!!! it's really annoting
any help, comment, tip is welcome and appreciated

This line:
while(in >> value)
says while I can read integers...
But in the post this may not be true - you are not handling this case.
Either read stuff that is not integers and handle it. Or just read strings and then decide what to do.
In addition
cout << "ok"; // not printed
is because it is buffered.
Do this
cout << "ok" << flush; // printed

excuse me first for annoying you with nonsense question. finally I managed to discover the error:
in my main folder of project I unintentionally created a winrar file input.rar then I didn't remove it but rename it to input.txt it's ok I opened it manually and removed some unreadable characters. then I put inside it the content above of integers then my c++ application succeeds in opening it but can't read it.
*now I removed it input.txt which was input.rar and created a new document text input.txt and now everything is good!!!
thank you for your collaboration. and this post may help someone else.
* don't create rar file or other formats then rename them to be text files and try to read them via your c++ fstream because it'll fail in fact it'll produce an error-prone which looks impossible to solve

Related

ofstream keeps giving me the last line of the function instead of showng everything

so I have been trying to figure out a way to have a function enter whatever is written in a file and to output into a Sha-256 function. maybe why do I want to do that? Simple enough I am trying to just teach myself how things work in c++, however it displays the last line for the function ofstream. this is my main function
ifstream input ("/home/findme/Desktop/text.txt"); // opens text.txt file.
string s;
while (getline (input, s))
{
// loop to read every line one by one of the file.
string c = s; // enters function to be converted.
string output1 = sha256(c); // gives back the value of the string.
cout << "sha256('"<< c << "'):" << output1 << endl; //displays the results.
ofstream outfile ("/home/findme/Desktop/result.txt");
outfile << "sha256('"<< c << "'):" << output1 << endl;
outfile.close();
}
ok so just an insight of what happens, it reads the context of the file named text.txt in this file there is 3 lines which are (test, test2, test3). so it reads one line and sends it to the function and it returns then it does it for the second line and so on. Once it hits the last line the cout function reads this
sha256('test'):9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08
sha256('test2'):60303ae22b998861bce3b28f33eec1be758a213c86c93c076dbe9f558c11c752
sha256('test3'):fd61a03af4f77d870fc21e05e7e80678095c92d808cfb3b5c279ee04c74aca13
and that's correct. there is no problem whatsoever with the cout function but when I try to put it in an external file named result.txt it displays
sha256('test3'):fd61a03af4f77d870fc21e05e7e80678095c92d808cfb3b5c279ee04c74aca13
That's is the problem, it seems like all it does is writes the last function. I tried to change the placing of the ofstream as in outside the loop or before the cout function and it gives the same issue, I also tried with a loop and it gives the same issue. It just repeats the sha256('test3').
Now I know that its obviously something really easy to fix but im not seeing, therefore can someone please help me? I want it to display exactlty what the cout displays. (there are no error messages and it compiles without a problem). Thank you
You are creating your ofstream outfile in the loop. Meaning it's recreated each iteration through the loop. If you move this line to the top of your sample code it should work:
ofstream outfile ("/home/findme/Desktop/result.txt");

C++ reading a file into a struct

Using fstreams I have a file opened that contains numerous lines. Each contiguos set of 4 lines are such that: the first line is an int, the second and third are strings and fourth is a double. This sequence continues till EOF.
I'm attempting to load these lines into a struct array:
struct Library {
int id;
string title;
string artist;
double price;
};
and the code I'm trying to implement to load data into the struct is this:
const int LIMIT = 10
Library database[LIMIT];
ifstream file;
file.open("list.txt");
if(file) {
while(!(file.eof()) && counter < LIMIT) {
file >> database[counter].id;
getline(file, database[counter].title;
getline(file, database[counter].artist;
file >> database[counter].price;
}
} else {
...
}
// Using the following to debug output
for(int i = 0; i < counter; i++) {
cout << "ID: " << database[i].id << endl
<< "Title: " << database[i].title << endl
<< "Artist: " << database[i].artist << endl
<< "Price: " << database[i].price << endl
<< "-----------------------" << endl;
}
The file I'm trying to throw at this thing is
1234
Never Gonna Give You Up
Rick Astley
4.5
42
Thriller
Michael Jackson
32.1
The problem I'm having here is that between reading the id and title using file >> ... and getline(...) is that somewhere a newline bite is being introduced screwing up the output, which displays this monstrosity...
ID: 1234
Title:
Artist: Never Gonna Give You Up
Price: 0
--------------------
ID: 0
Title:
Artist:
Price: 0
--------------------
The solution is probably the most basic of solutions, but mainly because I can't figure out exactly what is going on with the newline bite I can't combobulate a phrase to shove into google and do my stuff there, and I'm at the stage where I've been looking at a problem so long, basic knowledge isn't working properly - such as how to handle basic input streams.
Any form of help would be much appreciated! Thanks in advance :)
This happens because the >> operator for the input stream only grabs part of a line, and does not always grab the newline character at the end of the line. When followed by a call to getline, the getline will grab the rest of the line previously parsed, not the line after it. There are a few ways to solve this: you can clear the buffer from the input stream after each read, or you can simply get all your input from getline and just parse the resulting strings into an integer or a double when you need to with calls to stoi or stod.
As a side note, you don't want to detect the end of your file the way you presently are. See why is eof considered wrong inside a loop condition?
You can solve this problem by adding:
fflush(file);
everytime before you use getline(file, ...). Basically this will clear the input buffer before you use the getline() function. And fflush() is declared in the cstdio library.
file >> database[counter].id;
will read, in this case, a whitespace separated sequence of characters that is interpreted as an int. The newline is considered whitespace. You should now be sitting on that newline character, thus the getline() will read nothing -- successfully -- and increment the file position just past that.
You may be better off using getline() for each line and then separately interpreting the lines from the reading. For example, the first line read could be interpreted with a subsequent std::stoi() to get the integer representation from the string.

How to extract specific substring from getline function in C++?

I'm fairly new to C++ so please forgive me if my terminology or methodology isn't correct.
I'm trying to write a simple program that:
Opens two input files ("infileicd" and "infilesel").
Opens a single output file "list.txt".
Compares "infilesel" to "infileicd" line by line.
If a line from "infilesel" is found in "infileicd", it writes that line from "infileicd" to "list.txt", effectively making a separate log file.
I am using the getline() function to do this but have run into trouble when trying to compare each file line. I think it might be easier if I could use only the substring of interest to use as a comparison.
The problem is that there are multiple words within the entire getline string and I am only really interested in the second one. Here are two examples:
"1529 nic1_mau_op_mode_3 "8664afm007-01" "1" OUTPUT 1 0 LOGICAL 4 4136"
"1523 pilot_mfd_only_sel "8664afm003-02" "1" OUTPUT 1 0 LOGICAL 4 4112"
"nic1_mau_op_mode_3" and "pilot_mfd_only_sel" are the only substrings of interest.
It would make it a lot easier if I could only use that second substring to compare but I don't know how to extract it specifically from the getline() function. I haven't found anything suggesting it is impossible to do this, but if it is impossible, what would be an alternative method for extracting that substring?
This is a personal project so I'm under no time contstraints.
Any assistance is greatly apprecated in advance. Here is my code (so far):
int main()
{
//Open the file to write the selected variables to.
ofstream writer("list.txt");
//Open the selected variabels file to be read.
ifstream infilesel;
infilesel.open("varsel.txt");
//Open the icd file to be read.
ifstream infileicd;
infileicd.open("aic_fdk_host.txt");
//Check icd file for errors.
if (infileicd.fail()){
cerr << "Error opening icd.\n" << endl;
return 1;
}
else {
cout << "The icd file has been opened.\n";
}
//Check selected variables file for errors.
if (infilesel.fail()){
cerr << "Error opening selection file.\n" << endl;
return 1;
}
else {
cout << "The selection file has been opened.\n";
}
//Read each infile and copy contents of icd file to the list file.
string namesel;
string nameicd;
while(!infileicd.eof()){
getline(infileicd, nameicd);
getline(infilesel, namesel);
if (nameicd != namesel){ //This is where I would like to extract and compare the two specific strings
infileicd; //Skip to next line if not the same
} else {
writer << nameicd << namesel << endl;
}
}
writer.close();
infilesel.close();
infileicd.close();
return 0;
}
So, based on what we discussed in the comments, you just need to toss the stuff you don't want. So try this:
string namesel;
string nameicd;
string junk;
while(!infileicd.eof()){
// Get the first section, which we'll ignore
getline(infileicd, junk, ' ');
getline(infilesel, junk, ' ');
// Get the real data
getline(infileicd, nameicd, ' ');
getline(infilesel, namesel, ' ');
// Get the rest of the line, which we'll ignore
getline(infileicd, junk);
getline(infilesel, junk);
Basically, getline takes a delimiter, which by default is a newline. By setting it as a space the first time, you get rid of the first junk section, using the same method, you get the part you want, and then the final portion goes to the end of the line, also ignoring it.

No methods of read a file seem to work, all return nothing - C++

EDIT: Problem solved! Turns out Windows 7 wont let me read/ write to files without explicitly running as administrator. So if i run as admin it works fine, if i dont i get the weird results i explain below.
I've been trying to get a part of a larger program of mine to read a file.
Despite trying multiple methods(istream::getline, std::getline, using the >> operator etc) All of them return with either /0, blank or a random number/what ever i initialised the var with.
My first thought was that the file didn't exist or couldn't be opened, however the state flags .good, .bad and .eof all indicate no problems and the file im trying to read is certainly in the same directory as the debug .exe and contains data.
I'd most like to use istream::getline to read lines into a char array, however reading lines into a string array is possible too.
My current code looks like this:
void startup::load_settings(char filename[]) //master function for opening a file.
{
int i = 0; //count variable
int num = 0; //var containing all the lines we read.
char line[5];
ifstream settings_file (settings.inf);
if (settings_file.is_open());
{
while (settings_file.good())
{
settings_file.getline(line, 5);
cout << line;
}
}
return;
}
As said above, it compiles but just puts /0 into every element of the char array much like all the other methods i've tried.
Thanks for any help.
Firstly your code is not complete, what is settings.inf ?
Secondly most probably your reading everything fine, but the way you are printing is cumbersome
cout << line; where char line[5]; be sure that the last element of the array is \0.
You can do something like this.
line[4] = '\0' or you can manually print the values of each element in array in a loop.
Also you can try printing the character codes in hex for example. Because the values (character codes) in array might be not from the visible character range of ASCII symbols. You can do it like this for example :
cout << hex << (int)line[i]

Can't get ios::beg to go back to the beginning of the file

It always seems to be the things that should be no problem that cause problems for me. I don't get it. :/
So I'm trying to make sure that I understand how to manipulate text files. I've got two files, "infile.txt" and "outfile.txt". "infile.txt" has six numbers in it and nothing else. Here is the code I used to manipulate the files.
#include<fstream>
using std::ifstream;
using std::ofstream;
using std::fstream;
using std::endl;
using std::ios;
int main()
{
ifstream inStream;
ofstream outStream;//create streams
inStream.open("infile.txt", ios::in | ios::out);
outStream.open("outfile.txt");//attach files
int first, second, third;
inStream >> first >> second >> third;
outStream << "The sum of the first 3 nums is " << (first+second+third) << endl;
//make two operations on the 6 numbers
inStream >> first >> second >> third;
outStream << "The sum of the second 3 nums is " << (first+second+third) << endl;
inStream.seekg(0); //4 different ways to force the program to go back to the beginning of the file
//2. inStream.seekg(0, ios::beg);
//3. inStream.seekg(0, inStream.beg);
//4. inStream.close(); inStream.open("infile.txt");
//I have tried all four of these lines and only #4 works.
//There has got to be a more natural option than just
//closing and reopening the file. Right?
inStream >> first >> second >> third;
outStream << "And again, the sum of the first 3 nums is " << (first+second+third) << endl;
inStream.close();
outStream.close();
return 0;
}
Maybe I don't understand quite how the stream works, but I've seen a few sources that said that seekg(0) should move the index back to the start of the file. Instead, this is what I get out of it.
The sum of the first 3 nums is 8
The sum of the second 3 nums is 14
And again, the sum of the first 3 nums is 14
It went back, but not nearly in the way I would have hoped. Any idea why this happened? Why did my first three attempts fail?
As Bo Persson states, it may be because your input has
encountered end of file; it shouldn't, because in C++, a text
file is defined as being terminated by a '\n', but practically
speaking, if you're working under Windows, a lot of ways of
generating a file will omit this final '\n'—although it
is formally required, practical considerations will mean that
you'll make sure that it works even if the final '\n' is
missing. And I can't think of any other reason off hand why the
seekg's wouldn't work. inStream.seekg( 0 ) is, of course,
undefined behavior, but in practice, it will work pretty much
everywhere. inStream.seekg( 0, ios::beg ) is guaranteed to
work if inStream.good(), and is, IMHO, preferable to the
first form. (The single argument form of seekg is normally
only used with the results of a tellg as an argument.) And of
course, it only works if the actual input source supports
seeking: it won't work if you're reading from a keyboard or
a pipe (but presumably, "infile.txt" is neither).
In general, you should check the status of inStream after each
read, before using the results. But if the only problem is that
the file doesn't end with '\n', it's probable that the status
will be OK (!fail()) after the final read, even if you've
encountered end of file. In which case, you'll need clear()
anyway.
Note that the above comments are valid for C++-03 and precedent.
C++11 has changed the specification of the single argument form
of seekg, and requires it to reset eofbit before anything
else. (Why is this change only for the single argument form of
seekg, and not the two argument form? Oversight?)
The second input reaches end-of-file for the stream. That state sticks until you call inStream.clear() to clear its state (in addition to the seek).
With a C++11 compliant compiler, option 4 should also work as close and reopen will now clear the previous state. Older compilers might not do that.
Try:
inStream.seekg(0, ios_base::beg);