ifstream, getline, and istringstream slow performance on big file in c++ - c++

I want to ask about my code below: (The code below basically read an input file named inputVelocity.dat with format stated in the code. The code reads with istringstream to pass each value to each particular arrays)
std::ifstream inputVelocity("input/inputVelocity.dat");
std::string lineInputVelocity;
while (std::getline(inputVelocity, lineInputVelocity)) {
std::istringstream issVelocity(lineInputVelocity);
double a, b, c, d, e;
if (!(issVelocity >> a >> b >> c >> d >> e)) {
std::cout << "ISS ERROR" << std::endl;
}
for (int k=0; k<=nz+1; k++) {
for (int j=0; j<=ny+1; j++) {
for (int i=0; i<=nx+1; i++) {
ux[i][j][k] = a;
uy[i][j][k] = b;
uz[i][j][k] = c;
pressure[i][j][k] = d;
temperature[i][j][k] = e;
}
}
}
}
inputVelocity.close();
The code is fine when reading around 20000 lines, but when I change the file into around 1.6 million lines, the code run very slow even on a server.
I did std::cout on each getline loop and it read like 5 lines/second, with around 1.6 million lines.
I have found some related questions here but still can't understand what's the problem source and how to fix it. Anyone can help?
Thank you.

I changed the code into this:
std::ifstream inputVelocity("input/inputVelocity.dat");
std::string lineInputVelocity;
int getI, getJ, getK;
getI = 0;
getJ = 0;
getK = 0;
while (std::getline(inputVelocity, lineInputVelocity)) {
std::istringstream issVelocity(lineInputVelocity);
double a, b, c, d, e;
if (!(issVelocity >> a >> b >> c >> d >> e)) {
std::cout << "ISS ERROR" << std::endl;
}
std::cout << getI << " " << getJ << " " << getK << std::endl;
ux[getI][getJ][getK] = a;
uy[getI][getJ][getK] = b;
uz[getI][getJ][getK] = c;
pressure[getI][getJ][getK] = d;
temperature[getI][getJ][getK] = e;
getK = getK + 1;
if (getK == nz+2) {
getJ = getJ + 1;
getK = 0;
}
if (getJ == ny+2) {
getI = getI + 1;
getJ = 0;
}
}
inputVelocity.close();
And that worked really well :)
If anyone has a more efficient solution, I would be very glad to see! :)

Related

How to get multiple line in a loop from a file?

I want to get multiple lines sequentially from a file and then save them to a variable. If in Java can be using scanner.nextInt.
How about C++?
int main(){
string line;
int a, b, c;
ifstream myFile("input.in");
if(myFile.is_open()){
while(getline(myFile,line)){
int cases = atoi(line.c_str());
double count[cases];
cout << "cases : "<<cases << "\n";
for(int i = 1; i <= cases; i++){
a = atoi(line.c_str());
b = atoi(line.c_str());
c = atoi(line.c_str());
cout << a << b << c;
}
}
}
return 0;
}
You can use while(input.in >> cases) to read the next int into cases until end of file (EOF) is reached. I've updated your code below.
int main(){
string line;
int a, b, c;
ifstream myFile("input.in");
if(myFile.is_open()) {
int cases = 0;
while(myFile >> cases) { // breaks on eof
double count[cases];
cout << "cases : " << cases << "\n";
for(int i = 1; i <= cases; i++){
myFile >> a;
myFile >> b;
myFile >> c;
cout << a << b << c;
}
}
}
return 0;
}

Output is a trash value when high precision is required in C++

