7

-edit- 我发送的是二进制而不是字符串。我的测试使用的是 html 页面,所以在这个例子中我只使用了一个字符串,但我的问题是关于二进制、向量和使用 ostream 进行调试。我这样做消除了一些混乱。

我有以下代码:

cout << string(&v[0]).substr(0, len);

有没有更好的方法来打印cout 长度为len的字符串v?我想过做 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();
4

4 回答 4

8

您可以在 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;
}

输出:

美国广播公司

由于 ostream::write 返回一个包含 *this 的 ostream&,你甚至可以这样做

cout.write(&test[0], 3) << endl;

但我不确定这实际上是否更好(或更清晰)。

于 2009-02-15T17:24:52.550 回答
6
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只会保证您可以 push_back 至少那么多元素,直到对向量的引用和迭代器再次失效(通过可能重新分配已用缓冲区)。它不允许您写入 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”(一个),这会让人们感到困惑)

于 2009-02-15T12:54:42.153 回答
0

为什么将大小设置为 1?
当您保留空间时,该空间可用于向量增长(无需重新分配)。但是谁说直接使用就安全了?我已经看到(调试)实现在 size() 修改这些位之后添加一个警告缓冲区,并且它会在下次检查时生成一个断言。您应该只从 0 -> size() 读取/写入。

注意这也将允许您使用 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);
}

请注意,这可能不是读取字符串的最佳方式。
我会通过流传递长度信息,这样你就知道什么时候没有更多信息可以读取,然后只读取所需的信息。

于 2009-02-15T17:22:26.393 回答
-2

见评论: 我的立场是正确的。我被告知了。但是,我仍然认为依靠这样的内部结构是疯狂的。我使用的最后一个 microsoft 编译器违反了 C99 标准,这让我悲痛欲绝。如果他们不能在vsnprinf()new 上获得正确的返回值,你真的要依赖这样的勘误表吗?

您正在对向量的实现方式做出假设。您假设 v[1] 紧跟在内存中的 v[0] 之后。

char buf[];之间有区别 & buf[1] == & buf[0] + 1向量 v; & v[1] == & v[0] + 1。char 数组使用指针算法。向量使用运算符 []。向量如何在内部存储数据,无论是否相邻,都取决于该向量类。

虽然您的代码可能仍然有效,但这仍然是一件坏事!它使您的软件变得脆弱,导致它在您最不期望的时候以奇怪和预期的方式崩溃!

这是本地堆栈上临时 char 数组的理想情况。尺寸很小。您有一个硬编码的最大尺寸。

如果大小不是恒定的,我仍然会在堆栈上使用一个小的本地字符数组缓冲区。我只是在每次迭代后将它附加到 C++ std::string 中。(是的,std::strings 可以存储包含多个空字符的二进制值。)

recv()返回它读取的字节数。Vector 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;
于 2009-02-15T17:02:14.647 回答