tags:

views:

402

answers:

5

-edit- I am sending binary and not a string. My test is using html pages so in this example i am only using a string but my question is about binary, vectors and debugging with ostream. I make this clears some confusion.

I have the following code:

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

Is there a better way to print the string v with cout up the length len? I thought of doing v[len] = 0 but I an assertion is thrown with a size of 1. My code is:

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

v[l] is an off by one error. when you receive l characters, then the buffer has been filled from [0..l-1]
The code makes me shiver a bit, I'd have just used a simple char[] buffer. Additionally, I don't know are you expecting wchar_t's over the wire?

Petesh
+5  A: 
vector<char> v;
v.reserve(1024*16); //required
v.resize(1); //so we can do &v[0]
recv(sockfd, &v[0], v.capacity(), 0);

That code has a bug. Calling reserve will only guarantee you that you can push_back at least that many elements until references and iterators to the vector are invalidated again (through a possible reallocation of the used buffer). It will not allow you to write into v[0..1024*16-1], as you do there with recv. You have to do

v.resize(1024*16); //required

to actually have that many elements available and actually pass v.size() instead of v.capacity().

For your substring operation, i would probably do

std::string str(&v[0], n);
std::cout << str;

Where n ranges from 0 up to v.size(). You can use std::min(n, v.size()) to guarantee that, if n could be larger in your case and you need an upper limit.

(on a side node, i would avoid having a variable called "l" (ell) there, because it can look very much like an "1" (one), which can confuse the hell out of people)

Johannes Schaub - litb
from what i read you can in fact write into 0-1024*16-1 elements and it is guaranteed to be continuous, however elements from size to capacity are not constructed/initialized.
acidzombie24
it's not right, because the vector does not have so many elements. you can only write to/ read from up to v[0..v.size()-1] of course.
Johannes Schaub - litb
btw, if you need a constant sized buffer, it's better to use boost::array<char, 1024*16> v; then pass v.data() and v.size() . or an array on the stack - though raw arrays should be avoided... u know, danger around the corner
Johannes Schaub - litb
std::string str(v.begin(), v.begin()+n); would be less hackish.
flodin
A: 
Mr.Ree
Johannes Schaub - litb
it wasn't that way in c++98. but it was fixed in c++03. read http://herbsutter.wordpress.com/2008/04/07/cringe-not-vectors-are-guaranteed-to-be-contiguous/
Johannes Schaub - litb
I stand corrected. Original posting updated. But I still think it's nuts to rely on internals like this. The last microsoft compiler I used violated C99 standards causing me no end of grief. Do you really want to rely on errata like this? Especially when there's no need?
Mr.Ree
When did Microsoft compilers ever claim to support C99?
bk1e
A: 

Why are you setting the size to 1?
When you reserve the space the space is available for the vector to grow into (without reallocating). But who said it was safe to use directly? I have seen (debug) implementations that add a warning buffer just after size() modify these bits and it would generate an assert next time it checked. You should only be reading/writing from 0 -> size().

NB This will then also allow you to use 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);
}

Note this is probably not the best way to read a string.
I would pass length information over the stream so you know when there is not more information to read then read only as much as is required.

Martin York
If i use do v.clear(); v.push_back(data) a bunch of times. I would need to resize it capacity again? which would construct all my chars and in chars case no ctor but initial it to fillData? thats annoying, especially if i write/send many 128bytes and need a buf of at least 16k. Is there a way to...
acidzombie24
is there a way to resize w/o initializing the data to fillValue? if not that debug impl would annoy me in this prj and it be debug imple vs avoiding potentially a lot of overhead with resize. also, ostream.write(ptr, len); solves my question.
acidzombie24
+4  A: 

You can use the method ostream::write on the cout object:

#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;
}

Outputs:

abc

Since ostream::write returns an ostream& containing *this, you can even do

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

but I'm not sure that is actually any better (or clearer).

SCFrench