I wanna use sscanf to get something from a string - regex

The row string is Chinese,e.g. "九张".And the regular expression is "%[^张]";
Code segment:(mingw-32 ,windows10)
char szTemp[64] = {0};
sscanf("九张","%[^张]",szTemp);
printf("szTemp = [%s]\n",szTemp);
szTemp = [綸
When I print szTemp's value ,it was messed up codes;
But,when I replace "九" to "一", it work.
char szTemp[64] = {0};
sscanf("九张","%[^张]",szTemp);
printf("szTemp = [%s]\n",szTemp);
szTemp = [一]
My development environment is Fedora21.
Thanks

Related

String formation from hex string

I m trying to create hash of file by reading its content, and then hashing it using SHA1, after this I m trying to create a filename with this hash value, but the issue only first two char of hash string is taken.
Hash function
void hash(const std::string& content, std::string& retValue, bool isFile)
{
SHA_CTX ctx;
SHA1_Init(&ctx);
SHA1_Update(&ctx, content.c_str(), content.size());
if (isFile) {
FILE* f = fopen(content.c_str(),"r");
assert(f != NULL);
char buffer[1024]={0};
while(fgets(buffer,1024,f))
SHA1_Update(&ctx,buffer,strlen(buffer));
fclose(f);
}
unsigned char hash[SHA_DIGEST_LENGTH] = {0};
SHA1_Final(hash,&ctx);
retValue.resize(60);
int cnt = 0;
for(int i=0;i<SHA_DIGEST_LENGTH;i++){
char ch[3] = {0};
sprintf(ch,"%02x",hash[i]);
retValue[cnt++] = ch[0];
retValue[cnt++] = ch[1];
retValue[cnt++] = ch[2];
}
std::cout<<retValue<<std::endl;
}
when I print hash value in console I get a valid looking val such as this 51d946cde43e90ec03493f88914ca948b5215916, but it contains only first two characters in this case '51', I switched to gdb to view the string, gdb shows me the string in a weird way 51\000d9\000\064\066\000cd\000e4\000\063e\000\071\060\000ec\000\060\063\000\064\071\000\063f\000\070\070\000\071\061\000\064c\000a9\000\064\070\000b5\000\062\06 1\000\065\071\000\061\066. I am saving file with std::ofstream. I have looked at prev answers that said this is a bug in gdb so it prints like this, but here I can see file getting created doesnt with only first char of hash.
Why is this happening?
Thank You.
-----------------------------------------------EDIT-------------------------------------------------------------------------
From comment of dvix, it got resolved, I was copying '\0' with ch[2], so basically I was needed to only copy first two character from each hex character, ch[0] and ch[1] and then place null at very end of string.
so the code inside of for loop should look like this
for(int i=0;i<SHA_DIGEST_LENGTH;i++){
char ch[3] = {0};
sprintf(ch,"%02x",hash[i]);
retValue[cnt++] = ch[0];
retValue[cnt++] = ch[1];
}
retValue[cnt] = '\0';
Here's a slightly shorter version that does the same thing:
for(int i=0;i<SHA_DIGEST_LENGTH;i++){
sprintf(retValue + cnt,"%02x",hash[i]);
cnt += 2;
}

How can I find text within an wchar_t* array

Sorry for what maybe will be an easy question to answer, but here we go.
itemname2 = tsection.htmlText.Data;
int rf = itemname2.rfind("'>");
itemname2 = itemname2.replace(0, rf + 2, "");
WriteLogFile(itemname2);
The code above works perfectly if I was to be passing a string into itemname2, however
tsection.htmlText.Data = wchar_t *TArray::Data
You can turn itemname2 into a std::wstring and then do it very similar way:
int rf = itemname2.rfind(L"'>");
itemname2 = itemname2.replace(0, rf + (2*sizeof(wchar_t)), "");
You need to use L prefix to let compiler interpret lietral string as a wide one.

C++ std::string length() or size() not working on method args

I have a method that that creates a MatLab array name from a file path and returns it as a std::string. the resulting string is passed into another method that writes the name to the file. When I try to get the length of the passed in string, it displays 0 when the length of the string is 12 or 13 chars.
My code:
bool MyClass::masterMethod(std::string fileURI){
FILE* dataStream;
// Assume dataStream is set up correctly
// Get arrayName from File URI
std::string arrayName = this->makeArrayNameFromPath( fileURI);
//Write array name to file
this->writeArrayName(arrayName , dataStream)
}
std::string MyClass::makeArrayNameFromPath(std::string filePathURI){
std::string tempString = filePathURI.substr(filePathURI.find_last_of('/')+1);
std::string returnString = "";
long index = 0;
for(long i = 0; i < tempString.length(); i++){
if((tempString[i] != ' ') && (tempString[i] != '.')){
returnString[index++] = tempString[i];
}
}
return returnString;
}
void MyClass::writeArrayName(std::string name , FILE *nameStream){
// long testLength = name.length();
// long testLength2 = name.size();
// const char* testChar = nam.c_str();
// long testCharLen = strlen(testChar);
// The size of the name is the number of Chars * sizeof(int8_t)
int32_t sizeOfName = (int32_t)(name.length() * sizeof(int8_t));
int32_t nameType = miINT8;
fwrite(&nameType , sizeof(int32_t) , 1 , nameStream);
fwrite(&sizeOfName, sizeof(sizeOfName), 1, nameStream);
fwrite(&name , sizeof(name[0]), sizeOfName , nameStream);
}
So I'm not sure why string::length is not working. If a create a std::string test = name, and print it , I can get the value of the string but can not get its length or size.
If I use const char* testName = name.c_str(); long test = strlen(testName), I get a the
correct value, but thought that wasn't necessary.
So any advice or suggestion is appreciated.
returnString[index++] = tempString[i]; doesn't do what you think it does. It's not adding additional space or length to the string, only overwriting memory at a location that the string doesn't actually own. I think returnString.append(1, tempString[i]) or similar should do it.
You never give the string a size, just trying to assign positions that isn't there.
Try this instead to add characters to the return value
returnString += tempString[i];

Spaces between characters in a string

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);

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.