I'm new to c++ and wrote this code to generate 10 1MB files with incremented file names
#include <fstream>
#include <iostream>
#include <sstream>
using namespace std;
int main() {
stringstream file_name_ss;
std::ofstream file;
for (int i = 0; i < 10; ++i) {
file_name_ss << "file_" << i << ".ini";
string file_name = file_name_ss.str();
int size = 1024 * 1024 * 1; //~1MB
file.open( file_name, ios::app);
for (int x = 0; x < size; x++) {
file << "a";
}
}
}
when I run it the program only one file (file_0.txt) is generated.
is the second loop breaking/escaping the first?
I tried looking online and couldn't find anything that got past the first file
EDIT: I got the loops working(thank you Sam Varshavchik) by adding the line file.close(); to the inner loop. Here is my updated code:
#include <fstream>
#include <iostream>
#include <sstream>
using namespace std;
int main() {
stringstream file_name_ss;
std::ofstream file;
for (int i = 0; i < 10; ++i) {
file_name_ss << "file_" << i << ".ini";
string file_name = file_name_ss.str();
int size = 1024 * 1024 * 1; //~1MB
file.open( file_name, ios::app);
for (int x = 0; x < size; x++) {
file << "a";
file.close();
}
}
}
But I now have a new problem: now the file names look like this:
not a terrible error but still kind of annoying. I think it has something to do with this part:
file_name_ss << "file_" << i << ".ini";
You have two problems, which are really the same problem but done twice: You only have a single string and file stream object, and those won't be "reset" when the loop iterates.
For example the single file object can only be opened once. Any attempt to open it again without closing in between will simply fail.
As for the string stream, each iteration will append to the file name you attempt to open. For example in the second iteration of the loop you will try to open the file file_0.inifile_1.ini. And so on.
The simple solution to both problems? Move the variable definitions inside the loop:
for (int i = 0; i < 10; ++i) {
ostringstream file_name_ss;
file_name_ss << "file_" << i << ".ini";
std::ofstream file(file_name_ss.str());
// ... Rest of loop...
}
[Note that the code should really add some error checking.]
stringstream file_name_ss;
std::ofstream file;
for (int i = 0; i < 10; ++i) {
file_name_ss << "file_" << i << ".ini";
string file_name = file_name_ss.str();
int size = 1; //~1MB
file.open(file_name, ios::app);
for (int x = 0; x < size; x++) {
file << "a";
}
file.close();//close file before open new one
file_name_ss.str("");//clear stream
}
You need to close the file after you are done writing to it. Also, your code doesn't clear the previous file name so you just keep adding on to it. Add this to the end of your for loop.
file_name_ss.str("");
file.close();
Related
I have 2 files: main.cpp and parser.hpp
I am returning vector<vector> from a member function in class in parser.hpp. However it seems I am not getting anything in my main.cpp from the return value because when I print its size I get 0.
This is my main.cpp:
#include <vector>
#include <cstring>
#include <fstream>
#include <iostream>
#include "parser.hpp"
using namespace std;
int main()
{
ifstream file;
file.open("test.csv");
csv obj;
obj.parse(file);
obj.print_parsed_csv(file);
vector<vector<string>> parsed_csv_data = obj.parse(file);
cout << parsed_csv_data.();
cout << parsed_csv_data.size();
for (int i = 0; i < parsed_csv_data.size(); i++)
{
for (int j = 0; j < parsed_csv_data[i].size(); j++)
cout << parsed_csv_data[i][j] << '\t';
cout << endl;
}
}
This is my parser.hpp
using namespace std;
class csv
{
public:
vector<vector<string>> parse(ifstream &file)
{
string str;
vector<vector<string>> parsed_data;
while (getline(file, str))
{
vector<string> parsed_line;
while (!str.empty())
{
int delimiter_pos = str.find(',');
string word = str.substr(0, delimiter_pos);
// cout << word << " ";
if (delimiter_pos == -1)
{
parsed_line.push_back(word);
break;
}
else
{
str = str.substr(delimiter_pos + 1);
// cout << str << endl;
parsed_line.push_back(word);
}
}
parsed_data.push_back(parsed_line);
}
return parsed_data;
}
void print_parsed_csv(ifstream &file)
{
vector<vector<string>> parsed_csv_data = parse(file);
cout << parsed_csv_data.size();
for (int i = 0; i < parsed_csv_data.size(); i++)
{
for (int j = 0; j < parsed_csv_data[i].size(); j++)
cout << parsed_csv_data[i][j] << '\t';
cout << endl;
}
}
};
I am getting correct cout output in parse() only. print_parsed_csv() in parser.hpp and the cout in main.cpp both are giving 0 as the variable's size.
How do I resolve this?
The first time you call obj.parse the stream object is read from until you get to the end of the file. You need to either reopen the file or reset file to point back to the beginning of the file after reading from it.
You pass the same file variable to each of the three functions below but only the first one works. The first call to obj.parse moves where file is pointing in the input file. When obj.parse exits the first time, file is pointing to the end of the file so when it's used in the subsequent 2 calls, there's nothing to read.
obj.parse(file); // <-- this works fine
obj.print_parsed_csv(file); // <-- this fails
vector<vector<string>> parsed_csv_data = obj.parse(file);fails
// ^^^^^^^^^- this fails
See this question for answers on how to reset the ifstream to the beginning of the file.
I am doing an assignment (.csv-parser) for uni. While trying to run the code after compilation it returns a SegFault 11.
This is my code:
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <sstream>
int main (int argc, char** argv) {
string line;
string buffer;
vector<vector<string> > database;
vector<string> dataset;
//bool start = true;
ifstream denkmaeler;
denkmaeler.open(argv[1]);
ifstream denkmal;
denkmal.open(argv[1]);
int semic = 1;
//int semic2 = 1;
int zaehler = 0;
if (denkmal.is_open()){
(getline(denkmal, buffer));
for (int i = 0; i < buffer.length(); i++ ){
if(buffer[i] == ';'){
semic++;}
}
}
denkmal.close();
if(denkmaeler.is_open()) {
//if (counter < 1) {
while (getline(denkmaeler, buffer));
if (line.back() == *argv[2]) {
line += argv[2];
stringstream ss(line);
while (getline(ss, line, *argv[2])) {
dataset.push_back(line);
database.push_back(dataset);
dataset.clear();
}
}
}
for (int x=0, y=semic; x < semic; y=database.size(), x++, y++){
if (x > semic){
x=0;
cout << '\n' << "-------------------------------" << '\n' << endl;
}
if (database[y][0].length() == 0){
database[y][0] = "not available";
}
cout << database[x][0] << " : " << database[y][0] << endl;
}
}
If someone would be able to point out my mistake I would be very thankful. I read some posts pointing out that the problem could be an array but I am not sure how that could be.
For segmentation error, it is best to use a debugging tool which can exactly show you where the error is (which line)!
I am using gdb, i recommend you to google it
I am currently working on a project that displays a table after reading the contents and dimensions of the table from a text file.
The contents of puzzle.txt:
5 5
ferac
asdvb
mfkgt
opemd
welsr
I want my program to read the left number and store it in the variable numRow, and the right number in numCol, then read the letters into the puzzle array. However, when the dimension numbers print, they print as 0 0 instead of 5 5, and the puzzle array only outputs empty box characters.
#include <iostream>
#include <map>
#include <fstream>
#include <cstring>
#include <string>
using namespace std;
char puzzle [numRow][numCol];
void initializePuzzle() {
string storeInput;
int numRow, numCol;
cout << "What is the name of the file?" << endl;
getline(cin, storeInput);
ifstream inFile (storeInput);
inFile.open(storeInput.c_str());
for (int c = 0; c < sizeof(storeInput); c++) {
if (c == 0) {
inFile >> numRow >> numCol;
cout << numRow << ' ' << numCol << endl;
}
}
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
inFile >> puzzle[i][j];
}
}
}
void displayPuzzle() {
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
cout << puzzle[i][j];
}
cout << endl;
}
}
int main() {
initializePuzzle();
displayPuzzle();
return 0;
}
You can do this just by using the C++ Standard Library. Try this: (See about std::copy(), std::array and std::vector...)
#include <iostream> // For std::cout, std::endl, etc.
#include <fstream> // For std::ifstream
#include <vector> // For std::vector
#include <iterator> // For std::ostream_iterator
int main() {
std::string file_src;
// Ask for file name...
std::cout << "What is the name of the file? " << std::endl;
std::getline(std::cin, file_src);
// Declare the file stream...
std::fstream reader(file_src);
// Terminate the program with value '1' in case of failure when reading file...
if (reader.fail()) return 1;
// Declaring necessary varibles...
unsigned num_row, num_column;
std::string temporary;
/* Extracting 'num_row' and 'num_column' and declaring a 'std::vector' (which are
better than dynamic arrays in numerous ways) with the dimensions... */
reader >> num_row >> num_column;
std::vector<std::vector<char>> puzzle(num_row, std::vector<char>(num_column));
// Iterating over each line and copying the string where required...
for (auto i = 0; std::getline(reader, temporary, '\n') && i < num_row; i++)
if (!temporary.empty())
std::copy(temporary.begin(), temporary.end(), puzzle[i].begin());
else --i;
// Close the stream...
reader.close();
// Print the resulting vector...
for (auto & elem : puzzle) {
std::copy(elem.begin(), elem.end(), std::ostream_iterator<char>(std::cout, " "));
std::cout << std::endl;
}
return 0;
}
Example:
Input:
puzzle.txt
Output:
f e r a c
a s d v b
m f k g t
o p e m d
w e l s r
I have the following code
if (StartMonitor) //StartMonitor
{
TotalVoltage5s += CalculatePower();
//TotalVoltage5s += 20;
xx123++;
CString sad;
m_power_edit.GetWindowText(sad);
int num1 = _ttoi(sad);
if(xx123 >= num1){
if(TotalTime > 19){
Power_Log_Chart.ClearChart();
TotalTime = 0;
}
CTime tm;
tm=CTime::GetCurrentTime();
CString str=tm.Format("%X");
ostringstream os;
ostringstream os1;
float ds= (float)atof((char *)(LPTSTR)(LPCTSTR)sad);
os << TotalVoltage5s/ds;
os1 << m_frequency;
m_power_list.InsertColumn(Current_columns,"",LVCFMT_CENTER,80,0);
m_power_list.SetItemText(0, Current_columns, str);
m_power_list.SetItemText(1, Current_columns, os.str().c_str());
m_power_list.SetItemText(2, Current_columns, os1.str().c_str());
m_power_list.SetItemState(Current_columns, LVIS_SELECTED|LVIS_FOCUSED, LVIS_SELECTED|LVIS_FOCUSED);
m_power_list.EnsureVisible(Current_columns, FALSE);
Power_Log_Chart.SetXYValue(TotalTime, TotalVoltage5s/ds, TotalTime, 0);
TotalTime++;
TotalVoltage5s = 0;
m_frequency = 0;
xx123 = 0;
}
}
Power_Log_Chart.Invalidate();
}
CDialog::OnTimer(nIDEvent);
}
What it simply does, it takes the output of the function CalculatePower and it plots and displays its results in real time every 5 seconds, and it does the same thing for frequency and time.
I need a method to save the data in a text file and this is what i tried to do but i am not sure if it is going to work or not.
SavePowerData[32780] =TotalVoltage5s;
SaveTimeData[32780] = TotalTime;
ofstream myfile;
myfile.open ("Power Data.txt");
for(int x=0; x<=TotalVoltage5s; x++)
{
myfile << SavePowerData[x];
myfile << SaveTimeData[x];
}
myfile.close();
#include <fstream>
void append_file(std::string param1,std::string param2, std::string param3){
std::ofstream outfile;
outfile.open("out.txt", std::ios_base::app);
outfile << param1 << " " << param2<< " " << param3;
}
You can try to encapsulate your method like this and append the values you want to the file each time before putting them to your plot. You can also use a separator just after the end of each 3 params so it will be easier to read from afterwards.
Thank you Yigit, That is what i did and it worked,
for (int q = 0; q<=TotalTime; q++)
{
Time_[q] = TotalTime;
voltage[q] = TotalVoltage5s;
Frequency[q] = m_frequency;}
std::ofstream outfile;
outfile.open("Power Data.csv", std::ios_base::app);
outfile<<"Total Time"<<" "<<"Total Voltage 5 sec"<<" "<<"Frequency"<<endl;
for(int k = 0; k<TotalTime; k++){outfile<<voltage[k]<<", "<<Time_[k]<<", "<<Frequency[k]<<endl;}
outfile.close();
I was working on a small project to practice i/o files in c++ but i can't figure out this problem. I wanted to write and algorithm that rearranges words in alphabetical order in a text file.(preferable bubble sorting). This is what i have so far
ifstream file("lab01.txt");
ofstream fileOut("lab01_out.txt");
char s[20][10];//variable for copying the words
//check if file was oppened
if (!file.is_open()) {
cout << "Error, file was not oppened!" << endl;
return -1;
}
//copy words from file to 2d array
for (int i = 0; i < 20; i++)
file >> s[i];
char check[1];
//bubble sort
for (int i = 0; i < 19; i++) {
for (int j = 0; j < 18 - i; j++) {
if (strcmp(s[j], s[j + 1]) > 0) {
strncpy_s(check, s[j], _TRUNCATE);//if not truncated error "buffer to small"
strncpy_s(s[j], s[j + 1], _TRUNCATE);
strncpy_s(s[j + 1], check, _TRUNCATE);
}
}
}
//printing array to output file and to console.
for (int i = 0; i < 20; i++) {
cout << s[i] << endl;
fileOut << s[i] << endl;
}
//closing files.
file.close();
fileOut.close();
The problem is that this is what my output file looks like. I'm getting these symbols instead of words...
enter image description here
Any help will be appreciated!
Some tips how to program in Modern C++.
Don't bring the whole std namespace into your code - Why is “using namespace std” considered bad practice?
Instead of legacy array use a std::vector;
Don't comment the obvious eg. !file.is_open()
this could lead to stale comments after code is modified, and comments are not modified. Make the code obvious.
Don't need to close the file at end of block (destructor does it for You)
Use standard available algorithms (eg. std::swap)
Use meaningful variable names
-
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <algorithm> // until c++11
#include <utility> // since c++11
using std::cout;
using std::endl;
using std::string;
int main()
{
std::ifstream fileToRead( "lab01.txt" );
std::ofstream fileOut( "lab01_out.txt" );
if ( !fileToRead.is_open() || !fileOut.is_open() )
{
cout << "Error, file was not oppened!" << endl;
return -1;
}
std::vector< string > strings;
string readString;
while ( fileToRead >> readString )
{
strings.push_back( readString );
}
const auto stringsCount = strings.size();
// bubble sort
for ( auto lastPosition = stringsCount - 1; lastPosition > 0; lastPosition-- )
{
for ( std::size_t checkedPosition = 0; checkedPosition < lastPosition; checkedPosition++ )
{
if ( strings[ checkedPosition ] > strings[ checkedPosition + 1 ] )
{
std::swap( strings[ checkedPosition ], strings[ checkedPosition + 1 ] );
}
}
}
for ( string str : strings )
{
cout << str << endl;
fileOut << str << endl;
}
}