using MultiByteToWideChar - windows

The following code prints the desired output but it prints garbage at the end of the string. There is something wrong with the last call to MultiByteToWideChar but I can't figure out what. Please help??
#include "stdafx.h"
#include<Windows.h>
#include <iostream>
using namespace std;
#include<tchar.h>
int main( int, char *[] )
{
TCHAR szPath[MAX_PATH];
if(!GetModuleFileName(NULL,szPath,MAX_PATH))
{cout<<"Unable to get module path"; exit(0);}
char ansiStr[MAX_PATH];
if(!WideCharToMultiByte(CP_ACP,WC_COMPOSITECHECK,szPath,-1,
ansiStr,MAX_PATH,NULL,NULL))
{cout<<"Unicode to ANSI failed\n";
cout<<GetLastError();exit(1);}
string s(ansiStr);
size_t pos = 0;
while(1)
{
pos = s.find('\\',pos);
if(pos == string::npos)
break;
s.insert(pos,1,'\\');
pos+=2;
}
if(!MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,s.c_str(),s.size(),szPath,MAX_PATH))
{cout<<"ANSI to Unicode failed"; exit(2);}
wprintf(L"%s",szPath);
}

MSDN has this to say about the cbMultiByte parameter:
If this parameter is -1, the function processes the entire input
string, including the terminating null character. Therefore, the
resulting Unicode string has a terminating null character, and the
length returned by the function includes this character.
If this parameter is set to a positive integer, the function processes
exactly the specified number of bytes. If the provided size does not
include a terminating null character, the resulting Unicode string is
not null-terminated, and the returned length does not include this
character.
..so if you want the output string to be 0 terminated you should include the 0 terminator in the length you pass in OR 0 terminate yourself based on the return value...

Related

Non-ASCII character casted on int

I would like to cast a non-ASCII character (for example 'ą') on int to get it number in UTF-8. When I do something like this:
#include <iostream>
using namespace std;
int main()
{
cout << static_cast<int>('ą')<<endl;
return 0;
}
I get -71 what is not its proper number in UTF-8. I heard that it might be because 'ą' is stored in 2 bytes and one of them is cut away when initialization of variable. Any solution for this?

how can i safely convert an ascii integer back to its associated ascii character using curses in c++?

I have not been able to find a reliable solution for my problem, what i'm simply trying to do is create some function which:
takes an rows and columns position in the terminal.
calls mvinch(window_object , rows, cols), which returns an unsigned int which corresponds to the character in the terminal at that position.
returns the ascii character associated with that unsigned int, effectively casting it back to a char.
Here is an example of my code in c++11:
char Kmenu::getChrfromW(size_t const y, size_t const x,
bool const save_cursor) const {
size_t curr_y, curr_x;
getyx(_win, curr_y, curr_x);
char ich = mvwinch(_win, y, x);
char ch = ich;
if (save_cursor)
wmove(_win, curr_y, curr_x);
return ch;
}
If for example the character in the terminal at position 2,3 is the letter 'a', i want this function to return the letter 'a'.
I tried the solution described here:
Convert ASCII number to ASCII Character in C
which effectively casts an integer as char.
unfortunately what i get back is still the integer: testing with a screen filled with 'w's, i get back the integer 119.
the man page for the curses function mvwinch() describes the function to return chtype, which the compiler recognises as unsigned int.
Is there a built in a curses function which gives the char back directly without casting to unsigned int, or some other way i can achieve this?
Edit: ch to ich, as in the actual code
A chtype contains a character along with other data. The curses.h header has several symbols which are useful for extracting those bits. If you mask it with A_CHARTEXT and cast that to a char, you will get a character:
char c = (char)((A_CHARTEXT) & n);
Your example should not compile, since it declares ch twice. You may have meant this:
char Kmenu::getChrfromW(size_t const y, size_t const x,
bool const save_cursor) const {
int curr_y, curr_x; // size_t is inappropriate...
getyx(_win, curr_y, curr_x);
char ch = (char)((A_CHARTEXT) & mvwinch(_win, y, x));
// char ch = ich;
if (save_cursor)
wmove(_win, curr_y, curr_x);
return ch;
}
The manual page for mvwinch mentions the A_CHARTEXT mask in the Attributes section, assuming the reader is familiar with things like that:
The following bit-masks may be AND-ed with characters returned by
winch.
A_CHARTEXT Bit-mask to extract character
A_ATTRIBUTES Bit-mask to extract attributes
A_COLOR Bit-mask to extract color-pair field information

C++: No viable overloaded '=' data.end() -1 = '\0'

