Getline Function Messing with Code - c++

Picking up C++ and having a go at it on OS X 10.9 using XCode 5.0.2 and using Alex Allain as reference.
The following code compiles just fine and outputs correctly
#include <iostream>
#include <string>
using namespace std;
int main()
{
std::string user_first_name = "test";
std::cout << user_first_name << "\n";
return 0;
}
When I add a getline function, code appears to compile but with no output.
#include <iostream>
#include <string>
using namespace std;
int main()
{
std::string user_first_name = "test";
std::getline( std::cin, user_first_name, '\n' );
std::cout << user_first_name << "\n";
return 0;
}
In fact debug navigator has memory filling up with bars (although actual memory use is fixed at 276 KB). Why am I getting stumped on such a simple thing/concept?
I did a bit of digging around and its quite likely this is related to a text encoding issue. I'm using defaults which is Unicode (UTF-8). Encoding is not something I'm familiar with, never something I had to deal with when learning on Windows. How do I get past this?

I can't comment regarding the use of XCode or OS X, but it was my understanding that std::cin always gives you a narrow (single-byte) character stream. In Windows (at least with Visual Studio), I think it works whether you compile for UTF8 (single-byte for all ASCII characters) or UTF16 (2-bytes for all ASCII characters). The runtime library presumably does the conversion for you as necessary.
I'm not sure what "filling up with bars" means, but maybe it's just that you're looking at uninitialized memory. If you think that it is an encoding issue, perhaps try using wstring/wcin instead of string/cin and see if that helps.

Related

Unicode output not showing

I'm trying to learn Unicode programming in Windows.
I have this simple program:
#include <iostream>
#include <string>
int main()
{
std::wstring greekWord = L"Ελληνικά";
std::wcout << greekWord << std::endl;
return 0;
}
However, it outputs nothing. Any ideas how to make it output Greek?
I tried adding non-Greek letters, and that didn't work quite right either.
The first thing to try is to make the program not dependent on the encoding of the source file. So use Unicode escapes not literal Unicode letters
std::wstring greekWord = L"\u0395\u03BB\u03BB\u03B7\u03BD\u03B9\u03BA\u03AC";
Having the incorrect encoding in the source file is only one thing of many things that could be preventing you from printing Greek. The other obvious issue is the ability of your terminal to print Greek letters. If it can't do that, or needs to be set up correctly so that it can then nothing you do in your program is going to work.
And probably you want to fix the source code encoding issue, so that you can use unescaped literals in your code. But that's dependent on the compiler/IDE you are using.
If you are outputting your cout to a normal console then the console doesn't usually support unicode text like greek, try setting it up for unicode text or find another way to output your data, like txt files or some gui,
There are two way to do this.
The old, non-standard Microsoft way is as follows:
#include <fcntl.h>
#include <io.h>
int main()
{
_setmode(_fileno(stdout), _O_U16TEXT);
_setmode(_fileno(stdin), _O_WTEXT);
// your code here
}
You will fild this everywhere, but this is not necessarily a good way to solve this problem.
The more standards-compliant way is as follows:
#include <locale>
int main()
{
std::locale l(""); // or std::locale l("en_US.utf-8");
std::locale::global(l); // or std::wcout.imbue(l); std::wcin.imbue(l);
// your code here
}
This should work with other modern compilers and operating systems too.
TRY this it works with me :
#include
#include <io.h>
#include <fcntl.h>
using namespace std;
int main() {
_setmode(_fileno(stdout),_O_U16TEXT);
wcout<<L"Ελληνικά";
setlocale(LC_ALL,"");
return 0;
}

c++ Unable to output unicode characters even though I can write them directly

