I am new in C++. This is a part of a program that actually runs, no mem-leak. It reads a line counting how much doubles per/line there are (aux_d), and if it is equal to dim (dimention) it push_back into the vector.
Read line, and then rewind istringstream fss. But when i print my v_db[i] (vector_database) it only loads zeros into the coordinate class.
coordinates aux_c;
double aux_d;
... do stuff and then
while(std::getline(filestream,line)){
i=0;
std::istringstream fss(line);
while( fss >> aux_d )
i++;
if (i != dim){
std::cerr << "Wrong Tiberium_Base coordinates // "
<< "Check line -"
<< lc
<< "-"
<< std::endl;
lc++;
continue;
}
fss.seekg(0);
fss >> aux_c;
v_db.push_back(aux_c);
lc++;
}
So i did this just to make it work.
std::istringstream fss2(line);
fss2 >> aux_c;
v_db.push_back(aux_c);
lc++;
I would like to know what the heck is going on here, since i've used seekg with that same purpose before, and didnt have any problem at all (in this program actually). Thanks.
After you are finished with the loop.
while( fss >> aux_d )
i++;
fss has failbit set. You need to clear that before you can use the stream.
while( fss >> aux_d )
i++;
...
// Clear the error states of the stream.
fss.clear();
fss.seekg(0);
fss >> aux_c;
Related
I'm sorry but I'm quite new to C++ but not programming in general. So I tried to make a simple encryption/decryption. However when I added the modification to my previous code (so there isn't two programs for encrypting and decrypting) I found that the code 'getline()' method no longer works. Instead it's just ignoring it when the code is ran. Here's the code:
int main(){
std::string string;
int op = 1; //Either Positive or Negative
srand(256);
std::cout << "Enter the operation: " << std::endl;
std::cin >> op;
std::cout << "Enter the string: " << std::endl;
std::getline(std::cin, string); //This is the like that's ignored
for(int i=0; i < string.length(); i++){
string[i] += rand()*op; //If Positive will encrypt if negative then decrypt
}
std::cout << string << std::endl;
std::getchar(); //A Pause
return 0;
}
That's because std::cin >> op; leaves a hanging \n in your code, and that's the first thing getline reads. Since getline stops reading as soon as it finds a newline character, the function returns immediately and doesn't read anything more. You need to ignore this character, for example, by using cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); (std::numeric_limits is defined in header <limits>), as stated on cppreference.
This is because you still have the newline character in the buffer which makes getline() stop reading as soon as it encounters it.
Use cin.ignore() to ignore the newline character from the buffer. This will do in your case.
In general, if you want to remove characters from your buffer untill a specific character, use:
cin.ignore ( std::numeric_limits<std::streamsize>::max(), ch )
Use :
cin.ignore ( std::numeric_limits<std::streamsize>::max(), '\n' );
to eat newlines from previous input std::cin >> op;
header - <limits>
Other way would be :
while (std::getline(std::cin, str)) //don't use string
if (str != "")
{
//Something good received
break;
}
As other stated already, the formatted input (using in >> value) start skipping space abd stop when they are done. Typically this results in leaving some whitespace around. When switching between formatted and unformatted input you typically want to get rid of leading space. Doing so can easily be done using the std::ws manipulator:
if (std::getline(std::cin >> std::ws, line)) {
...
}
You must use std::cin.ignore() before std::getline(std::cin, string) to clear the buffer, because when you use std::cin >> op before the getline a \n gets in the buffer and std::getline() reads it. std::getline() takes only the line you type, when you skip a line, std::getline() closes, so when std::getline() picks up \n from the buffer it is already terminated before you type something, because /n skips a line.
Try this way:
int main(){
std::string string;
int op = 1; //Either Positive or Negative
srand(256);
std::cout << "Enter the operation: " << std::endl;
std::cin >> op;
std::cout << "Enter the string: " << std::endl;
std::cin.ignore();
std::getline(std::cin, string); //This is the like that's ignored
for(int i=0; i < string.length(); i++){
string[i] += rand()*op; //If Positive will encrypt if negative then decrypt
}
std::cout << string << std::endl;
std::getchar(); //A Pause
return 0;
}
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;
}
}
After inputting getline, the first row of numbers in my input file are ignored and the program starts at the second line until the end.
Here's the code:
while (!file.eof())
{
getline(file, lineBuffer);
if(lineBuffer.length()==0)
{
continue; //ignore empty lines
}
else
{
// file.open("test.txt");
while (file >> A >> B >> N)
{
for(int count=1; count<=N; count++)
{
if(count%A == 0 && count%B == 0) { cout << "FB "; }
else if(count%A == 0) { cout << "F "; }
else if(count%B == 0) { cout << "B "; }
else { cout << count << " "; }
}
cout << endl;
}
}
}
The input file contains 3 rows of integers and only the second line and third like are processed. I've looked this up extensively, but no one has mentioned a case similar to mine. Usually they deal with people trying to get user input after a getline function. Any ideas would be greatly appreciated.
getline(file, lineBuffer) reads a line from file and stores it in lineBuffer. If you want to use it, you should then process lineBuffer instead of reading from file (where the first line will already be skipped). To make it work, simply remove all code outside of the inner while. This will read from the file 3 numbers at a time, stopping when extracting one of them fails.
Is the above code real or is it an example?
If it is real, you don't need to skip th eempty lines. The operator>> will skip the whitespaces for you.
The following code without any lineskipping performs just the same reading of "A B N" lines:
// outer loop is not needed, either remove it, or include error checking
// while (!file.eof() && !file.fail())
{
while (file >> A >> B >> N)
{
for(int count=1; count<=N; count++)
{
if(count%A == 0 && count%B == 0) { cout << "FB "; }
....
If for some reason you cannot remove the getline at all, remember that getline reads the line ALWAYS (well, unless the streampointer reached its end). This means that your code skips the empty lines, then reads first nonempty line, notices that the line is not empty and breaks the loop. Note that it has read the line, hence, your first-line-of-data now is in the linebuffer, and not in the stream anymore. Now you have to either unget the whole line (if your stream supports it) or rewind the stream by the line's length (if your stream supports it) or - just read the data from the line - for example using istringstream class.
In general, mixing getline and operator>> is doable but tricky, (especially when you first read via >> and then want to skip a 1 or 2 lines), as they behave a little differently in terms of buffering and whitespace-handling. If you really want that, search for this subject - there are lots of examples how to sync them.
I'm aware this has been asked a few time before and I read the threads related to it but the solutions there didn't work for me.
ifstream myFile;
myFile.open("largefile.txt");
if (myFile.is_open())
{
while (!myFile.eof( )) //step through each line until end of file
{
myFile>> str;
if(str.size() < 5){
amount++;
}
}
}
myFile.seekg(0, ios::beg);
if (myFile.is_open())
{
for(int i=0; i != random_integer; i++) //step through each line until random line reached
{
myFile>> str;
if(i == random_integer-1){
cout << "\n";
cout << str;
cout << "\n";
cout << str.size();
}
}
}
myFile.close();
I read that using EOF in the while statement was a bad idea, whats the alternative? And how can I rewind for the second loop as seekg isn't working out, I don't want to have to close the file and open again, and the file is to large to read into an array really?
TIA, I'm sure this is an easy fix I'm just very new to C++.
Instead of testing eof() (which doesn't work correctly), you should
just verify that each input has worked, by using the stream in a boolean
context:
while ( myFile >> str ) {
// ...
}
Once it has failed, of course, the stream is in a failed state, which
must be reset before any further operations are allowed:
myFile.clear();
myFile.seekg( 0, std::ios_base::beg );
myFile >> str is not guaranteed to work just because you checked for end of file, because that is a flag only set when EOF has been read, not when it is about to be read.
Instead you should do:
while( myFile >> str )
You also need to clear your stream before you use it again (with seekg). One of the unfortunate things about streams is that they hold state as flags and they can trip you up if you are not careful.
myFile.clear();
then continue.
I am trying to read a poorly formatted text file, and maybe I'm going about this the wrong way, but based on the getline documentation it sounded like it would pull values until the values weren't a delimiter value (' ', in my case):
"If the delimiter is found, it is extracted and discarded, i.e. it is
not stored and the next input operation will begin after it. If you
don't want this character to be extracted, you can use member get
instead."
But for some reason it returns nothing many times. See lines 604-607, all those commas in my output are returns of getline. Could someone tell me why it is returning blanks 6 times before it comes to the value? The text file only contains one space before the value. Thanks in advance. :)
Relevant screenshot: http://j.drhu.me/2011-09-07_1317.png
#include <iostream>
#include <fstream>
#include <string>
void CMuscleModel::LoadOpParams()
{
int i, j;
ifstream param("params.txt", ios::in);
if (param.is_open())
{
stringstream iss, isn;
string line, word;
i=0; j=0;
while (getline(param,line))
{
isn.clear();
isn << line;
if(i>27){
while (getline(isn,word,' ')) {
//LGma[i][j]=atof(word.c_str());
if(word == "SM"){
getline(param,line);
cout << line << endl << endl;
isn.clear(); isn << line;
getline(isn,word,' ');
int junk=0;
while (atof(word.c_str())==0){
junk++;
getline(isn,word,' ');
}
cout << atof(word.c_str()) << ", " << junk << endl;
}
if(word == "ST"){
cout << word << endl;
}
if(word == "BFL"){
cout << word << endl;
}
if(word == "BFS"){
cout << word << endl;
}
if(word == "MG"){
cout << word << endl;
}
if(word == "LG"){
cout << word << endl;
}
if(word == "RF"){
cout << word << endl;
}
if(word == "VM"){
cout << word << endl;
}
if(word == "VL"){
cout << word << endl;
}
if(word == "VI"){
cout << word << endl;
}
j++;
}
}
j=0; i++;
isn.clear();
}
}
param.close();
}
Ah, sorry for not including code.
If you're using space as a delimiter anytime it's encountered getline will return with whatever there was upto the delimiter. If the file had 5 spaces in a row before any other characters for example you'd now have to call getline 6 times.
Perhaps use the default newline character instead '\n'?
Edit: Didn't see code before. Perhaps restructure your code to read lines and then use find in conjunction with substr on each line to search for your keywords? Would be simpler code and less looping. There is no reason to read from the file only to output to a stringstream which you then read from.
Bi-directional I/O with std::stringstream is really ambiguous. I recommand that you use it a little differently.
ifstream param("params.txt", ios::in);
if (param.is_open())
{
stringstream iss;
string line, word;
i=0; j=0;
while (getline(param,line))
{
istringstream isn(line);
// ...
}
}
This creates a fresh string stream with clean state and contains the contents of the line read from the file each time. If you really want to re-use the instance for reading tokens on multiple lines, I recommand you use the .str(line) syntax rather than .clear() and operator<<.
If you want to clear the whitespace at the beginning of each line, you can use the std::ws manipulator:
istringstream isn(line);
isn >> ws;
// ...
I think the output text file I was reading from had trailing spaces and they were just being put into the stream so I was really confused about what was going on. I simply used .str("") at the end of each line to reset my current stream and things worked out marvelously. Thanks for all the help guys.