Making a sequential list of files - c++

I have been stuck on a problem for a while now and can't seem to find an answer.
I'm trying to create multiple files with the same name but a different number at the end each time, I have attempted this at first just by using
int seq_number = 1;
while (seq_number < 10)
{
ofstream fsave;
fsave.open("filename" + seq_number + ".txt");
fsave << "blablabla";
fsave.close();
seq_number = seq_number + 1;
}
But that gives me a very strange result where the letters get jumbled up, I'm not sure how that works but I know it doesn't.
I've looked online and found stringstream or sstream, and tried with that, but it keeps giving me errors too,
string filename;
filename = "character";
ostringstream s;
s << filename << seq_number;
filename(s.str());
fsave.open(filename + ".txt");
fsave << "blabla"
fsave.close(;)
but i keep getting an error:
no match for call to `(std::string) (std::basic_string, std::allocator >)'
I'm not sure how string stream works exactly so im working off of instinct, but i would appreciate any way this is possible, and honestly I think I would prefer doing it without sstream, but i need a way to get an int and str together and save a filename that is a string.
unless you know a better way ;) thanks guys

filename(s.str());
this is wrong; you are not constructing a new variable (filename is already constructed), what you want here is an assignment.
filename = s.str();
Then,
fsave.open((filename + ".txt").c_str());
(although, if you are using C++11, this change is not necessary)
Still, personally I would just construct the whole file name with the stream:
ostringstream s;
s<<"character"<<seq_number<<".txt";
fsave.open(s.str.c_str());
I'm not sure how string stream works exactly so im working off of instinct
This is a very bad idea, C++ is often quite a minefield of bizarre syntax, segfaults and undefined behavior, going by instinct usually leads to disaster.
About the errors you get:
fsave.open("filename" + seq_number + ".txt");
This shouldn't even compile, since you are summing an integer to a const char * (thus moving the "start of the string"), and then summing it again to a const char *, which is not allowed at all. Maybe it could compile if it were like this:
fsave.open("filename" + seq_number);
but it won't give the required result - "filename" is a pointer (not a C++ string), so summing an integer to it just moves the pointer of the given offset.
In your second snippet, instead, you are using an object (filename) as it were a function, which is only allowed if the class overloads operator(); thus, the compiler complains that such an operation is not allowed on that object.

Replace
fsave.open(filename + ".txt");
With
fsave.open( (filename + ".txt").c_str() );
This is because the ofstream constructor takes as parameter a char const *, not an std::string.
Also, your first version generates strange file names because in C and C++, adding an integer to a char * simply offsets within the character array. It does not append to the string.

In C++ you can not convert an int to a string, or concatenate it to one -- not to a ´char*`:
"filename" + seq_number + ".txt"
^const char* ^int ^const char*
Also, ostream can not recieve the filename as a string, it must be a const char*, which you can acquire temporarily via ´c_str()`.
Use sprintf, ostringstream (as you did), or C++11 to_string to do that:
#include <string>
#include <iostream>
int main() {
for(int seq_number = 1; i<10; ++i) {
std::string num_as_string = std::to_string(seq_number); // make a string, C++11
std::string filename = "abcd" + num_as_string + ".txt";
std::ostream f(filename.c_str());
f << "text\n";
}
}
This (modulo typos) should get you started.

You can do it like this:
ostringstream s;
s << "character" << seq_number << ".txt";
fsave.open(s.str());
fsave << "blabla";
fsave.close();
And this is how you could implement the original loop:
for (int seq_number = 1; seq_number<10; ++seq_number)
{
ostringstream s;
s << "filename" << seq_number << ".txt";
ofstream fsave(s.str());
fsave << "blablabla";
}

You could do something like this:
#include <iostream>
#include <string>
#include <sstream>
int main (int argc, char const* argv[])
{
std::string filename;
int seq_number = 10;
filename = "character";
std::stringstream s;
s << filename << seq_number << ".txt";
filename = s.str();
std::cout<< filename << std::endl; // <-- Here open your file instead print the filename
}

Related

C++ Program for Renaming Multiple Files at Once

I have a directory full of JPG files named Slide1, Slide2, Slide3, etc and I want to rename them to a list of names I wrote in a txt file titled "names.txt". Each new name is on one line, so basically I need to read this txt file line-by-line and make each line the new name of a JPG file. I will need to do this for multiple directories, but I expect each one to only contain a max of 60 JPGs (I will use the same names.txt file to rename the JPGs in each directory because it does not matter if there are duplicate JPG names between the directories, it only matters that the no two JPGs in the same directory have the same name).
This is the code I have so far. I know one problem is that char oldname[] and char newname[] can't use the + operator. So how do I get char oldname[] for each JPG to be Slide1, Slide2, etc? As for char newname[], I thought maybe I need to read each line of names.txt as a string and then convert that string to char and set it as char newname[] but I don't know how to do that.
#include <string>
#include <sstream>
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
int myNum;
cout << "How many slides are there? Max 60." << endl;
cin >> myNum;
if (myNum > 60)
cout << "Add more names to names.txt in lyrics folder, then rerun program." << endl;
if (myNum <= 60)
{
int nextNum = 1;
fstream readname;
readname.open("names.txt",ios::in);
if (readname.is_open())
{
string line;
while (getline(readname,line))
{
char oldname[] = "Slide" + nextNum + ".JPG";
char newname[] = line + ".JPG";
nextNum = nextNum++;
if (nextNum == myNum+1)
break;
}
readname.close();
}
}
return 0;
}
If anyone can explain how to do this using string instead of char, that would be fine too. This isn't an assignment, it's just a personal project, so there are no limits to what methods I can use.
From C++11 we have a function std::to_string this takes a numeric value and returns a std::string object. More info at https://en.cppreference.com/w/cpp/string/basic_string/to_string
Using that you can convert your code(in while loop) as follows:
std::string oldName = std::string("Slide") + std::to_string(nextNum) + ".JPG";
std::string newName = line + ".JPG";
Hope this helps,
Thanks
You should not be using char[] arrays at all. Just use std::string instead:
std::string oldname = "Slide" + std::to_string(nextNum) + ".JPG";
// Or, if you are not using C++11 or later:
/*
std::ostringstream oss;
oss << "Slide" << nextNum << ".JPG";
std::string oldname = oss.str();
*/
string newname = line + ".JPG";

C++ arguments to integer

I am attempting to create a text file with the args[1] which should be an integer. The file name should be ex "3.txt", but the file i am getting is called just "t". The number argument is correct, but the file name is somehow getting incorrect. What suggestions do you have to improve this code both readability and usability?
int main(int argc,char *args[])
{
ofstream myFile;
int num = atoi(args[1]);
myFile.open(num + ".txt");
if (myFile.is_open())
{
myFile << "num\n" ;
for(int i=num; i > 0; i--)
myFile << i + ",";
myFile.close();
}
}
Tricky one. When you do :
myFile.open(num + ".txt");
...you're not actually translating the int as a string. Instead, you're taking the char const* that is ".txt" and offseting it by num (3 in your case) chars before passing it to open, hence your "t" file.
I see you're using C++. Save yourself some headaches by using std::string, and C++11's std::to_string functions if you can.
I can't see a reason why you are converting the command line argument to a number in 1st place here.
Change your code like
myFile.open((std::string(argv[1]) + ".txt").c_str());
or for more recent compiler versions (capable of c++11 standards)
myFile.open(std::string(argv[1]) + ".txt");
You don't need to have argv[1] converted to be to a numeric value.
Your problems are resulting from use of wrong types. First of all int() + "text" are defined, but does not do what you expect. It's not operation on strings, but on pointers. You had better use a language. c++ contains std::string and it will be easy wit him. Initially you should make string from args[1]:
string num(args[1]);
Of course, it should be given and you need to check it fitst!
if(argc < 2)
//some throw
After it, operator plus will work in accordance with your wishes. So, you just add ".txt" to num.
num += ".txt"
Now you have to open file with ofstrem. It expect const char*, and string on given address should ended with '\0' so you can use std::basic_string::c_str.
ofstream my_file(num.c_str());
Well to know, since c++11 you can give just std::string:
ofstream my_file(num);
Let's get to the main ("C++ arguments to integer") topic. You can just use std::stoi. As you can see, you don't need to worry about chars after number.
for(int i=stoi(num); i > 0; i--)
myFile << i << ","; //it can't be i + "," - as above
Or if you want to convert directly argument to integer, you have the ability to use std::atoi.
int i = atoi(args[1]);
Finally begin of your code should looks like this:
if(argc < 2)
{//some throw}
ofstream myFile;
string num =string(args[1])+".txt";
myFile.open(num.c_str());

Different values on the function implementation

I'm kind of new with programming and I have wired problem.
I tried to search and read about it, but without success.
I have main file and one class (on windows)
main:
main()
{
LogOut x();
x.WriteToDelayFile(1.2, 3);
}
LogOut class:
void LogOut::WriteToDelayFile(double simTime, int nodeNum)
{
string fileName = "Delay" + nodeNum;
FILE* pFile = OpenFile(fileName);
fputs ("something\n",pFile);
}
I can't figure it out but when I call to WriteToDelayFile(2, 3) with values, I get garbage values edit: (for example, on debug- nodeNum=321546 instead of nodeNum=3) on the LogOut::WriteToDelayFile(double simTime, int nodeNum) implementation
Why does it happen?
Thanks.
As user657267 pointed out in his comment, you may not concatenate a string literal and an int string fileName = "Delay" + nodeNum;. Here you are getting a pointer into the literal, that may even be out of range:
string s = "hello"+1; // leads to "ello" in s
The probably intended concatenation can be done using a stringstream:
#include <sstream>
#include <assert>
void concat_check()
{
std::stringstream ss;
ss << "hello" << 1;
assert(ss.str() == "hello1");
}
Wolf you are a little bit wrong
string s = "hello"+3;
gives "lo" in s data
and
string si = string("hello")+3;
is incorrect you need to use stringstream instead
std::stringstream ss;
ss << "hello" << 3;
std::string s = ss.str();
Dudi Reuveni how can you tell that nodeNum has wrong data?

C++ int to string, concatenate strings [duplicate]

This question already has answers here:
How to concatenate a std::string and an int
(25 answers)
Closed 8 years ago.
I'm new to C++ and working on a simple project. Basically where I'm encountering a problem is creating a file with a number (int) in the file name. As I see it,I have to first convert the int to a string (or char array) and then concatenate this new string with the rest of the file name.
Here is my code so far that fails to compile:
int n; //int to include in filename
char buffer [33];
itoa(n, buffer, 10);
string nStr = string(buffer);
ofstream resultsFile;
resultsFile.open(string("File - ") + nStr + string(".txt"));
This gives a couple compilation errors (compiling in Linux):
itoa not declared in this scope
no matching function for call to ‘std::basic_ofstream char, std::char_traits char ::open(std::basic_string char, std::char_traits char , std::allocator char )’
I've tried the advice here: c string and int concatenation
and here: Easiest way to convert int to string in C++ with no luck.
If I using the to_string method, I end up with the error "to_string not a member of std".
You could use a stringstream to construct the filename.
std::ostringstream filename;
filename << "File - " << n << ".txt";
resultsFile.open(filename.str().c_str());
For itoa, you are likely missing #include <stdlib.h>. Note that itoa is non-standard: the standard ways to format an integer as string as sprintf and std::ostringstream.
ofstream.open() takes a const char*, not std::string. Use .c_str() method to obtain the former from the latter.
Putting it together, you are looking for something like this:
ostringstream nameStream;
nameStream << "File - " << n << ".txt";
ofstream resultsFile(nameStream.str().c_str());
You want to use boost::lexical_cast. You also need to include any needed headers:
#include <boost/lexical_cast>
#include <string>
std::string nStr = boost::lexical_cast<std::string>(n);
then it's simply:
std::string file_name = "File-" + nStr + ".txt";
because std::strng plays nicely with string literals (e.g. ".txt").
Using std::ostringstream:
std::ostringstream os;
os << "File - " << nStr << ".txt";
std::ofstream resultsFile(os.str().c_str());
Using std::to_string (C++11):
std::string filename = "File - " + std::to_string(nStr) + ".txt";
std::ofstream resultsFile(filename.c_str());
for itoa function
include <stdlib.h>
consider this link
http://www.cplusplus.com/reference/cstdlib/itoa/
You can use std::stringstream
std::stringstream ss;
ss << "File - " << n << ".txt";
Since the constructor requires a char pointer, you need to convert it into a char pointer using
ofstream resultsFile(ss.str().c_str());

String concatenation in C++ problem

everybody I have problem with string concatenation in C++, here is my code
map<double, string> fracs;
for(int d=1; d<=N; d++)
for(int n=0; n<=d; n++)
if(gcd(n, d)==1){
string s = n+"/"+d;// this does not work in C++ but works in Java
fracs.insert(make_pair((double)(n/d), s));
}
How can I fix my code?
Try like this.
stringstream os;
os << n << "/" << d;
string s =os.str();
In C++ you have to convert an int to a string before you can concatenate it with another string using the + operator.
See Easiest way to convert int to string in C++.
Use streams, in your case, a stringstream:
#include <sstream>
...
std::stringstream ss;
ss << n << '/' << d;
Later, when done with your work, you can store it as an ordinary string:
const std::string s = ss.str();
Important (side-) note: Never do
const char *s = ss.str().c_str();
stringstream::str() produces a temporary std::string, and according to the standard, temporaries live until the end of the expression. Then, std::string::c_str() gives you a pointer to a null-terminated string, but according to The Holy Law, that C-style-string becomes invalid once the std::string (from which you receved it) changes.
It might work this time, and next time, and even on QA, but explodes right in the face of your most valuable customer.
The std::string must survive until the battle is over:
const std::string s = ss.str(); // must exist as long as sz is being used
const char *sz = s.c_str();
n and d are integers. Here is how you can convert integer to string:
std::string s;
std::stringstream out;
out << n << "/" << d;
s = out.str();
You could use a stringstream.
stringstream s;
s << n << "/" << d;
fracs.insert(make_pair((double)n/d, s.str()));
No one has suggested it yet but you can also take a look at boost::lexical_cast<>.
While this method is sometimes criticized because of performance issues, it might be ok in your situation, and it surely makes the code more readable.
Unlike in Java, in C++ there is no operator+ that explicitly converts a number to a string. What is usually done in C++ in cases like this is...
#include <sstream>
stringstream ss;
ss << n << '/' << d; // Just like you'd do with cout
string s = ss.str(); // Convert the stringstream to a string
I think sprintf(), which is a function used to send formatted data to strings, would be a much clearer way to do it. Just the way you would use printf, but with the c-style string type char* as a first(additional) argument:
char* temp;
sprint(temp, "%d/%d", n, d);
std::string g(temp);
You could check it out at http://www.cplusplus.com/reference/cstdio/sprintf/