So thing is I can copy paste unicode characters like chess pieces directly to terminal( I'm using debian jessie linux) but whenever I write c++ code to do that, I get these � instead
here is my code
enter code here
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstdio>
using namespace std;
int main()
{
setlocale(LC_ALL,"");
wchar_t piece='♗';
wcout<<piece;
}
I tried to use the hex or decimal code of the characters but it does not work
I also use vim to edit and it does show the characters while I'm typing.
There's no specification of what encoding should be used for wchar_t. I need to use mbstowcs function to convert that character. Like this, for example:
#include <iostream>
#include <clocale>
#include <cstdlib>
using namespace std;
int main(void) {
setlocale(LC_ALL, "");
wchar_t piece;
mbstowcs(&piece, "♗", 1);
wcout << piece << endl;
return 0;
}
assuming your source file encoding matches the encoding of your locale.
Oddly enough what worked was going at it normally and putting the special character into a string it's so ridiculously simple I didn't even think to use it.
#include<iostream>
using namespace std;
int main()
{
string piece="♗";
cout<<piece;
}

Right aligning money_put results

I'm trying to get the C++ library to generate properly formatted USD output ($ sign, commas for every 1000s place etc).
I'm close, but I cannot get the right alignment to work:
#include <iostream>
#include <iomanip>
#include <locale>
using namespace std;
int main() {
double fiftyMil = 50000000.0; // 50 million bucks
locale myloc;
const money_put<char>& mpUS = use_facet<money_put<char> >(myloc);
cout.imbue(myloc);
cout << showbase << fixed;
cout << "A";
cout.width(30);
cout.setf(std::ios::right);
mpUS.put(cout, false, cout, ' ', fiftyMil * 100); // convert to cents
cout << "B" << endl;
return 0;
}
I'm getting:
A$50,000,000.00 B
I want to get:
A $50,000,000.00B
Any ideas why this isn't working?
I'm using the latest Solaris compiler (12.4)
Update:
It seems like the issue is with the C++ libraries included with the Solaris compiler. This is the workaround I used:
#include <iostream>
#include <iomanip>
#include <locale>
#include <sstream>
using namespace std;
string getFormattedCcy(double amt) {
ostringstream os;
static locale myloc;
static const money_put<char>& mpUS = use_facet<money_put<char> >(myloc);
os.imbue(myloc);
os << showbase << fixed;
mpUS.put(os, false, os, ' ', amt * 100);
return os.str();
}
int main() {
double fiftyMil = 50000000.0; // 50 million bucks
cout << "A";
cout.setf(std::ios::right);
cout.width(30);
cout << getFormattedCcy(fiftyMil);
cout << "B" << endl;
return 0;
}
You have a couple of problems--one with your code, another that looks like its in your implementation.
The problem in your code is pretty trivial. Since you're using a default-constructed locale, it should be using the "C" locale, which shouldn't write out the $ or thousands separators.
That part is easy to fix. Change: locale myloc; to: locale myloc(""); to get a localized locale (so to speak).
I doubt that'll fix the justification problem you're seeing though. That looks to me like it's a problem with the standard library you're using. When I run your code (with the correction above) I get what I'd expect:
A $50,000,000.00B
That's with Visual C++ though (and despite a compiler that conforms fairly poorly, its standard library is about as good as they come).
Also note that right justification is the default, so the line:
cout.setf(std::ios::right);
...should have no effect (but I suspect you knew that, and added it in the hope of getting it to work when it didn't otherwise).
As far as how to get things to work with the Sun Oracle compiler, the most obvious suggestion would probably be to switch standard libraries to one that works better. That leads to another question: whether to try to get a standard library to work with the compiler you're using, or switch to a different compiler such as CLang or gcc. From what I understand, 12.4 was a pretty serious improvement in terms of C++ conformance, but I don't think either the compiler or (apparently) the standard library is really competitive with gcc or Clang yet. OTOH, you may not have a choice, in which case essentially your only route is to build a different standard library with your existing compiler, and hope for the best. If you can't even do that...you could try setting the locale correctly, and just writing the number with std::cout << fiftyMil;, and hope it at least gives you commas as it should, then add the currency sign separately.
As an aside, if you do get an updated (C++11 or newer) library, you can use put_money to simplify the code quite a bit:
#include <iostream>
#include <iomanip>
#include <locale>
using namespace std;
int main() {
double fiftyMil = 50000000.0; // 50 million bucks
std::locale myloc("");
cout.imbue(myloc);
cout << "A" << showbase << setw(30) << put_money(fiftyMil * 100) << "B";
}

stringstream question

Here is some code that used to work with my code, but is having a problem now:
#include <iostream>
#include <fstream>
#include <sstream>
#include <cstring>
using namespace std;
int main()
{
stringstream out;
out << 100;
cout << out.str();
}
I get just blank output. I just changed to snow leopard with Xcode 3.2.
Get this exact same issue under the same conditions Snow Leopard 64-Bit XCode 3.2 Base SDK 10.6 and the switch to Base SDK 10.5 resolves it.
Apparently it's a SDK 10.6 issue.
and the correct workaround is to remove the preprocessor macros:
_GLIBCXX_DEBUG=1
_GLIBCXX_DEBUG_PEDANTIC=1
From the preprocessor settings (or else fall back to SDK 10.5 as above).
Apple Discussion Link
it works for me. if there's a problem, it should be your gcc's.
btw, maybe you have to add fflush(stdout); after the cout << sometime the problem is stdout buffer
#include <iostream>
#include <fstream>
#include <sstream>
#include <cstring>
using namespace std;
int main()
{
stringstream out;
out << 100;
cout << out.str();
fflush(stdout);
}
Another idea is that you have a .o file left over from before you upgraded that's somehow messing things up. Mixing .o files from two different versions of the C++ compiler can cause all kinds of strange problems. I also do not discount the header file issue as well, though sstream should be including string.
Shouldn't you add the end of string before converting to string?
cout << out.str() << sdt::ends;

Windows std::ifstream::open() problem

I know there's been a handful of questions regarding std::ifstream::open(), but the answers didn't solve my problem. Most of them were specific to Win32, and I'm using SDL, not touching any OS-specific functionality (...that's not wrapped up into SDL).
The problem is: std::ifstream::open() doesn't seem to work anymore since I've switched from Dev-C++ to Code::Blocks (I've been using the same MinGW-GCC back-end with both), and from Windows XP to Vista. (It also works perfectly with OS X / xcode (GCC back-end).)
My project links against a static library which #includes <string>, <iostream>, <fstream> and <cassert>, then a call is made to functionality defined in the static library, which in turn calls std::ifstream::open() (this time, directly). Following this, the stream evaluates to false (with both the implicit bool conversion operator and the good() method).
Code:
#include "myStaticLibrary.hpp"
int main(int argc, char **argv)
{
std::string filename("D:/My projects/Test/test.cfg");
std::cout << "opening '" << filename << "'..." << std::endl;
bool success(false);
// call to functionality in the static library
{
std::ifstream infile(filename.c_str());
success = infile.good();
// ...
}
// success == false;
// ...
return 0;
}
stdcout.txt says:
opening 'D:/My projects/Test/test.cfg'...
When I open stdcout.txt, and copy-paste the path with the filename into Start menu / Run, the file is opened as should be (I'm not entirely sure how much of diagnostic value this is though; also, the address is converted to the following format: file:///D:/My%20projects/test/test.cfg).
I've also tried substituting '/'s with the double backslash escape sequence (again, slashes worked fine before), but the result was the same.
It is a debug version, but I'm using the whole, absolute path taken from main()'s argv[0].
Where am I going wrong and what do I need to do to fix it?
Please create a minimal set that recreates the problem. For example, in your code above there's parsing of argv and string concatentation, which do not seem like a necessary part of the question. A minimal set would help you (and us) see exactly what's going wrong, and not be distracted by questions like "what's GetPath()?".
Try to do this instead of assert(infile.good()):
assert(infile);
I have overseen the importance of the fact that the function in question has close()d the stream without checking if it is_open().
The fact that it will set the stream's fail_bit (causing it to evaluate to false) was entirely new to me (it's not that it's an excuse), and I still don't understand why did this code work before.
Anyway, the c++ reference is quite clear on it; the problem is now solved.
The following code:
#include <string>
#include <iostream>
#include <fstream>
#include <assert.h>
using namespace std;;
int main(int argc, char **argv)
{
std::string filename("D:/My projects/Test/test.cfg");
std::cout << "opening '" << filename << "'..." << std::endl;
std::ifstream infile(filename.c_str());
assert(infile.good()); // fails
return 0;
}
works fine on my Windows system using MinGW g++ 4.4.0, if I create the required directory structure. Does the file test.cfg actually exist? If you are opening a stream for input, it wioll fail if the file is not there.
Edit: To remove any DevC++ to CB issues:
build using command line only
make sure you rebuild the static library too