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());
Related
I would like to hear if there is a solution to this problem. my computer does not support C++ 11 so I can not join string and integer by std::string to_string... instead, I used a string stream.
I want C++ part in ROOT program to read each all files by loop them and from each file read the three columns by ifstream.
int N= ;
for (i=1; i<=N; i++){
ending = ".dat";
name0 = "pulse_value";
ostringstream temp;
temp << i;
str = temp.str();
input = name0 + str + ending;
ifstream get(input);
for (int j=0; j<N4; j++){
time[j]=0.;
energy[j]=0.;
current[j]=0.;
get >>time[j]>>energy[j]>>current[j];
}
}
But it gives me :
Can't call basic_ifstream<char,char_traits<char> >::basic_ifstream<char,char_traits<char> >(input).
basic_ifstream<char,char_traits<char> > basic_ifstream<char,char_traits<char>>::basic_ifstream<char,char_traits<char> >(void);
NB: I am a recent user of C++ .
Thank you in advance
Problem
ifstream get(input); is also a C++11-ism. Before C++11, you cannot use a std::string as an argument to the std::ifstream constructor. It only accepts file names as a pointer to a null-terminated char array.
Quick Fix:
ifstream get(input.c_str());// c_str provides a null-terminated character array
Smarter Fix:
But since you have to pull out the stringstream for the number, you might as well go all in and use the stringstream to format the whole file name:
ostringstream temp;
temp << "pulse_value" << i << ".dat";
ifstream get(temp.str().c_str());
I need to read a text file that's in this format:
n k
S1
S2
S3
.
.
.
Sn
N being and integer, and S's being strings. Now, as far as I've seen a string cannot be read with fscanf function, but rather an array of char's has to be used.
The problem is that I need to set the length of the character array even though I have no way of knowing how long a word will be:
in = fopen("01.in", "r");
int N, k;
fscanf(in, "%d %d", &N, &k);
for (int i=0; i<N; i++){
char temp[100];
fscanf(in, "%s", temp);
}
So is there a way to maybe use vectors or something?
Or maybe in the off case that this problem cannot be solved, can I convert a string of chars into a string, and then create a vector of strings?
Why not use std::ifstream and std::getline something like this:
std::ifstream in("01.in");
int N, k;
if(!(in >> N >> k))
{
std::cerr << "Error reading file!" << '\n';
return EXIT_FAILURE;
}
std::string line; // read lines into this
int i = 0;
while(i < N && std::getline(in, line))
{
// deal with line here
++i; // keep track
}
The first step towards code sanity here is to stop using char arrays and start using std::string instead. The big difference between the two is that an array's size is set in stone at compile time, whereas a std::string's initial size can be can be chosen at runtime, and it can also grow and shrink while the program runs.
Now, as far as I've seen a string cannot be read with fscanf function,
but rather an array of char's has to be used.
Since C++11, that's not strictly true. std::strings are in many ways compatible with C functions. For example, you can safely get a pointer to the underlying buffer with &s[0]. Therefore, you could technically do this:
std::string temp(100, '\0');
fscanf(in, "%s", &temp[0]);
But that has not gotten us far. Apart from some other bad things about this "solution" (unidiomatic, undefined behaviour if too many characters are read, wasteful if too few characters are read), as you can see, the original problem still persists; the number 100 is hard-coded in the program. This is the real problem, as you have also said in the comment you added:
What I mean is what if I get a string that's longer than 100 characters?
The answer to that is: Just don't use fscanf anymore. Use std::ifstream along with the std::getline function. std::getline reads a whole line, i.e. everything until the next line break, and stores the result in a std::string. Size and memory management are all handled automatically for you:
std::ifstream is("01.in");
std::string temp;
std::getline(is, temp);
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
}
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());
I have a text file with numbers ranging from 0-255 separated by commas. I want to be able to store each of these numbers into an integer array. An example of what the text file might contain is;
"32,51,45,12,5,2,7,2,9,233,132,175,143,33..." etc
I have managed to get my program to store the data from the text file as a string and output them on the screen. What I need to do next is store the values of that string in an integer array, separating the numbers by the commas.
Here is the code I have written so far, which I am having problems getting it working;
int _tmain(int argc, _TCHAR* argv[])
{
string line;
ifstream myfile ("example.txt");
if (myfile.is_open())
{
while ( myfile.good() )
{
getline (myfile,line);
cout << line << endl;
}
myfile.close();
}
else cout << "Unable to open file";
//STRING CONVERSION
std::string str = line;
std::vector<int> vect;
std::stringstream ss(str);
int i = 0;
while (ss >> i)
{
vect.push_back(i);
if (ss.peek() == ',')
ss.ignore();
}
system("pause");
return 0;
It looks like your code for tokenizing your string is bit off. In particular you need to make sure you call atoi() on the string of your integer to get an integer. I'll focus on the parsing of the string though.
One thing you could use is C's strtok. I recommend this mainly because your case is rather simple, and this is probably the simplest way to go about it.
The code you'd look for is essentially this:
char* numStr = strtok(str.c_str(), ",");
while (numStr)
{
vect.push_back(atoi(numStr));
numStr = strtok(NULL, ",");
}
strtok() takes two arguments: a pointer to the C-style string (char*) you're tokenizing, and the string of delimiters (note that each character in the delimiter string is treated as its own delimiter).
I should mention that strtok is not thread-safe, and you also have to ensure that the string you extract from the file ends with a null character \0.
The answers to this question provide many alternatives to my solution. If you'd prefer to use std::stringstream then I suggest you look at the 5th answer on that page.
Regarding your trouble with PDBs, what is the exact error you're getting?