Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/155.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用istringstream处理可变长度的内存块_C++_String_Stl_Stringstream - Fatal编程技术网

C++ 使用istringstream处理可变长度的内存块

C++ 使用istringstream处理可变长度的内存块,c++,string,stl,stringstream,C++,String,Stl,Stringstream,我正试图使用istringstream从一些内存中重新创建一个编码的wstring。内存的布局如下所示: 1字节,表示wstring编码的开始。这是‘!’。 n字节以文本格式存储字符串的字符长度,例如0x31、0x32、0x33将为123,即123字符串 1字节分隔符—空格字符 n个字节,它们是组成字符串的wchars,其中wchar\u t各为2个字节。 例如,字节序列: 21362066006F006F00 是的!6 f.o.o.使用点表示字符0 我得到的只是一个char*指针,我们称之为p

我正试图使用istringstream从一些内存中重新创建一个编码的wstring。内存的布局如下所示:

1字节,表示wstring编码的开始。这是‘!’。 n字节以文本格式存储字符串的字符长度,例如0x31、0x32、0x33将为123,即123字符串 1字节分隔符—空格字符 n个字节,它们是组成字符串的wchars,其中wchar\u t各为2个字节。 例如,字节序列:

21362066006F006F00

是的!6 f.o.o.使用点表示字符0

我得到的只是一个char*指针,我们称之为pData,指向内存块的开头,其中包含编码数据。使用数据重建wstring foo并将指针移到编码数据末尾后的下一个字节的“最佳”方法是什么

我正在尝试使用istringstream来使用前缀字节、字符串长度和分隔符。之后,我可以计算要读取的字节数,并使用流的read函数插入到大小适当的wstring中。问题是,首先我如何将这些内存放入istringstream?我可以尝试先构造一个字符串,然后将其传递到istringstream,例如

std::string s((const char*)pData);
但这不起作用,因为字符串在第一个空字节处被截断。或者,我可以使用字符串的另一个构造函数显式说明要使用的字节数:

std::string s((const char*)pData, len);
这很有效,但前提是我事先知道len是什么。考虑到数据的长度是可变的,这很棘手


这似乎是一个真正可以解决的问题。我在字符串和流方面的新手身份是否意味着我忽略了一个简单的解决方案?还是我用“整串”方法选错了树?

试着设置你的stringstream:


编辑:我发现此解决方案将出现与stringchar*,len情况类似的问题。您能告诉我们更多关于缓冲区对象的信息吗?如果您不知道长度,并且它不是以null结尾的,那么将很难处理。

尝试设置您的stringstream的:


编辑:我发现此解决方案将出现与stringchar*,len情况类似的问题。您能告诉我们更多关于缓冲区对象的信息吗?如果您不知道长度,并且它不是以null结尾的,那么将很难处理。

是否可以修改编码长度的方式,并将其设置为固定大小

无符号长尺寸=6;//已知字符串长度 char*buffer=新字符[1+sizeofunsigned long+1+size]; 缓冲区[0]='!'; memcpybuffer+1,&size,sizeofunsigned long

缓冲区应包含起始指示符1字节、无符号长字符的实际大小、分隔符1字节和文本本身大小。 这样,您可以非常容易地获得大小,然后将指针设置为超出开销的点,然后在字符串构造函数中使用len变量。 无符号长透镜; memcpy&len,pData+1,sizeofunsigned long;//+1避免启动指示灯 //len现在包含6个 char*actualData=pData+1+sizeofunsigned long+1; std::字符串sactualData,len;


它的级别较低且容易出错:例如,如果您读取的内容没有按照预期的编码方式进行编码,则len可能会变得相当大,但您可以避免动态读取字符串的长度。

是否可以修改长度编码方式,并将其设置为固定大小

无符号长尺寸=6;//已知字符串长度 char*buffer=新字符[1+sizeofunsigned long+1+size]; 缓冲区[0]='!'; memcpybuffer+1,&size,sizeofunsigned long

缓冲区应包含起始指示符1字节、无符号长字符的实际大小、分隔符1字节和文本本身大小。 这样,您可以非常容易地获得大小,然后将指针设置为超出开销的点,然后在字符串构造函数中使用len变量。 无符号长透镜; memcpy&len,pData+1,sizeofunsigned long;//+1避免启动指示灯 //len现在包含6个 char*actualData=pData+1+sizeofunsigned long+1; std::字符串sactualData,len;


