Why is this C++ money_put<char> program not working? - c++

I am experimenting with C++ locales, and cannot work out why the output is 0.05 instead of 4.98.
#include <iostream>
#include <vector>
#include <string>
#include <locale>
using namespace std;
int main(int argc, const char** argv) {
vector<string> locales;
locales.push_back("de_DE");
locales.push_back("en_AU");
locales.push_back("en_GB");
locales.push_back("zh_CN");
long double amount = 4.98;
for (size_t i = 0, s = locales.size(); i < s; ++i) {
if (locales[i] != "C") {
cout.imbue(locale(locales[i].c_str()));
cout << i << " (" << locales[i] << "): ";
const moneypunct<char>& mp = use_facet<moneypunct<char> >(cout.getloc());
const money_put<char>& mv = use_facet<money_put<char> >(cout.getloc());
cout << mp.curr_symbol();
ostreambuf_iterator<char> out(cout);
mv.put(out, false, cout, cout.fill(), amount);
cout << endl;
}
}
return 0;
}
The output of the program is below:
0 (de_DE): Eu0,05
1 (en_AU): $0.05
2 (en_GB): £0.05
3 (zh_CN): ¥0.05
What am I doing wrong?

The (simplified) answer is that the money_put<char>.put() function refers to a long double parameter called units. This is the units in cents, not dollars.

[locale.money.put.virtuals]
The argument units is transformed into a sequence of wide characters as if by
ct.widen(buf1, buf1 + sprintf(buf1, "%.0Lf", units), buf2)
You can find exhaustive info on the cppreference page.

Related

Defining a string in an if statement

Im trying to make a number that is positive (already converted into a string) look like "+number" instead of "number" but i can't define it in an if
#include <iostream>
#include <string>
int main()
{
std::string x3s;
int number = 145;
if (number >= 0)
{
x3s = "+" + number;
}
std::cout << x3s << std::endl;
}
Firstly, there is an I/O manipulator std::showpos.
#include <iostream>
int main()
{
int number = 145;
std::cout << std::showpos << number << std::endl;
}
Secondly, you are using the verb "define" incorrectly.
You can use x3s = std::string("+") + std::to_string(number);

Typed string::length(). I got "Unable to resolve identifier length"

Using Win8.1 system. Using NetBeans IDE for C++ programming because it offers an easy way to make simple windows.
Code:
#include <cstdlib>
#include <iostream>
#include <ctime>
#include <string>
using namespace std;
int main(int argc, char** argv) {
srand(time(NULL));
int seed_component0 = rand();
string Player_name;
string seed_component1;
int i = 0;
cout << "Please, enter your player name: ";
cin >> Player_name;
while (i < Player_name.length()){
seed_component1.append(int(Player_name[i]));
i++;
}
string seed = seed_component0 + seed_component1;
cout << endl << "The seed we will use is " << seed << endl;
return 0;
}
That's just the main file, I only created a new project and tried to do that, but when I tried to run it it threw "Unable to resolve identifier length"
I also tried with size(). It just doesn't know what that is.
Also I have another error that doesn't affect the program, at least for now; in the include lines, it says"Library file (path) but there is an unresolved #include < stddef.h > in included file (path) wctype.h"
I am using MinGW as the compiler.
Edit: I also wanted to use to_string() and it didn't work either.
I tried to use sstream instead of to_string() for conversion. I also replaced your while loop with a for loop. The size() works for me though
Just take a look at http://www.cplusplus.com/articles/D9j2Nwbp/ which is about converting numbers to strings and vice versa
#include <cstdlib>
#include <iostream>
#include <ctime>
#include <string>
#include <sstream>
using namespace std;
string IntToString(int Number)
{
ostringstream ss;
ss << Number;
return ss.str();
}
int main(int argc, char** argv) {
srand(time(NULL));
int seed_component0 = rand();
string Player_name;
string seed_component1;
int i = 0;
cout << "Please, enter your player name: ";
cin >> Player_name;
int name_length = Player_name.size();
for(int i = 0; i < name_length; i++)
{
seed_component1 += IntToString(int(Player_name[i]));
}
string seed = IntToString(seed_component0) + seed_component1;
cout << endl << "The seed we will use is " << seed << endl;
return 0;
}
Setting both C and C++ to version 11 helped to resolve "unable to resolve length()" issue. Haven't tried to sec C++ v14 or v17 yet

