Spaces between characters in a string - c++

I am using Embarcadero C++Builder XE and I am trying to write 123456 to a textfile like this:
String teststring = "123456";
int iFileHandle = FileCreate("example.txt");
int iLength = teststring.Length()*sizeof(wchar_t);
int output = FileWrite(iFileHandle, teststring.w_str(), iLength);
But the output is this:
1 2 3 4 5 6
Spaces have been added after every character. I can see that iLength is 12 so are the spaces added when the string is created and how can I prevent this?

System::String is encoded in XE as UTF-16, which uses 16-bit values. Those "spaces" you see are the high-order bytes of those character values, which are nulls for ASCII character values. If you don't want those bytes in your file, then you have to convert the String to a different encoding that doesn't use them, eg:
String teststring = "123456";
AnsiString s = teststring; // or UTF8String, or any other MBCS encoding you want
int iFileHandle = FileCreate("example.txt");
int iLength = s.Length() * sizeof(AnsiChar);
int output = FileWrite(iFileHandle, s.c_str(), iLength);

You could just uses a string list and add the string you want to then then save the string list to file.
TStringList *Temp = new TStringList( );
Temp->Add("123456");
Temp->SaveToFile(("example.txt");
delete Temp;

iLength is supposed to be 12 since string length is 6 and size of wchar_t is 2 in this case.
So, indeed, spaces are not added when the string is created. These are 2., 4., 6., 8. and 10. bytes allocated and initialized to space character when you create a wide string from a string here:
teststring.w_str()
Try using c_str() instead:
String teststring = "123456";
int iFileHandle = FileCreate("example.txt");
int iLength = teststring.Length();
int output = FileWrite(iFileHandle, teststring.c_str(), iLength);

Related

Converting fractions (1/8, 3/8, 5/8, 7/8) to UTF-8 in C++

I have to display fractions using the symbols and I can't seem to be able to display these 4.
using
char UCP_VULGAR_FRACTION_ONE_HALF_UTF8 = L'\u00BD';
char UCP_VULGAR_FRACTION_ONE_QUARTER_UTF8 = L'\u00BC';
char UCP_VULGAR_FRACTION_THREE_QUARTERS_UTF8 = L'\u00BE';
I can get 1/2, 1/4 and 3/4 to display just fine (cout<< (char)UCP_VULGAR_FRACTION_ONE_HALF_UTF8), but doing the same for those fractions:
char UCP_VULGAR_FRACTION_ONE_EIGHTH_UTF8 = L'\u215B';
char UCP_VULGAR_FRACTION_THREE_EIGHTHS_UTF8 = L'\u215C';
char UCP_VULGAR_FRACTION_FIVE_EIGHTHS_UTF8 = L'\u215D';
char UCP_VULGAR_FRACTION_SEVEN_EIGHTHS_UTF8 = L'\u215E';
Gets me [, \, ] and ^. What am I doing wrong? I tried g_unichar_to_utf8 with no success...
For UTF-8 you need to store multibyte characters - characters contained in one or more bytes. Typically these are stored in a std::string:
std::string const UCP_VULGAR_FRACTION_ONE_EIGHTH_UTF8 = u8"\u215B";
std::string const UCP_VULGAR_FRACTION_THREE_EIGHTHS_UTF8 = u8"\u215C";
std::string const UCP_VULGAR_FRACTION_FIVE_EIGHTHS_UTF8 = u8"\u215D";
std::string const UCP_VULGAR_FRACTION_SEVEN_EIGHTHS_UTF8 = u8"\u215E";
Or possibly a null terminated char array:
char const* UCP_VULGAR_FRACTION_ONE_EIGHTH_UTF8 = "\u215B";
char const* UCP_VULGAR_FRACTION_THREE_EIGHTHS_UTF8 = "\u215C";
char const* UCP_VULGAR_FRACTION_FIVE_EIGHTHS_UTF8 = "\u215D";
char const* UCP_VULGAR_FRACTION_SEVEN_EIGHTHS_UTF8 = "\u215E";
Use wchar_t instead of char. Also be aware that you can't print wchar_t using std::cout, you need to use wide version of std::cout which is std::wcout. BTW, If you use wcout with cout together, the program will crash most probably. so you may want to store these unicode characters in normal UTF-8 std::string instead of wchar_t, and print them using std::cout

c++ initializing a default value for a c-style string in dynamic memory

So in c++ a normal c-style string can be initiated like this:
char cString[] = "my string";
How can I do the same thing using dynamic memory?
Why doesn't this work?
char *charPtr;
charPtr = new char("make this the value of the c string");
You can't just initialize a c-style string like that.
First of all you need a pointer, that points to the beginning of the string. Then need to allocate enough memory to hold that string, which is the number of characters + the terminating '\0'. You should include cstring header, for strlen and strcpy. At last you need to copy the string to the memory block.
char *str; //pointer to string
str = new char[strlen("The string to copy")+1]; //allocate memory
//strlen returns the number of charaters of a string exluding the '\0', so we need to add 1
//either use a string constant, or another cstyle string, or input the length manually
strcopy(str, "The string to copy");//strcpy copies the content of the string constant to str
//be sure to set the last element of the string to '\0'
str[strlen(str)] = 0; // or '\0'
//if str has 5 char it returns 4 because the last is \0
//but the array goes from 0 to 4, so 4 is the last element
And dont forget to use delete [ ] str; if you get rid of the string!

c++ to VB.Net IntPtr Strings

Alright so I have this code, and I pass it to an unmanaged dll, to which I only know the exports, and have some sample code. I'm getting back the correct string, but it's followed by garbage bytes.
I'm basically translating code verbatim from a c++ example program that doesn't have this issue. I'm assume there is something fundamental I am missing here, so if anyone could tell me what that is, I'd appreciate it.
Example C++ Code
void CDUKPT_TESTDlg::OnButton4()
{
// TODO: Add your control notification handler code here
unsigned char dataout[1024],tmp[1024],ksn[20],keyval[20];
int nRet,len;
memset(dataout,0,sizeof(dataout));
memset(ksn,0,sizeof(ksn));
memset(keyval,0,sizeof(keyval));
memset(tmp,0,sizeof(tmp));
UpdateData(TRUE);
two_one((unsigned char *)m_strCURKSN.GetBuffer(m_strCURKSN.GetLength()),m_strCURKSN.GetLength(),ksn);
two_one((unsigned char *)m_strMACK.GetBuffer(m_strMACK.GetLength()),m_strMACK.GetLength(),keyval);
two_one((unsigned char *)m_EncryptDat.GetBuffer(m_EncryptDat.GetLength()),m_EncryptDat.GetLength(),dataout);
len=m_EncryptDat.GetLength()/2;
//extern int __stdcall ExtractDat(unsigned char *input,
//unsigned short len,unsigned char *output,unsigned char *key,
//unsigned char *ksn);
nRet=ExtractDat(dataout,len,tmp,keyval,ksn); //External Call
//Good string+bad trailing data comes back in tmp
m_Result=tmp;
UpdateData(FALSE);
}
This code spits out this ܉Òdÿo 
Here is my VB.Net Code
Public Function Encrypt(ByVal inp As String) As String
Dim tmpSB As New StringBuilder
Dim i As Integer
Dim tKsn As Char() = TwoOne(StrCurKsn)
For i = tKsn.Length To 19
tKsn = tKsn + Chr(0)
Next
Dim tMack As Char() = TwoOne(StrMack)
For i = tMack.Length To 19
tMack = tMack + Chr(0)
Next
Dim tEnc As Char() = TwoOne(inp)
For i = tEnc.Length To 1023
tEnc = tEnc + Chr(0)
Next
Dim len As Integer = tEnc.Length / 2
Dim tmpStr(1023) As Char
Array.Clear(tmpStr, 0, 1024)
Dim tmpPtr = Marshal.StringToHGlobalAnsi(tmpStr)
Dim nRet = ExtractDat(tEnc, len, tmpPtr, tMack, tKsn)
tmpStr = Marshal.PtrToStringAnsi(tmpPtr)
Dim tsl = tmpStr.Length
Encrypt = tmpStr
End Function
This code spits this out
܉Òdÿo ålUäÙålUäÙålUäÙålUäÙålUäÙålUäÙålUäÙ
So I get the right string, but it's followed by a repeating string of garbage characters.
I'm hoping I've done something blatantly wrong here, but I've tried pulling the data as bytes, and chars, and converting in many different methods, and I can't seem to get rid of those characters...Also, ExtractDat doesn't return the length of the string(not a problem, as it's not supposed to, which is really annoying).
Turns out the dll was bad, so after I got a fresh compile from the vendor it seemed to work.

