有没有更好的方法来打印cout最多N个字符的字符串?

时间:2009-02-15 12:19:25

标签: c++ vector

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

4 个答案:

答案 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;