I'm trying to create a program that filters through speech text, removes any unwanted characters (",", "?", etc., etc.") and then produces a new speech where the words are jumbled based on what words follow or precede them. So for example, if you had the Gettysburg Address:
Four score and seven years ago our fathers brought forth, on this continent, a new nation, conceived in Liberty, and dedicated to the proposition that all men are created equal.
my program would take that text, put it into a set of strings. i.e. ["Four","score","and","seven",...."continent,"..."Liberty,"..."equal."] Then it would remove any unwanted characters from each string using c++ .erase and c++ .remove, like "," or "." and capitals. After, you'd have a filtered string like ["four","score","and","seven",...."continent"..."liberty"..."equal."]
After that then the words would be rearranged into a new coherent, funnier speech, like:
"Seven years ago our fathers conceived on men...", etc.
That was just so you know the scope of this project. My trouble at the moment has to do with either using my iterator properly or null terminators.
#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
#include <set>
#include <iterator> //iterates through sets
#include <algorithm>
using namespace std;
int main() {
set <string> speechSet;
set <string> ::iterator itr; //forgot what :: means. Declares iterator as set
int sum = 0;
int x;
string data;
ofstream out;
string setString;
ifstream speechFile; //declare output file stream object. Unknown type name
speechFile.open("./MySpeech");
if (!speechFile) {
cerr << "Unable to open file " << endl;
exit(1);
}
char unwantedCharacters[] = ".";
while (!speechFile.eof()) {
speechFile >> data; //speechFile input into data
for (unsigned int i = 0; i < strlen(unwantedCharacters); ++i) {
data.erase((remove(data.begin(), data.end(),
unwantedCharacters[i]), data.end())); //remove doesn't delete.
data.end() - 1 = '\0'; //Reorganizes
cout << data << endl;
}
speechSet.insert(string(data));
}
//Go through each string (word) one at a time and remove "",?, etc.
/*for(itr = speechSet.begin(); itr != speechSet.end(); ++itr){
if(*itr == ".")//if value pointed to by *itr is equal to '.'
itr = speechSet.erase(itr);//erase the value in the set and leave blank
cout << " " << *itr;//print out the blank
else{
cout << " " << *itr;
}
}*/
speechFile.close();
return (0);
}
I keep getting an error that says error: no viable overloaded '='. At first I thought it might be due to .end() not being a command for a C++ string, but I checked the documentation and it shouldn't be an issue of mismatched data typed. Then I thought it might have to set the iterator itr equal to the end of the data.
iterator itr = data.end() - 1;
and then dereference that pointer and set it equal to the null terminator
itr* = '\0';
That removed the overload error, but I still had another error use of class template 'iterator' requires template arguments. Let me know if any more clarification is needed.
In the for loop, use auto for iterator so you don't have to specify its type like:
for(auto itr = speechSet.begin(); itr != speechSet.end(); ++itr){

error when trasforming tolower, help would be nice

I'm trying to convert a txt file so all words can be lower case. and when I try I get an error I've tried to differ ways but no luck, my code is as followed
ifstream words("sample_doc.txt");
ofstream samp("sample.txt");
set <string> lower;
set <string> to_low;
copy(istream_iterator<string>(words), istream_iterator<string> (), inserter(lower, begin(lower)) );
transform(begin(lower), end(lower), inserter(to_low, begin(to_low) ), tolower );
when I tried to complete I get this error
'int (int)': cannot convert argument 1 from 'const std::basic_string,std::allocator>' to 'int'
Your problem is that int tolower(int ch); takes as argument an int or a char. However, you are passing it a std::string.
for(std::string& x: lower)
{
transform(x.begin(), x.end(), x.begin(), [](unsigned char c) { return std::tolower(c);});
to_low.insert(x);
}
If you change your last line to the above loop, it will convert each string in std::set<std::string> lower to a lower case string, character by character, and insert it in std::set<std::string> to_low
Hope this helps!

CryptStringToBinary not working with a NULL terminated string. Why?

does anyone know why this code is not working?
#include "stdafx.h"
#include <windows.h>
#include <WinCrypt.h>
int _tmain(int argc, _TCHAR* argv[])
{
wchar_t *bin = TEXT("ProductID:1233===>55555");
BYTE out2[1000];
DWORD olen;
olen = 1000;
if (CryptStringToBinary(bin, 0, 1, out2, &olen, 0, 0) == 0)
{
wprintf(TEXT("Failure\n"));
}
else
{
//wprintf(TEXT("rn%s\n"),out2);
wprintf(TEXT("Success\n"));
}
system("pause");
return 0;
}
Thank you very much in advance!
Tom
Because you specified a length (parameter 2) of 0?
Edit: Just to clarify our eventual solution in the comments below, the code in the original question (since edited) contained two errors:
It was calling CryptBinaryToString instead of CryptStringToBinary. Since it's invalid to pass a 0 in the second parameter to CryptBinaryToString, the function was failing.
It was passing 1 in the third parameter (dwFlags), which is interpreted as CRYPT_STRING_BASE64. Since the string to encrypt wasn't in base 64 (it contained invalid characters such as ':'), the function was failing. In general, passing a raw value instead of using an existing definition (e.g., CRYPT_STRING_BASE64) is not a good idea.

Resources