Different values on the function implementation - c++

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?

Related

C++ format int numbers to separate thousands with a dot

I'm working on Eclipse, on Fedora. I want to make a number more understandable using a dot to separate the thousands. This number is an integer Value that can be 0<Value<99.999
So... if Value = 1000 it shows 1000 and what I want is to show 1.000 (note the dot). The code I need to change is the next one:
char str[12];
sprintf(str, "%d", (int)(Value));
m_Text.SetText(str);
And what I thought is to do something like:
if (Value > 999)
{
int RightPart = (int)Value % 1000;
int LeftPart = Val/1000 ;
}
And then append in a string LeftPart + "." + RightPart so if Value = 1563 it will be 1+.+563 which is 1.563
My problem is that it's very ugly to do this and I was wondering if there were a better way of doing it. I've searched on google and found imbueand localebut they are only for cout. I've see too some posts like this and this but this doesn't help me with my problem.
Thank you.
NOTE: I want to remark that I DON'T WANT to change the output format. I want to change the int I receive so I can have the dots in the str var with which I will work later.
NOTE 2: Basically the code has to: receive an integer (Value), and send it like a string to setText(). setText() will basically print it on the screen where and when it has to, and I want it to print 1.563 and not 1563 which is more difficult to read.
Use stringstream and same imbue technique for it.
For example:
struct dotted : std::numpunct<char> {
char do_thousands_sep() const { return '.'; } // separate with dots
std::string do_grouping() const { return "\3"; } // groups of 3 digits
static void imbue(std::ostream &os) {
os.imbue(std::locale(os.getloc(), new dotted));
}
};
and then:
std::stringstream ss;
dotted::imbue(ss);
ss << Value;
std::cout << ss.str();
Demo
#include <iomanip>
#include <locale>
#include <iostream>
#include <sstream>
using namespace std;
template<class T>
string format(T value)
{
stringstream ss;
ss.imbue(locale(""));
ss << fixed << value;
return ss.str();
}
int main(int argc, char argv[])
{
cout.imbue(locale(""));
cout << 1000000 << endl;
return 0;
}
Prints:
1.000.000
You should probably look at which locale is used when "" is passed and change it with a more appropriate one.
Or vice versa:
int str_to_nr(string str)
{
int val;
stringstream ss(str);
ss.imbue(locale(""));
ss >> val;
return val;
}
int main(int argc, char argv[])
{
cout << str_to_nr("1.000") << endl;
return 0;
}
Prints:
1000
#gandgandi's answer basically gives you a technique to print out the value with dots on demand using C++ streams.
sprintf (which is generally not safe to use, BTW) is a C library function. C does not provide a mechanism to alter the locale behavior in the same way C++ provides. In C, you will have to define the locale behavior with mechanisms/tools provided by your operating system and assign it a name. Then, you can use the C function setlocale to alter the locale in the program to the one you have created to get it to print how you want. However, this will only work on machines that have the locale you have created installed. It won't work on any other machine.
With only a little bit of work and almost no creative effort, you can just use the C++ solution already provided combined with a call to sprintf.
char str[12];
stringstream ss;
dotted::imbue(ss);
ss << Value;
sprintf(str, "%s", ss.str());
m_Text.SetText(str);
But, there is really no reason to use sprintf at all:
stringstream ss;
dotted::imbue(ss);
ss << Value;
m_Text.SetText(ss.str());

Making a sequential list of files

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
}

String as a parameter (C++)

Is this example code valid?
std::string x ="There are";
int butterflies = 5;
//the following function expects a string passed as a parameter
number(x + butterflies + "butterflies");
The main question here is whether I could just pass my integer as part of the string using the + operator. But if there are any other errors there please let me know :)
C++ doesn't do automatic conversion to strings like that. You need to create a stringstream or use something like boost lexical cast.
You can use stringstream for this purpose like that:
#include <iostream>
#include <sstream>
using namespace std;
int main()
{
stringstream st;
string str;
st << 1 << " " << 2 << " " << "And this is string" << endl;
str = st.str();
cout << str;
return 0;
}
A safe way to convert your integers to strings would be an excerpt as follows:
#include <string>
#include <sstream>
std::string intToString(int x)
{
std::string ret;
std::stringstream ss;
ss << x;
ss >> ret;
return ret;
}
Your current example will not work for reasons mentioned above.
No, it wouldn't work. C++ it no a typeless language. So it can't automatically cast integer to string. Use something like strtol, stringstream, etc.
More C than C++, but sprintf (which is like printf, but puts the result in a string) would be useful here.

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/

converting integer to string C++

I am trying to convert an integer to char array and I came across this piece of code
int i = 5;
std::string s;
std::stringstream out;
out << i;
s = out.str();
But when I try to print the value of s it still prints 5. I don't know if its supposed to do that or am I doing something wrong? Besides I would prefer if I could convert the same int to char array. But I would appreciate any help in the matter.
Thanks!
Code taken from: Alternative to itoa() for converting integer to string C++?
Yes, it's supposed to do that. You'd (primarily) notice the difference from just printing a number out directly if you do some other string-type manipulation on the result (e.g., concatenating it with other strings, searching for characters in the string).
Just for example:
std::cout << i+i; // should print "10"
std::cout << s+s; // should print "55"
Besides I would prefer if I could convert the same int to char array.
char *charPtr = new char[ s.length() + 1 ] ; // s is the string in the snippet posted
strcpy( charPtr, s.c_str() ) ;
// .......
delete[] charPtr ; // Should do this, else memory leak.
If you would like to stop worrying about issues like that you might be interested in boost/lexical_cast.hpp.
#include <boost/lexical_cast.hpp>
#include <string>
#include <iostream>
int main() {
const int i=5;
const char* s = boost::lexical_cast<std::string>(i).c_str();
std::cout << s << std::endl;
}