Code(main.cpp) (C++):
#include <string>
#include <sstream>
#include <stdio.h>
#include <stdlib.h>
#include <ctime>
//general vars
std::ofstream ofs;
std::ifstream ifs;
std::stringstream ss;
//spamFiles vars
std::string defPath;
int defAmt;
void spamFiles(std::string paramPath);
int main(int argc, const char * argv[])
{
srand(time_t(NULL));
std::cout << "Enter the amount of files: ";
std::cin >> ::defAmt;
std::cout << "Now enter the target path: ";
std::cin >> ::defPath;
::spamFiles(::defPath);
std::cout << defAmt << " files were created." << std::endl;
return 0;
}
void spamFiles (std::string paramPath){
//system("open -a Terminal .");
for(int i = 0; i < ::defAmt; i++){
std::string tempS;
int ranNum = rand() % 501;
ss << ranNum;
std::string ssResult = ss.str();
std::string finalPath = ::defPath + ssResult + ".txt";
ifs.open(finalPath);
if(ifs.good()){
finalPath += "dupe.txt";
while(ifs.good()){
finalPath += "dupe.txt";
ifs.open(finalPath);
}
}
ofs.open(finalPath);
ofs << "";
ofs.close();
ss.str(std::string());
}
return;
}
My problem is following.
Whenever I run this and enter, lets say 53 as for the amount, in the end it'll never create the full amount of files. It's always scaled.
Here's an example.
Defined Amont: 300 -> What I Get: 240
Defined Amount: 20 -> What I get: 15
Defined Amount: 600 -> What I get: 450
Thanks in advance.
Based on the logic of your code, you are creating a file if your ifstream object is not 'good()'. If some files aren't being created, then the error lies here.
With some digging, you'll find that the constructor for an ifstream object does not take a string, but instead a char *.
Adding a c_str() to your 'finalPath' variable should take care of this issue.
Some things to note:
You've forgotten to include fstream and iostream.
When digging into problems like this, don't use random numbers as your first test case. It was easier for me to replicate your issue by just trying to create files in numerical order.
Also don't forget 'close()' your ifstreams!
My adaptation of the code:
#include <string>
#include <sstream>
#include <stdio.h>
#include <stdlib.h>
#include <ctime>
#include <fstream>
#include <iostream>
//general vars
std::ofstream ofs;
std::ifstream ifs;
std::stringstream ss;
//spamFiles vars
std::string defPath;
int defAmt;
void spamFiles(std::string paramPath);
int main(int argc, const char * argv[])
{
srand(time_t(NULL));
std::cout << "Enter the amount of files: ";
std::cin >> ::defAmt;
std::cout << "Now enter the target path: ";
std::cin >> ::defPath;
::spamFiles(::defPath);
std::cout << defAmt << " files were created." << std::endl;
return 0;
}
void spamFiles (std::string paramPath){
//system("open -a Terminal .");
for(int i = 0; i < ::defAmt; i++){
std::string tempS;
int ranNum = rand() % 501;
ss << ranNum;
std::string ssResult = ss.str();
std::string finalPath = ::defPath + ssResult + ".txt";
ifs.open(finalPath.c_str());
while(ifs.good()){
finalPath += "dupe.txt";
ifs.open(finalPath.c_str());
}
ifs.close();
std::cout << finalPath << std::endl;
ofs.open(finalPath.c_str());
ofs << "";
ofs.close();
ss.str(std::string());
}
return;
}
Related
Hi I have got an text file and inside writing:
15 7 152 3078
178 352 1 57
What I want to do is get the int's from first line, sum up the numbers and make it an integer. And than do it for the second line with another int. How can I do that with c++? Thanks for your help.
You can use stringstream to convert a string into integer. And to sum a vector of integer, use accumulate algorithm. You can pass a filename as first argument to the program, by default the program assume the filename as input.txt.
Here is a complete program to demonstrate this.
#include <iostream>
#include <fstream>
#include <sstream>
#include <numeric> // for accumulate
#include <vector>
int main(int argc, char *argv[]) {
std::string filename{"input.txt"};
if(argc > 1) {
filename = argv[1];
}
// open the input file
std::ifstream inputFile(filename);
if(!inputFile.is_open()) {
std::cerr << "Unable to open " << filename << std::endl;
return 1;
}
std::string line;
// read the file line by line
while(getline(inputFile, line)) {
if(line.empty()) continue;
std::stringstream ss(line);
std::vector<int> v;
int x;
// extract the content as integer from line
while(ss >> x) {
v.push_back(x);
}
// add them all
auto total = std::accumulate(v.begin(), v.end(), 0);
std::cout << total << std::endl;
}
}
As in Aamir's answer, but with separate listing of sums and numbers per line. Maybe that helps too.
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
int main(int argc, char *argv[]) {
std::string filename{"input.txt"};
if(argc > 1) {
filename = argv[1];
}
// open the input file
std::ifstream inputFile(filename);
if(!inputFile.is_open()) {
std::cerr << "Unable to open " << filename << std::endl;
return 1;
}
std::vector<int> v_numberSum;
std::vector<int> v_numbersPerLine;
std::string line;
// read the file line by line
int i = 0;
while(getline(inputFile, line)) {
if(line.empty()) continue;
v_numberSum.push_back(0);
v_numbersPerLine.push_back(0);
std::stringstream f(line);
std::string s;
int cnt = 0;
while (getline(f, s, ' ')) {
v_numberSum[i] += std::stoi(s);
cnt++;
}
v_numbersPerLine[i] = cnt;
i++;
}
int j = 0;
for (auto intItem: v_numberSum){
std::cout << "sum"<<j<<": " << intItem << " numbers per line: " << v_numbersPerLine[j] << std::endl;
j++;
}
}
First time asking a question on this site, so here goes. I've been racking my brain for quite some time, but still can't seem to find the answer to this.
Let's say I have a file that reads as follows:
123456789John Doe 0001111.11
925219042Mary Jane 0000302.54
891492829Gertrude Marisou 0123467.76
How would I separate say, 123456789 and John into their own respective strings for input into a vector containing four variables? (Std::string, Std::string, Std::string, Double)
Here is my current code if you all would like to take a peek at it and tell me where I am going wrong.
#pragma once
#if !defined(__Account7_h__)
#define __Accoun7_h__
#include <string>
#include <iostream>
#include <string>
#include <fstream>
#include <vector>
#include <sstream>
//Personal file for trimming the extra whitespace
#include "Trim.h"
class Account7 {
private:
std::string account_code;
std::string first_name;
std::string last_name;
double balance;
public:
//Getters, Setters, Initialization List and whatnot.
//On a separate file
#if !defined(__Vmanager7_h__)
#define __Vmanager7_h__
#include <iostream>
#include <string>
#include <fstream>
#include <vector>
#include <sstream>
#include "Account7.h"
#include "Trim.h"
using namespace generic;
class Vmanager7 {
public:
int a = 1;
std::ifstream infile;
std::ofstream outputFile;
std::vector<Account7> _Account;
Account7 temp;
std::string Empl;
std::string scapeg;
std::string acc_c;
std::string fname;
std::string lname;
double bal;
int Managed() {
int count;
infile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
try {
infile.open("account.dat", std::ifstream::in);
}
catch (std::ios_base::failure &fail) {
std::cout << "File is not opening" << std::endl;
return 0;
}
infile.exceptions(std::ios::goodbit);
while (getline(infile, Empl)) {
count = 1;
std::istringstream ss(Empl);
while (getline(ss, scapeg)) {
if (count == 1)
acc_c = scapeg;
else if (count == 2)
fname = scapeg;
else if (count == 3)
lname = scapeg;
else
bal = atof(scapeg.c_str());
count++;
}
temp.setac(acc_c);
temp.setfn(fname);
temp.setln(lname);
temp.setba(bal);
_Account.push_back(temp);
}
infile.close();
outputFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
try {
outputFile.open("Aoutput.dat");
}
catch (std::ios_base::failure &fail) {
std::cout << "File opening fail" << std::endl;
return 0;
}
outputFile.exceptions(std::ios::goodbit);
for (int i = 0; i < _Account.size(); i++) {
std::cout << _Account[i].getac() << " " << _Account[i].getfn() << " " << _Account[i].getln() << " " << _Account[i].getba();
bal = _Account[i].getba();
bal -= int(bal);
if (bal == 0)
std::cout << ".00";
std::cout << '\n';
}
outputFile.close();
}
};
};
The output I get is something along the lines of this:
123456789John Doe 0001111.11 -9.25596e+61
925219042Mary Jane 0000302.54 -9.25596e+61
191492829Gertrude Marisou 0123467.76 -9.25596e+61
I would like the output to look just like the input. Any help would be immensely appreciated.
I want to create some text file in C++. For example: I will run a loop from 1 to 5 and create the following files:
1.txt
2.txt
3.txt
4.txt
5.txt
is it possible? I have made a sample code:
#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;
main()
{
FILE *fp;
int i;
for(i=1;i<=5;i++)
{
//fp=fopen("%d.txt","r",i); //what will go here??
}
}
I am confused about what I will write inside the loop. how can I create those files?
char i;
char fileName[] = "0.txt";
for(i='1';i<='5';i++)
{
fileName[0]=i;
fp=fopen(fileName,"r"); //what will go here??
//...
}
You can use sprintf if this is too simple for your case;
Since you tag c++, I think fstream string is the thing to use.
A simple c++ example
#include <fstream>
#include <string>
using namespace std;
int main(){
string base(".txt");
for(int i=1;i<=5;++i){
ofstream(to_string(i)+base);// to_string() need c++11
}
}
If you still don't have to_string (you don't have c++11 or your compiler just don't have this) you can use this simple version for now. (better put this in your own namespace)
#include <string>
#include <sstream>
std::string to_string(int i){
std::stringstream s;
s << i;
return s.str();
}
You can use a std::stringstream to compose the file name before passing it to the std::ofstream constructor as a std::string.
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <iomanip>
int main()
{
std::cout << "How many files do you want to create? ";
int n;
std::cin >> n;
std::cout << "How many digits do you want to display? ";
int n_digits;
std::cin >> n_digits; // i.e. zeroes == 3 -> 001.txt
std::cout << "Enter a common prefix for all the files: ";
std::string prefix;
std::cin.ignore();
std::getline(std::cin, prefix); // i.e. prefix == "file" -> file001.txt
std::string ext(".txt");
for ( int i = 1; i <= n; ++i )
{ // use a stringstream to create a file names like: prefix001.txt
std::stringstream ss;
ss << prefix << std::setfill('0') << std::setw(n_digits) << i << ext;
// open the file. If not c++11 use ss.str().c_str() instead
std::ofstream file( ss.str() );
if ( !file )
{
std::cerr << "Error: failed to create file " << ss.str() << '\n';
break;
}
// write something to the newly created file
file << "This is file: " << ss.str() << "\n\nHello!\n";
if ( !file )
{
std::cerr << "Error: failed to write to file " << ss.str() << '\n';
break;
}
}
}
#include <iostream>
#include <fstream>
int main(void)
{
std::ofstream out; // you must call out.close() inside loop to be able to open another file for writting otherwise you'll get only the first one "a.txt"
std::string sFileName;
for(char c('a'); c < 'f'; c++)
{
sFileName = c;
sFileName += ".txt";
out.open(sFileName.c_str(), std::ios::out);
// std::ofstream out(sFileName.c_str(), std::ios::out); // here you are not obliged to call out.close() because the first out is not the very second and so on...
out.close(); // very important if you use the same ofstream to open another file
}
std::cout << std::endl;
return 0;
}
*** to be able to use one ostream object in opening many files you must close the precedent file to be able to open the next otherwise it fails trying creating the next one.
I'm a beginner in c++ and required to write a c++ program to read and print a csv file like this.
DateTime,value1,value2
12/07/16 13:00,3.60,50000
14/07/16 20:00,4.55,3000
May I know how can I proceed with the programming?
I manage to get the date only via a simple multimap code.
I spent some time to make almost (read notice at the end) exact solution for you.
I assume that your program is a console application that receives the original csv-file name as a command line argument.
So see the following code and make required changes if you like:
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <map>
#include <string>
std::vector<std::string> getLineFromCSV(std::istream& str, std::map<int, int>& widthMap)
{
std::vector<std::string> result;
std::string line;
std::getline(str, line);
std::stringstream lineStream(line);
std::string cell;
int cellCnt = 0;
while (std::getline(lineStream, cell, ','))
{
result.push_back(cell);
int width = cell.length();
if (width > widthMap[cellCnt])
widthMap[cellCnt] = width;
cellCnt++;
}
return result;
}
int main(int argc, char * argv[])
{
std::vector<std::vector<std::string>> result; // table with data
std::map<int, int> columnWidths; // map to store maximum length (value) of a string in the column (key)
std::ifstream inpfile;
// check file name in the argv[1]
if (argc > 1)
{
inpfile.open(argv[1]);
if (!inpfile.is_open())
{
std::cout << "File " << argv[1] << " cannot be read!" << std::endl;
return 1;
}
}
else
{
std::cout << "Run progran as: " << argv[0] << " input_file.csv" << std::endl;
return 2;
}
// read from file stream line by line
while (inpfile.good())
{
result.push_back(getLineFromCSV(inpfile, columnWidths));
}
// close the file
inpfile.close();
// output the results
std::cout << "Content of the file:" << std::endl;
for (std::vector<std::vector<std::string>>::iterator i = result.begin(); i != result.end(); i++)
{
int rawLen = i->size();
for (int j = 0; j < rawLen; j++)
{
std::cout.width(columnWidths[j]);
std::cout << (*i)[j] << " | ";
}
std::cout << std::endl;
}
return 0;
}
NOTE: Your task is just to replace a vector of vectors (type std::vector<std::vector<std::string>> that are used for result) to a multimap (I hope you understand what should be a key in your solution)
Of course, there are lots of possible solutions for that task (if you open this question and look through the answers you will understand this).
First of all, I propose to consider the following example and to try make your task in the simplest way:
#include <iostream>
#include <sstream>
#include <vector>
#include <string>
using namespace std;
int main()
{
string str = "12/07/16 13:00,3.60,50000";
stringstream ss(str);
vector<string> singleRow;
char ch;
string s = "";
while (ss >> ch)
{
s += ch;
if (ss.peek() == ',' || ss.peek() == EOF )
{
ss.ignore();
singleRow.push_back(s);
s.clear();
}
}
for (vector<string>::iterator i = singleRow.begin(); i != singleRow.end(); i++)
cout << *i << endl;
return 0;
}
I think it can be useful for you.
Its not appending to the end of the already created text file (which has contents in it) that i specify with cin , even when i have out2.open(tablename2, std::ofstream::out | std::ofstream::app); and out2 << v2[i]; in there.
Full code:
#include "stdafx.h"
#include <iostream>
#include <string>
#include <fstream>
#include <vector>
#include <iomanip>
#include <stdio.h>
using namespace std;
using std::vector;
using std::string;
void insertit(std::vector<std::string>& v, std::vector<std::string>& v2, std::string insertedstr)
{
std::string tablename2;
cout << "Enter file name with the extension " << endl;
std::getline(std::cin, tablename2);
for (int w = 0; w < v.size(); w++) {
cout << v[w] << ": ";
cin.ignore();
std::getline(std::cin, insertedstr);
v2.push_back(insertedstr + " ");
insertedstr.clear();
}
//below, why is it not writing to the file you specified from cin >>tablename2?
std::ofstream out2(tablename2);
out2.open(tablename2, std::ofstream::out | std::ofstream::app);
for (int i = 0; i < v2.size(); i++) {
out2 << v2[i];
}
out2.close();
v2.clear();
cout << "The record has been inserted into " << tablename2 << endl;
}
int main()
{
std::vector<std::string> v = {"author", "title"};
std::vector<std::string> v2;
std::string insertedstr;
insertit(v, v2, insertedstr);
return 0;
}
Any ideas why?
The constructor already opens the file, although not in appending mode. It's not clear to me what this does (I looked at http://en.cppreference.com/w/cpp/io/basic_filebuf/open , which didn't help too much, and I'm not a standards wizard). If your constructor looks like
std::ofstream out2(tablename2, std::ofstream::out | std::ofstream::app);
and you remove the out.open(....) call, your code works (tested with gcc 4.8.4 - I removed the #include "stdafx.h").