Part 2 on encoding characters in C++ (by User123).
<- Go to the previous post.
I was yesterday making some code, and Paul Sanders in this question told me useful solution: He told me not to use std::cout << "something"; but to use std::wcout << L"something";.
But I have another problem. Now I want to do something like this (some special characters, but in array):
#include <iostream>
using namespace std;
string myArray[2] = { "łŁšđřžőšě", "×÷¤ßł§ř~ú" };
int main()
{
cout << myArray[0] << endl << myArray[1];
return 0;
}
But now I get something really unusual:
│úܰקÜý
θĄ▀│ž°~˙
If I add L in front of the array, I get (Visual Studio 2019):
C++ initialization with '{...}' expected for aggregate object
How can I represent these special characters but in the array?
#include <iostream>
using namespace std;
wstring myArray[2] = { L"łŁšđřžőšě", L"×÷¤ßł§ř~ú" };
int main()
{
wcout << myArray[0] << endl << myArray[1];
return 0;
}
L can only be applied directly to string literals. The result is a string literal of type wchar_t[] (wide character) rather then the usual char_t[] (narrow character), so you cannot save it in a string. You need to save it in a wstring. And to output a wstring you need to pass it to wcout, not cout.
Related
I would like to convert a hex-value ("206564697374754f") to a string (from hex to ascii). These hex-values are from gdb, so the contents are "reversed" by every two. (So the exact hex-value I need to convert is "4f75747369..."). reverse2() reverses the string appropriately, but it needs to now be converted to hex (hence the "0x", then atoi()).
The following code is what I have so far, but I run into a runtime-error. What is the issue, and is there a better way of doing this?
#include <bits/stdc++.h>
using namespace std;
void reverse2s(string str)
{
for (int i=str.length()-2; i>=0; i-=2) {
string hx="0x"+str[i]+str[i+1];
cout << (char)(std::stoi( hx ));
}
}
// Driver code
int main(void)
{
string s = "206564697374754f";
reverse2s(s);
return (0);
}
The expression "0x"+str[i]+str[i+1]; does not do what you think. "0x" is a character array (not a string). Since str[i] is a character, the addition will add convert that character to an int, and perform a pointer addition. This results in Undefined Behavior.
To do the string concatenation you're expecting, you need to create a string object first:
string hx="0x"s+str[i]+str[i+1];
"0x"s will create an actual string literal to append characters to.
Well it seems like you're just trying to print it as hex,
so you could do
std::cout << std::hex << 5 << std::endl; // prints 0x5
If you don't care about performance:
std::stringstream s;
s << std::hex << num:
s.str(); // std::string containing your number as hex
If you do care about performance I have no clue
This should work:
#include <iostream>
#include <strstream>
#include <string>
int main()
{
std::strstream s1; // dynamic buffer
s1 << std::hex << 12345 << std::endl;
std::cout << "buffer: '" << s1.str() << "'\n";
s1.freeze(false);
return 0;
}
I am trying to store a hex value in a string and latter retrieve it after some time, but while retrieving No value is coming size of the string is also coming 0. Sample code:
using namespace std;
int main() {
std::string s;
s.assign("\x00\x53"); // std::string s ="\x00\x53"
cout<<s.size();
}
output is coming 0
Try using \\ instead of \:
s.assign("\\x00\\x53");
Now you have:
#include <iostream>
using namespace std;
int main() {
std::string s;
s.assign("\\x00\\x53"); // std::string s ="\x00\x53"
cout << s.size() << endl;
cout << s << endl;
}
Output:
8
\x00\x53
From C++14 onwards, we have the option of using string literals, using that feature you can do this:
std::string s1 = "\x00\x53"s;
This will do what you expect and will return the correct value for size().
If you cannot use C++14 features, you need to use a string constructor that will allow you to specify the length of the string. You can do this:
std::string s1( "\x00\x53", 2);
You can see demo for both versions here.
I was trying to hold the text entered by user inside an Char array but it does not end up well. I tried this method but i think it deleted after c++ 11.
Here's my code :
#include "stdafx.h"
#include <iostream>
using namespace std;
int main()
{
char sentence[2];
cout << "Enter your sentences : ";
gets_s(sentence);
cout << sentence << endl;
system("PAUSE");
return 0;
}
It gives overload error and doesnt works.
Chances are you are trying to get the string literal that is longer than 2 characters yet not being able to insert it into your buffer of:
char sentence[2];
Increase the buffer size to something more acceptable:
char sentence[255];
That being said in C++ you should prefer std::string to character array and std::getline to gets_s.
Can someone explain to me how to properly search for a "tab" character stored in a string class?
For example:
text.txt contents:
std::cout << "Hello"; // contains one tab space
User enters on prompt: ./a.out < text.txt
main.cpp:
string arrey;
getline(cin, arrey);
int i = 0;
while( i != 10){
if(arrey[i] == "\t") // error here
{
std::cout << "I found a tab!!!!"
}
i++;
}
Since there is only one tab space in the textfile, I am assuming it is stored in index [0], but the problem is that I can't seem to make a comparison and I don't know any other way of searching it. Can someone help explain an alternative?
Error: ISO C++ forbids comparison between pointer and integer
First of all, what is i? And secondly, when you use array-indexing of a std::string object, you get a character (i.e. a char) and not a string.
The char is converted to an int and then the compiler tries to compare that int with the pointer to the string literal, and you can't compare plain integers with pointers.
You can however compare a character with another character, like in
arrey[i] == '\t'
std::string::find() might help.
Try this:
...
if(arrey.find('\t') != string::npos)
{
std::cout << "I found a tab!!!!";
}
More info on std::string::find is available here.
Why not using what C++ library provides? You could do it like this:
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main()
{
string arrey;
getline(cin, arrey);
if (arrey.find("\t") != std::string::npos) {
std::cout << "found a tab!" << '\n';
}
return 0;
}
The code is based on this answer. Here is the ref for std::find.
About your edit, how are sure that the input is going to be 10 positions? That might be too little or too big! If it is less than the actual size of the input, you won't look all the characters of the string and if it is too big, you are going to overflow!
You could use .size(), which says the size of the string and use a for loop like this:
#include <iostream>
#include <string>
using namespace std;
int main() {
string arrey;
getline(cin, arrey);
for(unsigned int i = 0; i < arrey.size(); ++i) {
if (arrey[i] == '\t') {
std::cout << "I found a tab!!!!";
}
}
return 0;
}
I have this code to serialize/deserialize class objects to file, and it seems to work.
However, I have two questions.
What if instead two wstring's (as I have now) I want to have one wstring and one string member
variable in my class? (I think in such case my code won't work?).
Finally, below, in main, when I initialize s2.product_name_= L"megatex"; if instead of megatex I write something in Russian say (e.g., s2.product_name_= L"логин"), the code doesn't work anymore as intended.
What can be wrong? Thanks.
Here is code:
// ConsoleApplication3.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include <string>
#include <fstream> // std::ifstream
using namespace std;
// product
struct Product
{
double price_;
double product_index_;
wstring product_name_;
wstring other_data_;
friend std::wostream& operator<<(std::wostream& os, const Product& p)
{
return os << p.price_ << endl
<< p.product_index_ << endl
<< p.product_name_ << endl
<< p.other_data_ << endl;
}
friend wistream& operator>>(std::wistream& is, Product& p)
{
is >> p.price_ >> p.product_index_;
is.ignore(std::numeric_limits<streamsize>::max(), '\n');
getline(is,p.product_name_);
getline(is,p.other_data_);
return is;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
Product s1,s2;
s1.price_ = 100;
s1.product_index_ = 0;
s1.product_name_= L"flex";
s1.other_data_ = L"dat001";
s2.price_ = 300;
s2.product_index_ = 2;
s2.product_name_= L"megatex";
s2.other_data_ = L"dat003";
// write
wofstream binary_file("c:\\test.dat",ios::out|ios::binary|ios::app);
binary_file << s1 << s2;
binary_file.close();
// read
wifstream binary_file2("c:\\test.dat");
Product p;
while (binary_file2 >> p)
{
if(2 == p.product_index_){
cout<<p.price_<<endl;
cout<<p.product_index_<<endl;
wcout<<p.product_name_<<endl;
wcout<<p.other_data_<<endl;
}
}
if (!binary_file2.eof())
std::cerr << "error during parsing of input file\n";
else
std::cerr << "Ok \n";
return 0;
}
What if instead two wstring's (as I have now) I want to have one
wstring and one string member variable in my class? (I think in such
case my code won't work?).
There are an inserter defined for char * for any basic_ostream (ostream and wostream), so you can use the result of c_str() member function call for the string member. For example, if the string member is other_data_:
return os << p.price_ << endl
<< p.product_index_ << endl
<< p.product_name_ << endl
<< p.other_data_.c_str() << endl;
The extractor case is more complex, since you'll have to read as wstring and the convert to string. The most simple way to do this is just reading as wstring and then narrowing each character:
wstring temp;
getline(is, temp);
p.other_data_ = string(temp.begin(), temp.end());
I'm not using locales in this sample, just converting a sequence of bytes (8 bits) to a sequence of words (16 bits) for output and the opposite (truncating values) for input. That is OK if you are using ASCII chars, or using single-byte chars and you don't require an specific format (as Unicode) for output.
Otherwise, you will need handle with locales. locale gives cultural contextual information to interpret the string (remember that is just a sequence of bytes, not characters in the sense of letters or symbols; the map between the bytes and what symbol represents is defined by the locale). locale is not an very easy to use concept (human culture isn't too). As you suggest yourself, it would be better make first some investigation about how it works.
Anyway, the idea is:
Identify the charset used in string and the charset used in file (Unicode or utf-16).
Convert the strings from original charset to Unicode using locale for output.
Convert the wstrings read from file (in Unicode) to strings using locale.
Finally, below, in main, when I initialize s2.product_name_=
L"megatex"; if instead of megatex I write something in Russian say
(e.g., s2.product_name_= L"логин"), the code doesn't work anymore as
intended.
When you define an array of wchar_t using L"", you'are not really specifying the string is Unicode, just that the array is of chars, not wchar_t. I suppose the intended working is s2.product_name_ store the name in Unicode format, but the compiler will take every char in that string (as without L) and convert to wchar_t just padding with zeros the most significant byte. Unicode is not good supported in the C++ standard until C++11 (and is still not really too supported). It works just for ASCII characters because they have the same codification in Unicode (or UTF-8).
For using the Unicode characters in a static string, you can use escape characters: \uXXXX. Doing that for every not-English character is not very comfortable, I know. You can found a list of Unicode characters in multiple sites in the web. For example, in the Wikipedia: http://en.wikipedia.org/wiki/List_of_Unicode_characters.