Why am i getting two different strings?

I wrote a very simple encryption program to practice c++ and i came across this weird behavior. When i convert my char* array to a string by setting the string equal to the array, then i get a wrong string, however when i create an empty string and add append the chars in the array individually, it creates the correct string. Could someone please explain why this is happening, i just started programming in c++ last week and i cannot figure out why this is not working.
Btw i checked online and these are apparently both valid ways of converting a char array to a string.
void expandPassword(string* pass)
{
int pHash = hashCode(pass);
int pLen = pass->size();
char* expPass = new char[264];
for (int i = 0; i < 264; i++)
{
expPass[i] = (*pass)[i % pLen] * (char) rand();
}
string str;
for (int i = 0; i < 264; i++)
{
str += expPass[i];// This creates the string version correctly
}
string str2 = expPass;// This creates much shorter string
cout <<str<<"\n--------------\n"<<str2<<"\n---------------\n";
delete[] expPass;
}
EDIT: I removed all of the zeros from the array and it did not change anything
When copying from char* to std::string, the assignment operator stops when it reaches the first NULL character. This points to a problem with your "encryption" which is causing embedded NULL characters.
This is one of the main reasons why encoding is used with encrypted data. After encryption, the resulting data should be encoded using Hex/base16 or base64 algorithms.
a c-string as what you are constructing is a series of characters ending with a \0 (zero) ascii value.
in the case of
expPass[i] = (*pass)[i % pLen] * (char) rand();
you may be inserting \0 into the array if the expression evaluates to 0, as well as you do not append a \0 at the end of the string either to assure it being a valid c-string.
when you do
string str2 = expPass;
it can very well be that the string gets shorter since it gets truncated when it finds a \0 somewhere in the string.
This is because str2 = expPass interprets expPass as a C-style string, meaning that a zero-valued ("null") byte '\0' indicates the end of the string. So, for example, this:
char p[2];
p[0] = 'a';
p[1] = '\0';
std::string s = p;
will cause s to have length 1, since p has only one nonzero byte before its terminating '\0'. But this:
char p[2];
p[0] = 'a';
p[1] = '\0';
std::string s;
s += p[0];
s += p[1];
will cause s to have length 2, because it explicitly adds both bytes to s. (A std::string, unlike a C-style string, can contain actual null bytes — though it's not always a good idea to take advantage of that.)
I guess the following line cuts your string:
expPass[i] = (*pass)[i % pLen] * (char) rand();
If rand() returns 0 you get a string terminator at position i.

Double null-terminated string

I need to format a string to be double null-terminated string in order to use SHFileOperation.
Interesting part is i found one of the following working, but not both:
// Example 1
CString szDir(_T("D:\\Test"));
szDir = szDir + _T('\0') + _T('\0');
// Example 2
CString szDir(_T("D:\\Test"));
szDir = szDir + _T("\0\0");
//Delete folder
SHFILEOPSTRUCT fileop;
fileop.hwnd = NULL; // no status display
fileop.wFunc = FO_DELETE; // delete operation
fileop.pFrom = szDir; // source file name as double null terminated string
fileop.pTo = NULL; // no destination needed
fileop.fFlags = FOF_NOCONFIRMATION|FOF_SILENT; // do not prompt the user
fileop.fAnyOperationsAborted = FALSE;
fileop.lpszProgressTitle = NULL;
fileop.hNameMappings = NULL;
int ret = SHFileOperation(&fileop);
Does anyone has idea on this?
Is there other way to append double-terminated string?
The CString class itself has no problem with a string containing a null character. The problem comes with putting null characters into the string in the first place. The first example works because it is appending a single character, not a string - it accepts the character as is without checking to see if it's null. The second example tries appending a typical C string, which by definition ends at the first null character - you're effectively appending an empty string.
You cannot use CString for this purpose. You will need to use your own char[] buffer:
char buf[100]; // or large enough
strcpy(buf, "string to use");
memcpy(buf + strlen(buf), "\0\0", 2);
Although you could do this by only copying one more NUL byte after the existing NUL terminator, I would prefer to copy two so that the source code more accurately reflects the intent of the programmer.