注册 登录
编程论坛 C++教室

C++求助 字符串遇到 0x00(二)

rosemaryzed 发布于 2021-12-15 18:11, 3063 次点击
https://bbs.bccn.net/viewthread.php?tid=502521&page=1#pid2732833
上次的问题在rjsp版的帮助下解决了,rjsp版果然厉害。
这次遇到一个新的问题,需要各位朋友的帮助,本人C++用的不多,学艺不精。
===========
拿到一个LPVOID* 指针,测试过发现指针的类型是wchar_t*。而且里面有数值。(数组中有非常多的0x00)。

我需要获取wchar_t*的数组长度。问题跟上一个贴一摸一样。上一次是用sizeof(char *)解决的。
这一次sizeof(wchar_t*)就算不出来了,请求指教。

如果用strlen(wcslen(wchar_t*))计算字符串长度,那么遇到0x00就退出。
wchar_t* p_t = _T("129099\0\0xxaa");
std::cout << wcslen(p_t);
std::cout << "\n";
std::cout << sizeof(p_t);
std::cout << "\n";
std::cout << sizeof(*p_t);
std::cout << "\n";
std::cout << sizeof(&p_t);

百度搜索了很多结果 有用while循环的。结果也是一样。跟wcslen一模一样,0x00忽略掉。
int arrayVlenth(_TCHAR* p)
{
    int len = 0;
    while (*p)
    {
        p++;
        len++;
    }
    return len;
}
int arrayLNlenth( _TCHAR** p)
{
    int len = 0;
    //while (**p)      //提示:0xC0000005: 读取位置 0xCDCDCDCD 时发生访问冲突。
    while (**p)          //**p是值
    {
        p++;
        len++;
    }
    return len;
}
13 回复
#2
rosemaryzed2021-12-15 18:12
@rjsp
#3
rjsp2021-12-16 08:23
看不懂,不知道你想干什么。

程序代码:
#include <iostream>
using namespace std;

int main( void )
{
    wchar_t a[10] = L"abc";
    cout << sizeof(a)/sizeof(*a) << endl; // 输出 10,即数组长度
    cout << size(a) << endl; // 与上一行等同
    cout << wcslen(a) << endl; // 输出 3,即字符串长度

    const wchar_t* p = L"abc\0def";
    cout << wcslen(p) << endl; // 输出 3,即字符串长度
   
// 你是获得不了它的数组长度的,因为不存在“数组长度”这个信息

   
// p 指向内存某处,它前面8个字符是"abc\0def\0",但后面还有数据呀,比如是 "abc\0def\0ghi\0……"
   
// 它怎么知道你只需要前面8个字符?你得告诉它呀
   
// 如果你依然是做 base64,那你应该把需要转换的长度传给函数
}
#4
rosemaryzed2021-12-16 19:49
回复 3楼 rjsp
感谢r版回复
    const wchar_t* p = L"abc\0def";
    cout << wcslen(p) << endl; // 输出 3,即字符串长度
我想要得到p的值是8我该怎么做。sizeof与wcslen都取不到。
#5
rosemaryzed2021-12-16 19:51
回复 3楼 rjsp
比如是 "abc\0def\0ghi\0……"
wchar_t* p "abc\0def\0ghi\0……";就像这种数据,我想要取到他的字符串长度,但是wcslen会被0x00卡住。sizeof又分别是4和2,我该怎么做
#6
rosemaryzed2021-12-16 19:52
回复 3楼 rjsp
r版,我获取到的wchar_t*不是const的,而且数据里面有大量0x00,该怎么获取他的长度。
#7
rjsp2021-12-17 08:16
仅仅一个指针是获取不了长度的。

指针保存着内存起始处的地址,它怎么可能知道你想要的内存有效长度是多少?
而对于字符串而言,那是因为互相约定好了“遇到\0即为终止”。

另外,你的“wchar_t*”不应该有L'\0',如果有L'\0'的话,那就不应该将之当成 宽字符串 看待。
举个例子,比如 L"abc",它可能的内存数据是 0x61 0x00 0x62 0x00 0x63 0x00 0x00 0x00,
作为 wchar_t[] 看待,它是 { 0x0061, 0x0062, 0x0063, 0x0000 } 这样的一个数组,除了结尾有 0x0000,其它地方不可能出现 0x0000。

拿到一个LPVOID* 指针,测试过发现指针的类型是wchar_t*。而且里面有数值。(数组中有非常多的0x00)。
这话很奇怪,里面有没有0x00都不是判断为wchar_t*的依据;
如果你说的 0x00 是指 L'\0' 的话,那就更奇怪了,既然里面有很多L'\0',那你为什么就判断它是wchar_t*,就类似于说“这盆水里面有大量的泥沙,所以它是纯净的”

直接说你想完成什么任务吧
#8
rjsp2021-12-17 13:35
我不知道你想完成什么功能,明说吧,我帮你写

