2009-02-15 35 views
6

-edit- Tôi đang gửi nhị phân chứ không phải chuỗi. Thử nghiệm của tôi là sử dụng các trang html vì vậy trong ví dụ này tôi chỉ sử dụng một chuỗi nhưng câu hỏi của tôi là về nhị phân, vectơ và gỡ lỗi với ostream. Tôi làm điều này rõ ràng một số nhầm lẫn.Có cách nào tốt hơn để in chuỗi có cout tối đa N ký tự không?

Tôi đã đoạn mã sau:

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

Có cách nào tốt hơn để in ra chuỗi v với cout lên độ dài len? Tôi nghĩ làm v [len] = 0 nhưng tôi khẳng định một được ném với một kích thước của 1. Mã của tôi là:

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

Mã này bị hỏng. Thật kinh khủng như vậy. Sử dụng một vector để phân bổ một mảng (đó là những gì cơ bản đang xảy ra ở đó) không chỉ nguy hiểm (các vector là MEANT để tái phân bổ mảng nội bộ của chúng!) Mà còn vô nghĩa. –

+0

Ít nhất sử dụng v.resize (1024 * 16) nếu bạn * phải * sử dụng một véc tơ, nhưng như đã đề cập bởi dionadar, làm theo cách này không phải là một ý tưởng hay và về cơ bản không bảo vệ bạn khỏi bất cứ điều gì và có thể dẫn đến một số đêm thú vị gỡ lỗi mã này. –

+0

có vấn đề gì với việc sử dụng véc tơ của anh ta? nếu kích thước là động, tôi không thấy bất cứ điều gì xấu với nó –

Trả lời

7

Bạn có thể sử dụng phương pháp ostream :: viết trên đối tượng 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; 
} 

Đầu ra:

abc

Kể từ ostream :: write trả về một ostream & chứa * điều này, bạn thậm chí có thể làm

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

nhưng tôi không chắc chắn rằng thực sự là tốt hơn (hoặc rõ ràng hơn).

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

Đó là mã có lỗi. Gọi reserve sẽ chỉ đảm bảo với bạn rằng bạn có thể push_back ít nhất là nhiều phần tử cho đến khi các tham chiếu và các vòng lặp tới vectơ bị vô hiệu hóa một lần nữa (thông qua khả năng tái phân bổ bộ đệm đã sử dụng). Nó sẽ không phải cho phép bạn viết vào v [0..1024 * 16-1], giống như bạn làm với recv. Bạn phải làm

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

để thực sự có nhiều yếu tố có sẵn và thực sự vượt qua v.size() thay vì v.capacity().

Đối với hoạt động chuỗi con của bạn, tôi có lẽ sẽ làm

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

đâu n dao động từ 0 đến v.size(). Bạn có thể sử dụng std::min(n, v.size()) để đảm bảo rằng, nếu n có thể lớn hơn trong trường hợp của bạn và bạn cần một giới hạn trên.

(trên nút bên, tôi sẽ tránh có biến "l" (ell) ở đó, vì nó có thể trông rất giống "1" (một), có thể gây nhầm lẫn cho mọi người)

+0

từ những gì tôi đọc bạn thực tế có thể viết thành các phần tử 0-1024 * 16-1 và nó được đảm bảo là liên tục, tuy nhiên các thành phần từ kích thước đến dung lượng không được xây dựng/khởi tạo. –

+0

không đúng, vì vectơ không có nhiều yếu tố. bạn chỉ có thể viết/đọc từ lên đến v [0..v.size() - 1] tất nhiên. –

+0

btw, nếu bạn cần một bộ đệm có kích thước không đổi, tốt hơn là sử dụng boost :: array v; sau đó chuyển v.data() và v.size(). hoặc một mảng trên stack - mặc dù mảng thô nên tránh ... u biết, nguy hiểm xung quanh góc –

-2

Xem nhận xét: Tôi đã sửa. Tôi đã được biên soạn. Tuy nhiên, tôi vẫn nghĩ rằng nó là hạt để dựa vào internals như thế này. Trình biên dịch microsoft cuối cùng mà tôi đã sử dụng đã vi phạm các tiêu chuẩn C99 khiến tôi không còn đau buồn nữa. Nếu họ không thể nhận được giá trị trả lại ngay trên vsnprinf() hoặc mới, bạn có thực sự muốn dựa vào errata như thế này không?