How to print an array of const chars?

I have written the following code to save in an char * array and print the following content:
band1.txt
band2.txt
...
band3.txt
The code seems right but what is printed on the console is very weird.
Code:
const char ** current_band = new const char * [103];
stringstream sstm;
string str;
for (i=0;i<103;i++){
current_band[i] = new char[11];
}
for (i=0;i<103;i++){
sstm.str("");
sstm << "band" << i+1 << ".txt";
str = sstm.str();
current_band[i] = str.c_str();
cout << current_band[i] << endl;
cout << i << endl;
}
for (i=0;i<103;i++){
cout << current_band[i] << endl;
cout << i << endl;
}
Console:
band1.txt
0
band2.txt
1
...
band103.txt
102
And then for the last loop:
band103.txt
0
band102.txt
1
band103.txt
2
band102.txt
3
...
band102.txt
101
band103.txt
102
How is this even possible?
EDIT: Actually i want the "bands" to be char* in order to call the ifstream current_band_file(current_band) constructor that wants such an argument
You have undefined behavior by using pointers to already destroyed objects.
Simply don't use raw pointers and raw arrays and such stuff yet.
std::string is your friend for strings, std::vector is your friend for arrays.
Example:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
auto main()
-> int
{
vector<string> band_names;
for( int i = 1; i <= 103; ++i )
{
band_names.push_back( "band" + to_string( i ) );
}
for( string const& name : band_names )
{
cout << name << endl;
}
}
As a minimal change to you existing code you can change:
current_band[i] = str.c_str();
to:
strcpy(current_band[i], str.c_str());
However, moving away from this mixed C and C++ to more idiomatic C++ (like Cheers and hth. - Alf's answer) will serve you better for the future.
Sticking with things like char[11] over std::string means you're stuck with:
The arbitrary choice of max length 11 even though probably there is no good technical reason for that limit.
Dealing with handling all the details of memory allocation which a proper C++ implementation hides.
The much less natural to read lower level code style.
As a band-aid you could replace:
current_band[i] = str.c_str();
with
if ( str.size() >= 11 )
throw std::runtime_error("string too long");
std::strcpy(current_band[i], str.c_str());
However it would be a much better idea to replace this whole thing with:
std::vector<std::string> current_band(103);
int i = 0;
for (auto &s : current_band)
{
// your sstm stuff, storing to s
}
Here's an alternative way that's a little more robust, readable and more likely to be correct.
#include <vector>
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int main()
{
vector<string> bands;
bands.reserve(103);
for(size_t i = 1 ; i <= 103 ; ++i) {
ostringstream ss;
ss << "band" << i;
bands.emplace_back( ss.str() );
}
for (size_t index = 0 ; index < bands.size() ; ++index) {
cout << index << " : " << bands[index] << endl;
}
return 0;
}
output:
Compiling the source code....
$g++ -std=c++11 main.cpp -o demo -lm -pthread -lgmpxx -lgmp -lreadline 2>&1
Executing the program....
$demo
0 : band1
1 : band2
2 : band3
...
100 : band101
101 : band102
102 : band103

could you explain the reasons about output when using std::hex and std::wios::hex in C++

I have three programs.
the code of programA is shown below:
#include "stdafx.h"
#include <iostream>
#include <sstream>
#include <locale>
using namespace std;
int _tmain( void )
{
wstringstream s2;
TCHAR waTemp2[4] = {0xA0, 0xA1, 0x00A2, 0xA3};
for (int i = 0; i < 4; i++)
{
s2<< hex <<(unsigned int)waTemp2[i] << " ";
}
wstring strData2 = s2.str();
wcout << strData2.c_str() <<endl;
return 0;
}
here is the output:
a0 a1 a2 a3
the code of programB is shown below:
#include "stdafx.h"
#include <iostream>
#include <sstream>
#include <locale>
using namespace std;
int _tmain( void )
{
wstringstream s2;
TCHAR waTemp2[4] = {0xA0, 0xA1, 0x00A2, 0xA3};
for (int i = 0; i < 4; i++)
{
s2<< hex << waTemp2[i] << " ";
}
wstring strData2 = s2.str();
wcout << strData2.c_str() <<endl;
return 0;
}
here is the output:
????
the code of the programC is shown below:
#include "stdafx.h"
#include <iostream>
#include <sstream>
#include <locale>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
wstringstream s2;
TCHAR waTemp2[4] = {0xA0, 0xA1, 0x00A2, 0xA3};
for (int i = 0; i < 4; i++)
{
s2 << std::wios::hex <<(unsigned int)waTemp2[i] << " ";
}
wstring strData2 = s2.str();
wcout<< strData2.c_str() <<endl;
return 0;
}
here is the output:
2048160 2048161 2048162 2048163
could you tell me the reasons the difference between std::wios::hex and std::hex, std::hex << waTemp2[i] and std::hex << (unsigned int)waTemp2[i] resulted in different of the output.
thank you very much!
std::hex is a manipulator. It sets the stream to output hex when you pass an integer. It is equivalent to calling setf(std::wios::hex, std::wios::basefield); on the stream (assuming wide streams). For example, try the following modification of your code. You should see the same results.
wchar_t waTemp2[4] = {0xA0, 0xA1, 0x00A2, 0xA3};
s2.setf(std::wios::hex, std::wios::basefield);
for (int i = 0; i < 4; i++)
{
s2 << (unsigned)waTemp2[i] << " ";
}
std::wios::hex is a constant number used as a bitmask flag. Do not confuse it with a manipulator which sets the stream.
On coliru for example the following prints 8.
std::cout << std::wios::hex;
It is used as a bitmask to update the format flags on the stream. It will defined something like the following (see the real definition in libstdc++ here):
enum fmtflags
{
_hex = 1L << 3,
};
class ios_base
{
static const fmtflags hex = _hex;
};
The reason you are seeing 2048160 2048161 2048162 2048163 is it is just printing out the numbers of std::wios::hex and (unsigned int)waTemp2[i]. Add a space in between to see s2 << std::wios::hex << " " << (unsigned int)waTemp2[i] << " ";
The problem with s2 << hex << waTemp2[i] << " "; is std::hex is only used for integers. Since wchar_t is not an integer, it just prints the corresponding character.

