I was wondering If I could jump positions in a text file.
Suppose I have this file.
12
8764
2147483648
2
-1
Whenever I try to read the third number it won't read because its larger than the max number for a 32 bit int.So whenever i reach the third number, it keeps reading the second over and over again. How can I jump to the 4th number?
Use std::getline instead of operator>>(std::istream, int)
std::istream infile(stuff);
std::string line;
while(std::getline(infile, line)) {
int result;
result = atoi(line.c_str());
if (result)
std::cout << result;
}
The reason you are experiencing the behavior that you are, is that when the std::istream tries (and fails) to read in an integer, it sets a "badbit" flag which means that something went wrong. As long as that badbit flag remains set, it won't do anything at all. So it's not actually re-reading in that line, it's doing NOTHING, and leaving the value that had been there alone. If you want to keep more in line with what you already had, it's probably like below. The above code is simpler and less error prone though.
std::istream infile(stuff);
int result;
infile >> result; //read first line
while (infile.eof() == false) { //until end of file
if (infile.good()) { //make sure we actually read something
std::cout << result;
} else
infile.clear(); //if not, reset the flag, which should hopefully
// skip the problem. NOTE: if the number is REALLY
// big, you may read in the second half of the
// number as the next line!
infile >> result; //read next line
}
You can first read the line, then convert the line to integer if you can. Here is an example for your file :
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
int main()
{
std::ifstream in("file");
std::string line;
while (std::getline(in, line)) {
int value;
std::istringstream iss(line);
if (!(iss >> value)) {
std::istringstream iss(line);
unsigned int uvalue;
if (iss >> uvalue)
std::cout << uvalue << std::endl;
else
std::cout << "Unable to get an integer from this" << std::endl;
}
else
std::cout << value << std::endl;
}
}
As an alternative to using std::getline(), you could call std::ios::clear(). Consider this excerpt from your previous question
fin >> InputNum;
You could replace that code with this:
fin >> InputNum;
if(!fin)
fin.clear();
Related
I need to sort the input text document and write it into another test document. so that lines with an even number of words delete every second word, and lines with an odd number of words remain unchanged. The sorting should be performed as a function, the first pointer to the input of the string and the second pointer to the output.
I did the input and output, tried to do a sorting to begin with without a function, but nothing worked. can you tell me what I did not do the rule?
Example:
Input.txt
I do not like to go to school or study
I like to play games
Output.txt
I not to to or
I like to play games
string in, out;
cin >> in;
cin >> out;
ifstream input(in);
string str;
ofstream output(out);
string st;
while (getline(input, str))
{
do
{
int i = count(str.cbegin(), str.cend(), ' ');
if (i % 2 == 0)
st.append(str);
else
st.append(" ");
i++;
}
while (input);
output << st << endl;
}
The std::stringstream will be your friend.
Read about it here and especially for the useful std::istringstream here.
What can we do with this thing? We can put a string into it and then use the extraction operator >> like with any other stream.
So, counting words will become very simple. We read a line from the file as a std::string and then put it into a std::istringstream, Then we extract dummy words and increase a counter until the reading fails. Then we have the number of words.
Example:
// We read one line. Count the number of words
// Put the string in a stringstream to easily extract words
std::istringstream iss(line);
// Counter for words
unsigned int wordCount{};
// Dummy word
std::string tempWord{};
// Do the counting
while (iss >> tempWord) ++wordCount;
The stream tries too read until it cannot read any more (the stream is empty) and then sets a failbit. The failure of any stream can be checked with its bool operator or the !-operator. The while loop expects a boolean. And the extraction operation iss >> tempWord will return a reference to the stream and then its bool operator will be called and used as condition.
OK, understood, we can now count words. Next step is to skip words.
This is similar simple. In case of even number of words in a string, we will read always 2 words in a loop and simply throw the second one away.
Like this
std::string usedWord{};
// Read 2 words, ignore the second
while (iss >> usedWord >> tempWord)
result += (usedWord + ' ');
There are of course many other possible ways to solve that, but maybe the below solution can give you an idea.
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
int main() {
// First read the input filename
std::cout << "\nPlease enter the path for the input file:\n";
std::string inputFileName{};
std::getline(std::cin, inputFileName);
// next read the output filename
std::cout << "\nPlease enter the path for the output file:\n";
std::string outputFileName{};
std::getline(std::cin, outputFileName);
// Open now both files. If one file cannot be opened, then no need tocontinue
// Open input file and check, if it could be opened
std::ifstream inputFileStream(inputFileName);
if (inputFileStream) {
// Input file could be opened without error.
// Now open output file and check, if it could be opened
std::ofstream outputFileStream(outputFileName);
if (outputFileStream) {
// Now, both input and output file streams are open
// Read lines
std::string line{};
while (std::getline(inputFileStream, line)) {
// We read one line. Count the number of words
// Put the string in a stringstream to easily extract words
std::istringstream iss(line);
// Counter for words
unsigned int wordCount{};
// Dummy word
std::string tempWord{};
// Do the counting
while (iss >> tempWord) ++wordCount;
// if the number of words is even then
if ((wordCount % 2) == 0) {
// Rinitialize stringstream
iss.clear(), iss.str(line);
// Here we store the resulting sentence
std::string result{};
// Now extract the word that we will keep and the other one that we will throw away
std::string usedWord{};
// Read 2 words, ignore the second
while (iss >> usedWord >> tempWord)
result += (usedWord + ' ');
// Write result to output
outputFileStream << result << '\n';
}
else
outputFileStream << line << '\n';
}
}
else std::cerr << "\n*** Error: could not open output file '" << outputFileName << "'\n\n";
}
else std::cerr << "\n*** Error: could not open input file '" << inputFileName << "'\n\n";
}
I want to write a function that gets a set of integers and saves them to a vector.
To get the integers I'm using a while loop.
Enter the vector elements: 1 2 3 4 5
I want the loop to stop looking for input after the last element is inputted or until a non-numberis inputted, however I'm having trouble with it.
It is an assignment, so it needs to read input from std::cin.
This is my code:
#include <iostream>
#include <vector>
bool NumInVect(int num, std::vector<int> vect)
{
bool numInVect = false;
for (int i = 0; i < vect.size(); i++)
{
if (vect[i] == num)
{
numInVect = true;
}
}
return numInVect;
}
int main() {
std::vector<int> tempVect;
std::vector<int> finalVector;
std::cout << "Enter the vector elements: ";
int currVal;
while (std::cin >> currVal)
{
std::cout << "-\n";
if (!NumInVect(currVal, tempVect))
{
tempVect.push_back(currVal);
}
std::cout << currVal << std::endl;
}
//the code never reaches this loop, since its stuck in the while loop
std::cout << "knak\n";
for (int i = 0; i < tempVect.size(); i++)
{
std::cout << tempVect[i];
}
}
I've tried doing multiple things like using std::cin.eof()/.fail(), std::cin >> currVal in the while loop, a do-while loop, but I can't seem to figure out how to get this to work. Does anyone have any tips on what to look into or how to approach this?
If your intention is to get all the input from a given line, and add individual numbers to the vector, then you want to read a line of input into a string, then use an istringstream to process that line of input.
A simplified example:
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
int main() {
std::vector<int> tempVect;
std::string line;
std::getline( std::cin, line );
std::istringstream iss( line );
int curVal;
while ( iss >> curVal ) {
tempVect.push_back( curVal );
}
}
You should add a condition in your while loop so that it breaks when you want like:
if (temptVect.size() >= 5)
break;
I want the loop to stop looking for input after the last element is inputted or until a non-numberis inputted,
This loop should do exactly that.
while (std::cin >> currVal)
{
std::cout << "-\n";
if (!NumInVect(currVal, tempVect))
{
tempVect.push_back(currVal);
}
std::cout << currVal << std::endl;
}
This test while (std::cin >> currVal) will fail if read does not work and exit the loop. Since currVal is an integer, it will fail as soon as it tries to read something that is not an integer (note space and new lines are completely ignored).
What may be the issue is that std::cin is buffered. You can type a long time before filling up the buffer and causing the operator>> to do anything. To force this operator to read you have to force a flush this is usually done by hitting <enter> on the keyboard.
After the buffer is flushed it will read all the numbers on the input and exit the loop if a read fails. So you need to explicitly type not a number before hitting the <enter>.
eg:
1 2 3 4 5 X<enter>
or:
1<enter>
2<enter>
3<enter>
4<enter>
5<enter>
X<enter>
You need that non number to force the read to fail and the loop to exit.
Alternatively, you could say I want to read all the numbers on one line then exit the loop.
In that case: You should read a line and the processes the line. This is only a slight change from your above code.
std::string line; // Hold a line of text
std::getline(std::cin, line); // Read a line of text.
std::stringstream lineStream(line); // Convert string into stream
while (lineStream >> currValue) // Read each integer from the stream.
{ // Exits when the read fails to read
// a number becuase it is empty.
// The other stuff like before.
}
I have a file that has a number in which is the number of names that follow. For example:
4
bob
jim
bar
ted
im trying to write a program to read these names.
void process_file(ifstream& in, ofstream& out)
{
string i,o;
int tmp1,sp;
char tmp2;
prompt_user(i,o);
in.open (i.c_str());
if (in.fail())
{
cout << "Error opening " << i << endl;
exit(1);
}
out.open(o.c_str());
in >> tmp1;
sp=tmp1;
do
{
in.get(tmp2);
} while (tmp2 != '\n');
in.close();
out.close();
cout<< sp;
}
So far I am able to read the first line and assign int to sp
I need sp to be a counter for how many names. How do I get this to read the names.
The only problem I have left is how to get the names while ignoring the first number.
Until then i cannot implement my loop.
while (in >> tmp1)
sp=tmp1;
This successfuly reads the first int from the and then tries to continue. Since the second line is not an int, extraction fails, so it stops looping. So far so good.
However, the stream is now in fail state, and all subsequent extractions will fail unless you clear the error flags.
Say in.clear() right after the first while loop.
I don't really see why you wrote a loop to extract a single integer, though. You could just write
if (!(in >> sp)) { /* error, no int */ }
To read the names, read in strings. A loop is fine this time:
std::vector<std::string> names;
std::string temp;
while (in >> temp) names.push_back(temp);
You'd might want to add a counter somewhere to make sure that the number of names matches the number you've read from the file.
int lines;
string line;
inputfile.open("names.txt");
lines << inputfile;
for(i=0; i< lines; ++i){
if (std::getline(inputfile, line) != 0){
cout << line << std::endl;
}
}
First of all, assuming that the first loop:
while (in >> tmp1)
sp=tmp1;
Is meant to read the number in the beginning, this code should do:
in >> tmp1;
According to manual operator>>:
The istream object (*this).
The extracted value or sequence is not returned, but directly stored
in the variable passed as argument.
So don't use it in condition, rather use:
in >> tmp1;
if( tmp1 < 1){
exit(5);
}
Second, NEVER rely on assumption that the file is correctly formatted:
do {
in.get(tmp2);
cout << tmp2 << endl;
} while ( (tmp2 != '\n') && !in.eof());
Although whole algorithm seems a bit clumsy to me, this should prevent infinite loop.
Here's a simple example of how to read a specified number of words from a text file in the way you want.
#include <string>
#include <iostream>
#include <fstream>
void process_file() {
// Get file name.
std::string fileName;
std::cin >> fileName;
// Open file for read access.
std::ifstream input(fileName);
// Check if file exists.
if (!input) {
return EXIT_FAILURE;
}
// Get number of names.
int count = 0;
input >> count;
// Get names and print to cout.
std::string token;
for (int i = 0; i < count; ++i) {
input >> token;
std::cout << token;
}
}
Yesterday I made a small script with some help to read .csv files. I though I found a way to read the first value and store it, but for some reason it stores the last value instead.
I store what I thought should be the first value under value1, and re-display it to make sure it displays properly and is in fact being stored under a callable variable.
Does anyone know what is wrong with this code? I think I should be using vectors but as I read the reference sheets I find on the internet about them I am being a little thrown of. Any help is appreciated.
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main ()
{
int loop = 1;
string value;
string value1;
while(loop = 1)
{
cout << "Welcome! \n" << endl;
ifstream myfile;
myfile.open ("C:/Documents and Settings/RHatfield/My Documents/C++/Product Catalog Creator/Source/External/Sample.csv");
while (myfile.good())
getline ( myfile, value, ',' );
cout << string ( value) << endl;
value1 = value;
cout << value1;
myfile.close();
system("PAUSE");
return 0;
}
}
Your error seems to be in pure code formatting.
while (myfile.good())
There is no {} after the loop. So only next line is repeated.
The following code is executed after reading of the whole file.
cout << string ( value) << endl;
Thus value stores the last line of the file.
You may want to change the condition in your while loop:
char separator;
int value1;
int value2;
int value3;
while (myfile >> value1)
{
// Skip the separator, e.g. comma (',')
myfile >> separator;
// Read in next value.
myfile >> value2;
// Skip the separator, e.g. comma (',')
myfile >> separator;
// Read in next value.
myfile >> value3;
// Ignore the newline, as it is still in the buffer.
myfile.ignore(10000, '\n');
// Process or store values.
}
The above code fragment is not robust but demonstrates the concept of reading from a file, skipping non-numeric separators and processing the end of the line. The code is optimized either.
I am creating a program (In C++) that takes an ASCII file and reads a few values from each line until it reaches the end of the file. I am using ifstream to read the file, and I have never had problems with it stopping when I use the ifstream.eof() method. This time, however, even though it found the eof character in my test case, when I analyzed my other files, it is infinite looping because it never finds the eof character. Is this a coding issue, or an issue with my files?
string line = "";
unsigned long pos = 0;
ifstream curfile(input.c_str());
getline(curfile, line);
int linenumber = 0;
cout<<"About to try to read the file"<<endl;
if (!curfile.good())
cout<<"Bad file read"<<endl;
while (!curfile.eof())
{
cout<<"Getting line "<<linenumber<<endl;
linenumber++;
pos = line.find_first_of(' ');
line = line.substr(pos+1, line.size()-1);
pos = line.find_first_of(' ');
current.push_back(atof(line.substr(0, pos).c_str()));
for (int i = 0; i<4; i++)
{
pos = line.find_first_of(' ');
line = line.substr(pos+1, line.size()-1);
}
pos = line.find_first_of(' ');
dx.push_back(atof(line.substr(0, pos).c_str()));
pos = line.find_first_of(' ');
line = line.substr(pos+1, line.size()-1);
pos = line.find_first_of(' ');
dy.push_back(atof(line.substr(0, pos).c_str()));
getline(curfile, line);
}
EDIT: When I first run the loop, currentfile.good() returns false...what am I doing that causes it to return that?
First thing is first, you shouldn't check like that. eof() doesn't return true until after a failed read. But you can do better (and easier)!
check the stream state with the implicit conversion to void* which can be used in a bool context. Since most of the read operations on streams return a reference to the stream, you can write some very consice code like this:
std::string line;
while(std::getline(currentfile, line)) {
// process line
}
Basically what it is doing is saying "while I could successfully extract a line from currentfile, do the following", which is what you really meant to say anyway ;-);
Like I said, this applies to most stream operations, so you can do things like this:
int x;
std::string y;
if(std::cin >> x >> y) {
// successfully read an integer and a string from cin!
}
EDIT: The way I would rewrite your code is like this:
string line;
unsigned long pos = 0;
int linenumber = 0;
ifstream curfile(input.c_str());
std::cout << "About to try to read the file" << std::endl;
while (std::getline(curfile, line)) {
std::cout << "Getting line " << linenumber << std::endl;
linenumber++;
// do the rest of the work with line
}
Do not do it like that.
EOF is not the only thing you'll encounter while reading. There's a bunch of errors you might get, and so the best is to simply test the stream itself:
while(currentfile)
{
// read somehow
}
If you're reading lines, then, the simplest way is:
std::string line;
while(std::getline(currentfile, line))
{
// use line
}
Your first call to getline is triggering one of the fail-bits on the ifstream object. That is why if you do a check for a fail-bit using ios::good(), you never enter your read loop. I would check to see what the value of line is ... it's probably empty, meaning you're having another issue reading your file, like maybe permissions problems, etc.
The problem is here:
if (!curfile.good())
cout<<"Bad file read"<<endl; // OK you print bad.
while (!curfile.eof()) // But the loop is still entered.
// Another reason to **NEVER** to use
// while (file.eof()) // as bad does not mean eof
// though eof is bad
Try this:
void readFile(std::istream& str)
{
std::string line;
while(std::getline(str, line))
{
std::stringstream lineStream(line);
std::string ignoreWord;
int number[3];
lineStream >> ignoreWord // reads one space seporated word
>> number[0] // reads a number
>> ignoreWord >> ignoreWord >> ignoreWords // reads three words
>> number[1] // reads a number
>> number[2]; // reads a number
current.push_back(number[0]);
dx.push_back(number[1]);
dy.push_back(number[2]);
}
}