Bạn đang đưa ra các giả định về cách thực hiện vectơ. Bạn giả định rằng v [1] xuất hiện ngay sau khi v [0] trong bộ nhớ.

Có sự khác biệt giữa char buf []; & buf [1] == & buf [0] + 1vectơ v; & v [1] == & v [0] + 1. Mảng char sử dụng số học con trỏ. Vector sử dụng toán tử []. Cách vector lưu trữ dữ liệu trong nội bộ, cho dù đó là liền kề hay không, là tùy thuộc vào lớp vectơ đó.

Mặc dù mã của bạn vẫn có thể hoạt động, đây vẫn là một điều là BAD! Nó làm cho phần mềm của bạn trở nên giòn, khiến nó vỡ ra theo những cách kỳ lạ và mong đợi khi bạn ít mong đợi nó nhất!

Đây là một tình huống lý tưởng cho một mảng char tạm thời trên ngăn xếp cục bộ. Kích thước nhỏ. Bạn có kích thước tối đa được mã hóa cứng.

Nếu kích thước không đổi, tôi vẫn sử dụng bộ đệm mảng cục bộ nhỏ trên ngăn xếp. Tôi chỉ cần thêm nó vào một C++ std :: string sau mỗi lần lặp. (Có, std :: chuỗi có thể lưu trữ các giá trị nhị phân bao gồm nhiều ký tự null.)

recv() trả về số byte đọc. Vector v không tự động chọn tùy chọn này. Vì vậy, bạn cần lưu trữ và sử dụng giá trị đó.

Tôi đề nghị:

#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

. thực sự là vector tiếp giáp là một trong những tính năng chính của nó. bạn được đảm bảo rằng & v [1] == & v [0] + 1 là true nếu vectơ chứa ít nhất 2 phần tử. –

+0

không phải như vậy trong C++ 98. nhưng nó đã được sửa trong C++ 03. đọc http://herbsutter.wordpress.com/2008/04/07/cringe-not-vectors-are-guaranteed-to-be-contiguous/ –

+0

Tôi đã sửa chữa. Đã cập nhật bài đăng gốc. Nhưng tôi vẫn nghĩ rằng đó là loại hạt để dựa vào nội tạng như thế này. Trình biên dịch microsoft cuối cùng mà tôi đã sử dụng đã vi phạm các tiêu chuẩn C99 khiến tôi không còn đau buồn nữa. Bạn có thực sự muốn dựa vào errata như thế này không? Đặc biệt là khi không cần? –

0

Tại sao các bạn thiết lập kích thước tới 1?
Khi bạn đặt trước dung lượng, khoảng trống có sẵn để vectơ phát triển thành (không cần tái phân bổ). Nhưng ai nói nó an toàn để sử dụng trực tiếp? Tôi đã thấy (gỡ lỗi) triển khai thêm một bộ đệm cảnh báo ngay sau khi kích thước() sửa đổi các bit này và nó sẽ tạo ra một xác nhận thời gian tới nó được kiểm tra. Bạn chỉ nên đọc/ghi từ 0 -> size().

NB Điều này sau đó sẽ cho phép bạn sử dụng 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); 
} 

Lưu ý đây có lẽ không phải là cách tốt nhất để đọc chuỗi.
Tôi sẽ chuyển thông tin chiều dài qua luồng để bạn biết khi nào không có thêm thông tin để đọc thì chỉ đọc nhiều nhất là bắt buộc.

+0

Nếu tôi sử dụng v.clear(); v.push_back (dữ liệu) một loạt các lần. Tôi sẽ cần phải thay đổi kích thước dung lượng của nó một lần nữa? mà sẽ xây dựng tất cả các ký tự của tôi và trong ký tự trường hợp không có ctor nhưng ban đầu nó để điềnData? thats gây phiền nhiễu, đặc biệt là nếu tôi viết/gửi nhiều 128bytes và cần một buf ít nhất 16k. Có cách nào để ... –

+0

có cách nào để thay đổi kích cỡ w/o khởi tạo dữ liệu để fillValue không? nếu không phải là debug impl sẽ làm phiền tôi trong prj này và nó được gỡ lỗi imple vs tránh có khả năng rất nhiều trên không với thay đổi kích cỡ. cũng, ostream.write (ptr, len); giải quyết câu hỏi của tôi. –

Các vấn đề liên quan