Got a question about printing Integers with thousands/millions separator.
I got a Textfile where i got Country, City,Total Population.
I have to read in the File, and sort by country. If country is eual, i have to sort descending by population.
Textfile is like:
Australia........Sydney.........10.123.456
Brazil...........Sao Paulo.......7.123.345
I read all 3 into a seperated string. Then i erase all "." in the population string. Then i use atoi() to cast the population string to an integer.
Now i can sort by population if country is equal. This sort works correctly.
So far so good. But i need to get thousand/millions seperator into the printing of the population.
If i use string,with the "." for population, sorting dont work correctly.
Its sorted like:
x........x......1.123456
x........x......10.123.456
x........x......2.123.232
It have to look like:
Australia........Sydney.........10.123.456
Australia........Brisbane.......8.123.456
Is there a way to manipulate the printing by adding separator the the int again?
Many Thanks in advance
imbue() the output stream with a locale that has the desired separator. For example:
#include <iostream>
#include <locale>
int main()
{
// imbue the output stream with a locale.
int i = 45749785;
std::cout << i << "\n";
std::cout.imbue(std::locale(""));
std::cout << i << "\n";
}
Output on my machine (and online demo):
45749785
45,749,785
As commented, and answered, by James Kanze imbue the input stream also to read the separated int values without manually modifying the input.
See Stroustrop's Appendix D: Locales for a detailed overview of locales.
Use a locale which supports the desired separators to read the
file (that way you can read the values as integers), and the
same locale to write the data.
Note that you may not have such a locale available, or if you
do, you may not know its name (and using a named locale might
change other things, that you don't want changed); on my
machine, imbueing with "" behaves differently according to
the compiler (or maybe the shell I'm invoking it from)—you
should never use the locale "" if you have strict formatting
requirements. (The use of locale "" is for the case when you
want the format to depend on the users environment
specifications.)
In this case, it's probably better to provide the local explicitly:
class MyNumPunct : public std::numpunct<char>
{
protected:
virtual char do_thousands_sep() const { return ','; }
virtual std::string do_grouping() const { return "\03"; }
};
int
main()
{
std::cout.imbue( std::locale( std::locale::classic(), new MyNumPunct ) );
std::cout << 123456789 << std::endl;
return 0;
}
Of course, you'll want to use this locale for the input as well.
(This code will give you the "C" locale, with only the
grouping changed.)
Related
I want to create a file with C++ and write something in it. I have two classes, one with a Vererbung::writer(string name) and another subclass called Vererbung1(int zahl). Without the integer it works peferctly but when I want to write the integer to string and paste it after the function it wont work.
this works normally
Vererbung.cpp
void Vererbung::Writer(string name)
{
ofstream text;
text.open ("test.txt", ios::trunc);
text <<"write something\n";
text <<"again2 \n";
text <<"again 3\n";
text << name;
text.close();
}
Vererbung1.cpp
include "Vererbung.h"
void Vererbung1::Writer(int zahl)
{
std::ostringstream ostr;
ostr<< zahl;
name = "\n" "Test\n""Test\n""Test\n" ostr.str();
Vererbung::Writer(name);
}
When I run it in main it says that I need a ';' before ostr.str(); how can I fix this, If I want a integer value to string in a file in it?
This problem is very unclearly stated but, if we assume that name is an std::string, then:
name = "\n" "Test\n""Test\n""Test\n" ostr.str();
This is just a bunch of string literals written next to each other, followed by an std::string expression also just randomly floating there in free space.
Your computer doesn't know what you want it to do.
Although you actually can concatenate string literals in this way (literals are something like "hello world", but not something like aStringVariable), that doesn't apply to arbitrary expressions (and you don't even need it where you've used it).
I think that what you meant was this:
name = "\nTest\nTest\nTest\n" + ostr.str();
I hope that your C++ book teaches this; if not, get a better one.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I am doing a Date class which takes a string as a parameter that is like :
11/13/2007
9/23/2008
9/23/2008
... and set it month, date and year objects, How can I use the substr() function, or are there any other functions ?
In your case, I would use the good old C(!) sscanf function:
unsigned int year, month, day;
char c;
if(sscanf(input, "%u/%u/%u%c", &month, &day, &year, &c) == 3)
{
// check ranges of your date variables!
}
You seem to use American date format, so I set the parameters accordingly.
Wondering why I'm reading an additional character ? It catches additional data at the end of your date string to detect invalid formats (if data follows, result will be 4, otherwise, only 3 values are read, which will be returned). One drawback: before the three numbers, white space is ignored, so if you wanted to disallow, you would need additional checks (e. g. "%n %n%u" and comparing, if the two corresponding values are equal).
See sscanf documentation (scanf for parameters).
(If your input is a ::std::string instance, you need to use sscanf(input.c_str(), ...), of course.)
If you are using C++11 you can use <regex> library:
#include <iostream>
#include <regex>
#include <string>
int main() {
std::string date = "1/1/1970";
std::regex dateRegex("(\\d\\d?)/(\\d\\d?)/(\\d{4})");
std::smatch match;
if (regex_match(date, match, dateRegex)) {
std::cout << match.str(1) << std::endl;
std::cout << match.str(2) << std::endl;
std::cout << match.str(3) << std::endl;
}
else {
// error
}
return 0;
}
This is maybe an overkill for your situation but remember that by using regular expression you are also doing some form of validation on your input. In above example, if you pass anything that doesn't have the form dd/dd/dddd where "d" is a digit you will enter the "error" block of code. Of course, 99/99/9999 will count as a valid input but you can also solve that case with more complicated regex.
Another option for parsing strings with delimiter is using getline function.
It seems to me that defining the << operator (operator<<) to work directly with strings is more elegant than having to work with ostringstreams and then converting back to strings. Is there a reason why c++ doesn't do this out of the box?
#include <string>
#include <sstream>
#include <iostream>
using namespace std;
template <class T>
string& operator<<(string& s, T a) {
ostringstream ss;
ss << a;
s.append(ss.str());
return s;
}
int main() {
string s;
// this prints out: "inserting text and a number(1)"
cout << (s << "inserting text and a number (" << 1 << ")\n");
// normal way
ostringstream os;
os << "inserting text and a number(" << 1 << ")\n";
cout << os.str();
}
Streams contain additional state. Imagine if this were possible:
std::string str;
int n = 1234;
str << std::hex;
str << n;
return str; // returns "0x4d2" (or something, I forget)
In order to maintain this additional state, strings would have to have storage for this state. The C++ standards committee (and C++ programmers in general) have generally frowned upon superfluous resource consumption, under the motto "pay only for what you use". So, no extra fields in the string class.
The subjective answer: is that I think the std::string class was quite poorly designed to begin with, especially compared to other parts of C++'s excellent standard library, and adding features to std::string is just going to make things worse. This is a very subjective opinion and feel free to dismiss me as a raving lunatic.
The problem with the idea of strings being output streams is that they would become too heavy.
Strings are intended to "hold string data", not to format some output. Output streams have a heavy "state" which can be manipulated (see <iomanip>) and thus has to be stored. This means that, of course, this has to be stored for every string in every program, but almost none of them are used as an output stream; so it's a huge waste of resources.
C++ follows the "zero overhead" design principle (or at least no more overhead than totally necessary). Not having a string class which doesn't add any unnecessary overhead would be a huge violation of this design principle. If this was the case: what would people do in overhead-critical cases? Use C-strings... ouch!
In C++11, an alternative is to use the operator+= with std::to_string to append to a string, which can also be chained like the operator<< of the output stream. You can wrap both += and to_string in a nice operator<< for string if you like:
template <class Number>
std::string& operator<<(std::string& s, Number a) {
return s += std::to_string(a);
}
std::string& operator<<(std::string& s, const char* a) {
return s += a;
}
std::string& operator<<(std::string& s, const std::string &a) {
return s += a;
}
Your example, updated using this method: http://ideone.com/4zbVtD
Probably lost in the depths of time now but formatted output was always associated with streams in C (since they didn't have "real" strings) and this may have been carried over into C++ (which was, after all, C with classes). In C, the way to format to a string is to use sprintf, a variation on fprintf, the output-to-stream function.
Obviously conjecture on my part but someone probably thought similarly to yourself that these formatting things in the streams would be brilliant to have on strings as well, so they subclassed the stream classes to produce one that used a string as it's "output".
That seems the elegant solution to getting it working as quickly as possible. Otherwise, you would have had formatting code duplicated in streams and strings.
I have an enum that I'm doing a cout on, as in: cout << myenum.
When I debug, I can see the value as an integer value but when cout spits it out, it shows up as the text representation.
Any idea what cout is doing behind the scenes? I need that same type of functionality, and there are examples out there converting enum values to string but that seems like we need to know what those values are ahead of time. In my case, I don't. I need to take any ol' enum and get its text representation. In C# it's a piece of cake; C++.. not easy at all.
I can take the integer value if I need to and convert it appropriately, but the string would give me exactly what I need.
UPDATE:
Much thanks to everyone that contributed to this question. Ultimately, I found my answer in some buried code. There was a method to convert the enum value to a string representing the actual move like "exd5" what have ya. In this method though they were doing some pretty wild stuff which I'm staying away form at the moment. My main goal was to get to the string representation.
Enum.hpp:
enum Enum {
FOO,
BAR,
BAZ,
NUM_ENUMS
};
extern const char* enum_strings[];
Enum.cpp:
const char* enum_strings[] = {
"FOO",
"BAR",
"BAZ",
"NUM_ENUMS",
0 };
Then when I want to output the symbolic representation of the enum, I use std::cout << enum_strings[x].
Thus, you do need to know the string values, but only in one place—not everywhere you use this.
This functionality comes from the IOStreams library. std::cout is an std::ostream.
std::stringstream is an std::ostream too.
int x = 5;
std::stringstream ss;
ss << x;
// ss.str() is a string containing the text "5"
So...
when I go:
cout<<stringName<<endl;
I get:
NT
But when I go:
cout<<stringName.c_str()<<endl;
I get:
NTNT
Why?
A quick test with the following code:
#include <string>
#include <iostream>
using namespace std;
int main(void) {
string str = "NT";
cout << str.c_str() << endl;
return 0;
}
produces one instance of NT so it looks like you probably have another output call somewhere.
A traditional C string (accessed through a char const*) has a sequence of characters terminated by a character 0. (Not the numeral 0, but an actual zero value, which we write as '\0'.) There's no explicit length — so various string operations just read one character at a time until it hits the '\0'.
A C++ std::string has an explicit length in its structure.
Is it possible that the memory layout of your string's characters looks like this:
'NTNT\0'
but the string's length is set to 2?
That would result in exactly this behavior — manipulating the std::string directly will act like it's just two characters long, but if you do traditional C operations using s.c_str(), it will look like "NTNT".
I'm not sure what shenanigans would get you into this state, but it would certainly match the symptoms.
One way you could get into this state would be to actually write to the string's characters, something like: strcat((char *)s.c_str(), "NT")
Show more code. It seems like you did cout << ealier and forgot that you did it. What does it print if you do cout<< "mofo" << stringName.c_str()<< "|||" << endl; Does it say NTmofoNT||| ? if so that may well be what happened ;)
This is not a problem with c_str(), but probably related to some other anomaly in the rest of the program.
Make a "hello world" application that does these same operations and you'll see it works fine there.