convert string to integer in c++

Hello
I know it was asked many times but I hadn't found answer to my specific question.
I want to convert only string that contains only decimal numbers:
For example 256 is OK but 256a is not.
Could it be done without checking the string?
Thanks
The simplest way that makes error checking optional that I can think of is this:
char *endptr;
int x = strtol(str, &endptr, 0);
int error = (*endptr != '\0');
In C++ way, use stringstream:
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int main()
{
stringstream sstr;
int a = -1;
sstr << 256 << 'a';
sstr >> a;
if (sstr.failbit)
{
cout << "Either no character was extracted, or the character can't represent a proper value." << endl;
}
if (sstr.badbit)
{
cout << "Error on stream.\n";
}
cout << "Extracted number " << a << endl;
return 0;
}
An other way using c++ style : We check the number of digits to know if the string was valid or not :
#include <iostream>
#include <sstream>
#include <string>
#include <cmath>
int main(int argc,char* argv[]) {
std::string a("256");
std::istringstream buffer(a);
int number;
buffer >> number; // OK conversion is done !
// Let's now check if the string was valid !
// Quick way to compute number of digits
size_t num_of_digits = (size_t)floor( log10( abs( number ) ) ) + 1;
if (num_of_digits!=a.length()) {
std::cout << "Not a valid string !" << std::endl;
}
else {
std::cout << "Valid conversion to " << number << std::endl;
}
}