程序代码:
#include <string>

std::string base64_encode( const void* p, size_t len )
{
    const char* base64char = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    const char padding_char = '=';

    const unsigned char* p_ = (const unsigned char*)p;
    const size_t base64_len = len/3*4 + (len%3!=0)*4; // (len+2)/3*4
    std::string base64( base64_len, '?' );
    for( size_t i=0; i!=len/3*4+len%3; ++i )
    {
        const size_t a = i/4*3 + i%4*3/4; // (i*6)/8
        const size_t b = i%4*6%8; // (i*6)%8
        unsigned char v = b<=2 ? (p_[a]>>(2-b)) : (p_[a]<<(b-2))|(p_[a+1]>>(10-b));
        base64[i] = base64char[v&0x3f];
    }
    if( len%3 == 1 )
    {
        base64[base64_len-3] = base64char[(p_[len-1]<<4)&0x3f];
        base64[base64_len-2] = padding_char;
        base64[base64_len-1] = padding_char;
    }
    else if( len%3 == 2 )
    {
        base64[base64_len-2] = base64char[(p_[len-1]<<2)&0x3f];
        base64[base64_len-1] = padding_char;
    }
    return base64;
}

#include <cassert>
#include <string.h>

void test( const char* s, const char* result )
{
    std::string out = base64_encode( s, strlen(s) );
    assert( out == result );
}

#include <iostream>
using namespace std;

int main( void )
{
    test( "", "" );
    test( "a", "YQ==" );
    test( "ab", "YWI=" );
    test( "abc", "YWJj" );
    test( "abc123@", "YWJjMTIzQA==" );
   
    unsigned char a[] = {172,237,5,51};
    string sa = base64_encode( a, sizeof(a) );
    cout << sa << endl;

    unsigned char b[] = {172,237,5,51,0};
    string sb = base64_encode( b, sizeof(b) );
    cout << sb << endl;

    unsigned char c[] = {172,237,5,51,0,172,237,5,51,172,237,5,51,172,237,5,51,172,237,5,51};
    string sc = base64_encode( c, sizeof(c) );
    cout << sc << endl;

    const wchar_t* d = L"大家好!";
    string sd = base64_encode( d, wcslen(d)*sizeof(*d) );
    cout << sd << endl;
}
#9
rosemaryzed2021-12-17 18:59
回复 7楼 rjsp
感谢r版回复,我先想想到底哪里出了问题。我也感觉我哪里有问题。我想想如何表述。
#10
rosemaryzed2021-12-17 19:24
回复 8楼 rjsp
r版,一时半会我不知如何表述,但是我感觉你说的对,我先查阅一下wchar_t*的资料。无法独自解决在来请教r版,谢谢r版解惑。
#11
rosemaryzed2021-12-19 17:33
结贴,自己看百度瞎鼓捣吧需求解决了。r版是对的,根据7楼回复给了很大启发在百度瞎鼓捣解决的。
总结一下就是怀疑wchar_t*内有0x00导致wcslen计算长度对不上,最后是这样解决的。
#define _UNICODE
_TCHAR* d = (_TCHAR*)lpvoida;//原来是这样指的 wcslen(d)计算出的长度对不上
TCHAR* d = (_TCHAR*)lpvoida;//获取到的LPVOID指过来
const size_t newsize = 8192;
wchar_t dest[newsize];
wcscpy(dest,d);//拷过来
主要需求是这样解决的
DWORD dlen = _tcslen(dest)//这样程序异常。长度对不上
DWORD dlen = _tcslen(dest) * sizeof(dest[0]);//这里+一个*sizeof(dest[0])就解决了。C艹太菜,不知道原理。目前理论解决需求。
我自己也描述不清楚我的需求跟解决方案。但是问题看起来暂时是解决了。
#12
rosemaryzed2021-12-19 17:33
回复 7楼 rjsp
感谢r版指点,我自己瞎弄好像弄好了。
#13
rjsp2021-12-19 18:55
我明白你的问题在哪里了

对于 const char* p = "abc"
strlen(p)等于3,说的是有3个有效char。而它所占用的字节数也是 3,因为C/C++规定“一个字节就是一个char所占用的内存”

对于 const wchar_t* p = L"abc"
wcslen(p)等于3,说的是有3个有效wchar_t。而它所占用的字节数却是 6(windows平台上wchar_t占2bytes,linux上wchar_t占4bytes),因为一个wchar_t并不就是占用一个byte。

对于任意的数组都是这样,比如
int a[3];
它有 3 个元素,但它占用的内存是 3 * sizeof(int)

[此贴子已经被作者于2021-12-19 18:56编辑过]

#14
rosemaryzed2021-12-31 22:04
回复 13楼 rjsp
R版好似醍醐灌顶,我感觉也是这个问题,字符串里面是没有0x00的,我搞错了。应该是R版说的这样。
1