-edit-我发送的是二进制而不是字符串。我的测试是使用html页面所以在这个例子中我只使用一个字符串,但我的问题是关于二进制,向量和使用ostream进行调试。我这让清除了一些混乱。
我有以下代码:
cout << string(&v[0]).substr(0, len);
有没有更好的方法来打印字符串 v cout的长度为 len ?我想做v [len] = 0但是我的断言被抛出,大小为1.我的代码是:
vector<char> v;
v.reserve(1024*16); //required
v.resize(1); //so we can do &v[0]
recv(sockfd, &v[0], v.capacity(), 0);
while (l > 0)
{
cout << string(&v[0]).substr(0, l);
recv(sockfd, &v[0], v.capacity(), 0);
}
cout << "the size is " << v.size();
答案 0 :(得分:7)
您可以在cout对象上使用ostream :: write方法:
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<char> test;
test.push_back('a');
test.push_back('b');
test.push_back('c');
cout.write(&test[0], 3);
cout << endl;
}
输出:
ABC
因为ostream :: write返回一个ostream&amp;含*这个,你甚至可以做
cout.write(&test[0], 3) << endl;
但我不确定这实际上是否更好(或更清晰)。
答案 1 :(得分:5)
vector<char> v;
v.reserve(1024*16); //required
v.resize(1); //so we can do &v[0]
recv(sockfd, &v[0], v.capacity(), 0);
该代码有错误。调用reserve
只能保证你可以推送至少那么多元素,直到向量的引用和迭代器再次失效(通过可能重新分配使用的缓冲区)。它将不允许您写入v [0..1024 * 16-1],就像使用recv
一样。你必须这样做
v.resize(1024*16); //required
实际上有许多元素可用并实际传递v.size()
而不是v.capacity()
。
对于你的子串操作,我可能会做
std::string str(&v[0], n);
std::cout << str;
其中n的范围从0到v.size()。您可以使用std::min(n, v.size())
来保证,如果您的情况下n可能更大,并且您需要一个上限。
(在一个侧节点上,我会避免在那里有一个名为“l”(ell)的变量,因为它看起来非常像一个“1”(一个),这可能会混淆人们的地狱)
答案 2 :(得分:0)
为什么要将大小设置为1?
当您保留空间时,该空间可用于向量生长(无需重新分配)。但谁说直接使用是安全的?我已经看到(调试)实现,在size()修改这些位之后添加一个警告缓冲区,它会在下次检查时生成一个断言。你应该只从0开始读/写 - >尺寸()。
注意,这将允许您使用v [len] ='\ 0';
vector<char> v(1024*16);
std::size_t len = recv(sockfd, &v[0], v.size(), 0);
while (len > 0)
{
v[len] = '\0';
cout << &v[0];
len = recv(sockfd, &v[0], v.size(), 0);
}
请注意,这可能不是读取字符串的最佳方式 我会通过流传递长度信息,以便您知道何时没有更多信息可供阅读,然后只需要阅读。
答案 3 :(得分:-2)
见评论:我的观点已得到纠正。我被小心翼翼。但是,我仍然认为依靠这样的内部结构是很难的。我使用的最后一个微软编译器违反了C99标准,导致我没有悲伤的结局。如果他们无法在 vsnprinf()或 new上获得返回值,你真的想依赖这样的勘误吗?
您正在假设向量的实现方式。你假设v [1]在内存中的v [0]之后出现。
char buf []之间存在差异; &安培; buf [1] ==&amp; buf [0] + 1 和向量v; &安培; v [1] ==&amp; v [0] + 1 。 char数组使用指针算法。向量使用operator []。向量如何在内部存储数据,无论它是否相邻,都取决于该向量类。
虽然您的代码可能仍然有用,但这仍然是 BAD 的事情!它会让你的软件变得脆弱,导致它在你最不期望的时候以奇怪和预期的方式破解!
这是本地堆栈上临时char数组的理想情况。尺寸很小。你有一个硬编码的最大尺寸。
如果大小不是常量,我仍然会在堆栈上使用一个小的本地char数组缓冲区。我只是在每次迭代后将它附加到C ++ std :: string。 (是的,std :: strings可以存储二进制值,包括多个空字符。)
recv()返回它读取的字节数。矢量 v 不会自动选择它。所以你需要存储和使用该值。
我建议:
#define BUFFER_SIZE (1024*16)
#define FLAGS 0
int received = 0;
int total = 0;
char buffer [ BUFFER_SIZE + 1 ];
memset( buffer, 0, BUFFER_SIZE + 1 );
received = recv( sockfd, buffer, BUFFER_SIZE, FLAGS );
if ( received > 0 )
{
copy( buffer + total,
buffer + total + received,
ostream_iterator<char>(cout) );
total += received;
}
while( (received > 0) && (total < BUFFER_SIZE) )
{
received = recv( sockfd, buffer + total, BUFFER_SIZE - total, FLAGS );
if ( received > 0 )
{
copy( buffer + total,
buffer + total + received,
ostream_iterator<char>(cout) );
total += received;
}
}
buffer [ total ] = '\0';
buffer [ BUFFER_SIZE ] = '\0';
cout << "The total size is " << total << endl;