I have this code-snippet as part of a bigger program. I've searched the Web for finding a solution for my code and used long float, long double, long long int and also setprecision(10), but no success!
In this code I'm going to put that floating point number (0.000098765) into the stringstream ss;(for some purpose) and then put it to output, but when I run the code, a trash value (very very big) will be shown that is clear to be wrong.
It's as bellow:
How to solve my problem please?
int main()
{
stringstream ss;
int temp = 0;
long double d = 0.000098765;
long int n = d;
long double r = d - n;
ss << n;
if (d > n)
{
if (r < 0.0001)
{
ss << '.';
do {
r *= 10;
if (r < 1)
ss << 0;
else
{
temp = r;
ss << temp;
r -= temp;
}
} while (r != 0);
}
}
cout << setprecision(10) << ss.str() << endl;
system("pause");
return 0;
}
Try something like this:
#include <iostream>
#include <iomanip>
using namespace std;
// ...
long double d = 0.000098765;
// ...
stringstream ss2;
ss2 << setprecision(10) << fixed << d;
cout << ss2.str() << endl;
The manipulators operate on the thing fed to the stream, which in your case was a string -- and so 'setprecision' had no effect.
Note also that the 'fixed' manipulator makes the output fixed width, not scientific notation.

C++ Mastermind For Loop

Edit
I've included #include <sstream> now. This helped. But still an issue displaying the correct information. I've stepped it out, and it has to deal with some sort of program error. I have the text file already made inside of the same folder path. I've tried setting it to a direct C:/ path such as
C:\Users\Matt\Documents\Visual Studio 2015\Projects\listofcolors.txt
I'm having problem opening my file and displaying data. I recently downloaded Microsoft Visual Basic C++ to write the program I need for Mastermind. My goal is to create numbers that represent 9 to the 5th and put them within a text file. (Essentially, 5 columns of 9 numbers, 9 I've written this so far.
#include <iostream>
#include <fstream>
#include <sstream>
using namespace std;
int main() {
int a = 0;
int b = 0;
int c = 0;
int d = 0;
int e = 0;
std::string result;
std::stringstream sstm;
ofstream myfile;
myfile.open("listofcolors.txt");
if (myfile.is_open())
{
for (a = 0; a<9; a++) {
sstm << a << b << c << d << e;
result = sstm.str();
myfile << result << '\n';
for (b = 0; b<9; b++) {
sstm << a << b << c << d << e;
result = sstm.str();
myfile << result << '\n';
for (c = 0; c<9; c++) {
sstm << a << b << c << d << e;
result = sstm.str();
myfile << result << '\n';
for (d = 0; d<9; d++) {
sstm << a << b << c << d << e;
result = sstm.str();
myfile << result << '\n';
for (e = 0; e<9; e++) {
sstm << a << b << c << d << e;
result = sstm.str();
myfile << result << '\n';
}
}
}
}
myfile.close();
return 0;
}
}
else cout << "Unable to open file";
return 0;
}
For some reason, nothing is outputted. Any ideas??? Thank you!!
We can get clever by borrowing this arbitrary base conversion code that will output numbers in base 9 - see the cout version online here:
#include <iostream>
#include <iomanip>
#include <fstream>
#include <algorithm>
using namespace std;
/**
* C++ version 0.4 std::string style "itoa":
* Contributions from Stuart Lowe, Ray-Yuan Sheu,
* Rodrigo de Salvo Braz, Luc Gallant, John Maloney
* and Brian Hunt
*/
std::string itoa(int value, int base) {
std::string buf;
// check that the base if valid
if (base < 2 || base > 16) return buf;
enum { kMaxDigits = 35 };
buf.reserve( kMaxDigits ); // Pre-allocate enough space.
int quotient = value;
// Translating number to string with base:
do {
buf += "0123456789abcdef"[ std::abs( quotient % base ) ];
quotient /= base;
} while ( quotient );
// Append the negative sign
if ( value < 0) buf += '-';
std::reverse( buf.begin(), buf.end() );
return buf;
}
int main() {
ofstream myfile("listofcolors.text");
if (myfile.is_open())
{
for (int i = 0; i <= 9 * 9 * 9 * 9 * 9; i++)
{
// Formats the number to five places, filled with leading zeroes
myfile << setw(5) << setfill('0') << itoa(i, 9) << '\n';
}
myfile.close();
}
else
cout << "Unable to open file";
return 0;
}
Note that the file is created in the working directory; here is how to check and set where it is.
Also note that your code had the myfile.close() inside the first loop, so it would only have printed from 00000 to 08888.
Finally, since you are on Windows, use File Explorer to search for listofcolors.txt, just in case it is being created in an unexpected location.
On Windows, text files have a .txt file extension, not .text. Also, you are creating the file using a relative path, so it will be created in the process's current working directory, which may not be what you are expecting it to be. Always use absolute paths.
Your loop code is unnecessarily complex, it can be simplified to something more like this:
#include <iostream>
#include <fstream>
using namespace std;
int main() {
ofstream myfile("C:\\some path\\listofcolors.txt", ios_base::trunc);
if (myfile.is_open())
{
for (int a = 0; a < 9; a++)
for (int b = 0; b < 9; b++)
for (int c = 0; c < 9; c++)
for (int d = 0; d < 9; d++)
for (int e = 0; e < 9; e++) {
if (!(myfile << a << b << c << d << e << '\n')) {
cout << "Unable to write to file";
return 0;
}
}
myfile.close();
cout << "File created";
}
else
cout << "Unable to create file";
return 0;
}