它的级别较低且容易出错:例如,如果您读取的内容没有按照预期的编码方式进行编码,则len可能会变得相当大,但您会避免动态读取字符串的长度。

似乎按照以下顺序进行操作:

std::wstring make_string(char const *input) { 
    if (*input != '!')
       return "";
    char length = *++input;
    return std::wstring(++input, length);
}
困难的部分是处理尺寸的可变长度。如果没有指定长度的内容,很难猜测何时停止将数据视为指定字符串的长度


至于移动指针,如果要在函数内部执行,则需要传递指针的引用,否则只需将找到的指针大小添加到接收到的指针上即可。

似乎按照以下顺序操作:

std::wstring make_string(char const *input) { 
    if (*input != '!')
       return "";
    char length = *++input;
    return std::wstring(++input, length);
}
困难的部分是处理可变长度 大小的第四个。如果没有指定长度的内容,很难猜测何时停止将数据视为指定字符串的长度


至于移动指针,如果要在函数内部执行,则需要传递指针的引用,否则只需将找到的指针大小添加到收到的指针上即可。

很容易滥用已弃用但标准的std::istrstream

// Maximum size to read is 
// 1 for the exclamation mark
// Digits for the character count (digits10() + 1)
// 1 for the space
const std::streamsize max_size = 3 + std::numeric_limits<std::size_t>::digits10;

std::istrstream s(buf, max_size);

if (std::istream::traits_type::to_char_type(s.get()) != '!'){
    throw "missing exclamation";
}

std::size_t size;
s >> size;

if (std::istream::traits_type::to_char_type(s.get()) != ' '){
    throw "missing space";
}

std::wstring(reinterpret_cast<wchar_t*>(s.rdbuf()->str()), size/sizeof(wchar_t));

这里很容易滥用不推荐但标准的std::istrstream:

// Maximum size to read is 
// 1 for the exclamation mark
// Digits for the character count (digits10() + 1)
// 1 for the space
const std::streamsize max_size = 3 + std::numeric_limits<std::size_t>::digits10;

std::istrstream s(buf, max_size);

if (std::istream::traits_type::to_char_type(s.get()) != '!'){
    throw "missing exclamation";
}

std::size_t size;
s >> size;

if (std::istream::traits_type::to_char_type(s.get()) != ' '){
    throw "missing space";
}

std::wstring(reinterpret_cast<wchar_t*>(s.rdbuf()->str()), size/sizeof(wchar_t));

恐怕没有缓冲区“对象”,只有指向内存块的指针。我得到一个指向该内存开头的指针,我需要从中重新创建一个wstring。我真的不能用null终止任何东西,因为null是有效的数据,请参见我的示例。我知道它的大小,因为它被编码在数据中,虽然是一个文本字符串。作为一个人,我可以很容易地解析这些数据,但我正在努力想出一种优雅的方法来用代码来完成它。如果你有什么特别想知道的,就直接问吧。恐怕没有缓冲区“对象”,只有一个指向内存块的指针。我得到一个指向该内存开头的指针,我需要从中重新创建一个wstring。我真的不能用null终止任何东西,因为null是有效的数据,请参见我的示例。我知道它的大小,因为它被编码在数据中,虽然是一个文本字符串。作为一个人,我可以很容易地解析这些数据,但我正在努力想出一种优雅的方法来用代码来完成它。如果你有什么特别想知道的,就直接问吧。很有趣。。。你的意思是,因为我无法预先知道数据的大小,所以我将流设置为其最大大小。是的,我想那会有用的。但是这会带来额外的开销吗?@WalderFrey:istrstream没有自己的缓冲区,也不复制。但是仔细想想,传递max可能不是一个好主意,因为流的实现可能最终使用类似于buf+size的东西来计算其缓冲区的结尾,如果buf是一个大值,则可能会溢出。我将更新答案以使用更安全的缓冲区大小。有趣的是。。。你的意思是,因为我无法预先知道数据的大小,所以我将流设置为其最大大小。是的,我想那会有用的。但是这会带来额外的开销吗?@WalderFrey:istrstream没有自己的缓冲区,也不复制。但是仔细想想,传递max可能不是一个好主意,因为流的实现可能最终使用类似于buf+size的东西来计算其缓冲区的结尾,如果buf是一个大值,则可能会溢出。我将更新答案以使用更安全的缓冲区大小。