2009-02-15 20 views
6

-editar- Estoy enviando código binario y no una cadena. Mi prueba es usar páginas html, así que en este ejemplo solo estoy usando una cadena, pero mi pregunta es acerca de binarios, vectores y depuración con ostream. Lo hago aclara un poco de confusión.¿Existe alguna forma mejor de imprimir una cadena con un máximo de N caracteres?

he el siguiente código:

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

¿Hay una mejor manera de imprimir la cadena v con cout el longitud len ? Pensé en hacer v [len] = 0 pero una afirmación es lanzado con un tamaño de 1. Mi código es:

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

Este código está roto. Horriblemente así. Usar un vector para asignar una matriz (que es lo que esencialmente está sucediendo allí) no solo es peligroso (¡los vectores son SIGNIFICADOS para reasignar sus matrices internas!) Sino también inútiles. –

+0

Al menos use v.resize (1024 * 16) si * debe * usar un vector, pero como lo mencionó dionadar, hacerlo de esta forma no es una buena idea y, básicamente, no lo protege de nada y puede llevar a algunas noches interesantes depurando este código. –

+0

¿Qué hay de malo con su uso del vector? si el tamaño es dinámico, no veo nada malo con él –

Respuesta

7

Usted puede utilizar el método ostream :: escribe en el objeto cout:

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

Salidas:

abc

Desde ostream :: write devuelve un ostream & que contiene * esto, incluso puede hacer

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

pero no estoy seguro de que sea realmente mejor (o más claro).

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

Este código tiene un error. Llamar al reserve solo le garantizará que puede push_back al menos tantos elementos hasta que las referencias e iteradores al vector se invaliden nuevamente (a través de una posible reasignación del búfer utilizado). Va a no le permite escribir en v [0..1024 * 16-1], como lo hace allí con recv. Que tiene que hacer

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

que en realidad tienen que muchos elementos disponibles y, de hecho pasan v.size() en lugar de v.capacity().

Para su funcionamiento subcadena, probablemente hacer

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

donde n va desde 0 hasta v.size(). Puede usar std::min(n, v.size()) para garantizar que, si n podría ser más grande en su caso y necesita un límite superior.

(en un nodo lateral, evitaría tener una variable llamada "l" (ell) allí, porque puede parecerse mucho a un "1" (uno), lo que puede confundir a la gente)

+0

según lo que leí, de hecho puede escribir en elementos 0-1024 * 16-1 y se garantiza que será continuo; sin embargo, los elementos de tamaño a capacidad no se construyen/inicializan. –

+0

no está bien, porque el vector no tiene tantos elementos. solo puede escribir/leer desde hasta v [0..v.size() - 1] por supuesto. –

+0

Por cierto, si necesita un búfer de tamaño constante, es mejor usar boost :: array v; luego pase v.data() y v.size(). o una matriz en la pila, aunque deben evitarse las matrices en bruto ... ya sabes, peligro a la vuelta de la esquina –

-2

Ver comentarios: Me erraron corregido. Estaba mininformado. Sin embargo, todavía creo que es una locura confiar en elementos internos como este. El último compilador de Microsoft que utilicé violó los estándares C99 y me causó un gran dolor. Si no pueden obtener los valores de retorno correctos en vsnprinf() o nuevo, ¿realmente desea confiar en la errata de esta manera?

Usted está haciendo suposiciones con respecto a cómo se implementa el vector. Está asumiendo que v [1] viene justo después de v [0] en la memoria.

Hay una diferencia entre char buf []; & buf [1] == & buf [0] + 1 y vector v; & v [1] == & v [0] + 1. La matriz de caracteres utiliza la aritmética del puntero. El vector usa el operador []. Cómo el vector almacena los datos internamente, si es adyacente o no, depende de esa clase de vector.

Mientras que su código aún puede funcionar, esta sigue siendo una cosa BAD! Hace que su software se vuelva frágil, causando que se rompa de manera extraña y esperada cuando menos lo espera.

Esta es una situación ideal para una matriz de caracteres temporal en la pila local. El tamaño es pequeño Usted tiene un tamaño máximo codificado.

Si el tamaño no fuera constante, igual usaría un pequeño búfer local de matriz de caracteres en la pila. Solo lo agregaría a C++ std :: string después de cada iteración. (Sí, std :: cadenas pueden almacenar valores binarios incluyendo múltiples caracteres nulos.)

recv() devuelve la cantidad de bytes que leyó. Vector v no lo recoge automágicamente. Entonces necesita almacenar y usar ese valor.

sugiero:

#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; 
+0

bien. en realidad, el vector que es contiguo es una de sus características principales. tienes garantizado que & v [1] == & v [0] + 1 es verdadero si el vector contiene al menos 2 elementos. –

+0

no fue así en C++ 98. pero fue arreglado en C++ 03. lea http://herbsutter.wordpress.com/2008/04/07/cringe-not-vectors-are-guaranteed-to-be-contiguous/ –

+0

Estoy parado. Publicación original actualizada. Pero todavía creo que es una locura confiar en elementos internos como este. El último compilador de Microsoft que utilicé violó los estándares C99 y me causó un gran dolor. ¿De verdad quieres confiar en erratas como esta? ¿Especialmente cuando no hay necesidad? –

0

Por qué están estableciendo que el tamaño de 1?
Cuando reserva el espacio, el espacio está disponible para que el vector crezca (sin reasignación). ¿Pero quién dijo que era seguro usarlo directamente? He visto implementaciones (de depuración) que agregan un búfer de advertencia justo después de que size() modifique estos bits y generaría una afirmación la próxima vez que se marque. Solo debe leer/escribir desde 0 -> tamaño().

NB Esto también le permitirá usar 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); 
} 

Tenga en cuenta que probablemente esta no sea la mejor manera de leer una cadena.
Transmitiría la información de la longitud sobre la transmisión para que sepa cuándo no hay más información para leer y solo lea todo lo que se requiera.

+0

Si uso do v.clear(); v.push_back (data) un montón de veces. Tendría que cambiar el tamaño de su capacidad de nuevo? que construiría todos mis caracteres y, en el caso de caracteres, no ctor, pero la inicializa a fillData? eso es molesto, especialmente si escribo/mando muchos 128Bytes y necesito un buf de al menos 16k. ¿Hay alguna manera de ... –

+0

¿Hay alguna forma de redimensionar sin inicializar los datos a fillValue? si no que impl depuración me molestarían en este prj y se pueden depurar imple vs evitando potencialmente una gran cantidad de gastos generales con el cambio de tamaño. también, ostream.write (ptr, len); resuelve mi pregunta –

Cuestiones relacionadas