After completing the output,console application exits.. How to make it ask for input again?

I created a console application in VStudio 2015.... and after it executes properly,asks for input and shows the output, it says press any key to continue.
I want the program to ask again for the input...
Heres the code :-
#include "stdafx.h"
#include "iostream"
#include "stdio.h"
using namespace std;
int main()
{
int a, b, n;
cout << "Enter the number of lines:";
cin >> n;
for (a = 1; a <= n; a++)
{
for (b = 1; b <= a; ++b)
{
cout << a;
}
cout << "\n";
}
system("pause");
return 0;
}
Add another loop:
int a, b;
int n = 1;
while (n > 0)
{
cout << "Enter the number of lines:";
cin >> n;
for (a = 1; a <= n; a++)
{
for (b = 1; b <= a; ++b)
{
cout << a;
}
cout << "\n";
}
}
Put a third loop on top of your code.
int a, b, n;
while(true)
{
// here you need to figure out how to break loop
// I mean how to go out from it. It depends on your
// purpose
cout << "Enter the number of lines:";
cin >> n;
if (n==-1)
{
// I assume n should be larger than 0 for your purpose.
break;
}
for (a = 1; a <= n; a++)
{
for (b = 1; b <= a; ++b)
{
cout << a;
}
cout << "\n";
}
}
Edit
Although I do not think its necessary, as you can see, someone thinks that using n<=0 is better choise than n==-1. Its your call. You can either change it, or just type an information which states that which number the user should give as an input in order to terminate the program.

Loading Variable from a file

AT
4
5
6
7
#include<iostream>
#include<stdio.h>
#include <fstream>
using namespace std;
int main()
{
int data[4], a, b, c, d, e, f;
ifstream myfile;
myfile.open("tera.txt");
for (int i = 0; i < 4; i++)
{
myfile >> data[i];
}
myfile.close();
a = data[0];
b = data[1];
c = data[2];
d = data[3];
cout << a << "\t" << b << "\t" << c << "\t" << d << "\n";
return 0;
}
it takes AT also and give garbage value. how and where should i use ignore function to ignore AT Value.
And there is one thing more if there is another array given BT containing some value like this:
AT BT
how to store BT's all values under it in an array?
You just have to skip the first line. You can also add optional error handling, otherwise read may fail for all line.
if (!myfile)
{
cout << "can't open\n";
return 0;
}
string temp;
myfile >> temp;
cout << "first line: " << temp << endl;
for (int i = 0; i < 4; i++)
{
myfile >> data[i];
if (myfile.fail())
{
cout << "error\n";
myfile.clear();
myfile.ignore(1000000, '\n');
}
}