2011-11-17 30 views
15

Tôi có một bộ đệm mà tôi nhận được thông qua một cổng nối tiếp. Khi tôi nhận được một caracter nhất định, tôi biết một dòng đầy đủ đã đến, và tôi muốn in nó với phương pháp printf. Nhưng mỗi dòng có một giá trị độ dài khác nhau, và khi tôi chỉ đi với:Printf một bộ đệm của char đi qua chiều dài trong C

printf("%s", buffer); 

Tôi đang in dòng cộng thêm ký tự thuộc dòng cũ (nếu nó dài hơn dòng cũ).

Tôi đọc here rằng có thể, ít nhất là trong C++, để biết số lượng ký tự bạn muốn đọc là %s, nhưng không có ví dụ và tôi không biết cách thực hiện trong C. ?

EDIT: Hoàn hảo. Vì vậy, tôi có ba giải pháp: - in char bởi char với một for loop - sử dụng các ký tự kết thúc - hoặc sử dụng *

CÂU HỎI LÀ:. Cái nào nhanh hơn? Bởi vì tôi đang làm việc trên một vi mạch PIC và tôi muốn nó xảy ra càng nhanh càng tốt

+2

Khi bạn đã nhận rằng * "nhân vật nào đó" * và đã gắn nó cho 'buffer', nối thêm một ký tự null (' \ 0') là tốt. Điều này "cho biết" 'sprintf()' khi dừng các ký tự in. –

Trả lời

22

Chuỗi bạn có không bị hủy, do đó, printf (và bất kỳ chức năng chuỗi C khác) không thể xác định độ dài của nó, do đó nó sẽ tiếp tục viết các ký tự nó tìm thấy ở đó cho đến khi nó xảy ra khi một ký tự rỗng xảy ra ở đó.

Để giải quyết vấn đề của bạn, bạn có thể:

  • sử dụng fwrite qua stdout:

    fwrite(buffer, buffer_length, 1, stdout); 
    

    này hoạt động vì fwrite không nghĩ cho in ấn chỉ là chuỗi, nhưng bất kỳ loại dữ liệu, do nó không tìm kiếm một ký tự null kết thúc, nhưng chấp nhận độ dài của dữ liệu được viết dưới dạng tham số;

  • null-chấm dứt đệm của bạn bằng tay trước khi in:

    buffer[buffer_length]=0; 
    printf("%s", buffer); /* or, slightly more efficient: fputs(buffer, stdout); */ 
    

    Đây có thể là một ý tưởng tốt hơn nếu bạn phải làm bất cứ xử lý chuỗi khác trên buffer, mà bây giờ sẽ được null-chấm dứt và để dễ quản lý bởi các hàm xử lý chuỗi C bình thường.

+0

Tôi ngạc nhiên rằng câu trả lời cho các bản sao của câu hỏi SO này không bao gồm phương pháp này, nhưng chỉ gợi ý các vòng lặp 'for' ... – Alex

1

Một khi bạn đã xác định được cuối dòng, bạn phải nối thêm một nhân vật '\0' đến cuối của bộ đệm trước khi gửi nó cho printf.

+0

Bất cứ ai đã downvoted muốn giải thích lý do tại sao tôi có thể cải thiện câu trả lời của mình? –

+0

Bạn nên nói những gì OP đã làm sai, ngoài cách sửa nó. – Alex

37

Bạn có thể thêm một ký tự null sau ký tự kết thúc của bạn, và printf của bạn sẽ làm việc, hoặc bạn có thể thêm một '.*' trong bản Tuyên Bố printf bạn và cung cấp độ dài

printf("%.*s",len,buf); 

Trong C++ bạn có lẽ sẽ sử dụng std :: string và std :: cout thay vào đó, như thế này:

std::cout << std::string(buf,len); 

Nếu tất cả các bạn muốn là tốc độ nhanh nhất và không có định dạng - sau đó sử dụng

fwrite(buf,1,len,stdout); 
+0

đẹp, không biết điều này – Ben

+0

Hoàn hảo. Vì vậy, tôi có ba giải pháp: in char bằng char với vòng lặp for, sử dụng ký tự chấm dứt hoặc sử dụng. * CÂU HỎI THƯỜNG GẶP: cái nào nhanh hơn? Bởi vì tôi đang làm việc trên một vi mạch PIC và tôi muốn nó xảy ra nhanh chóng –

+0

@RomanRdgz: đoán của tôi: 'fwrite' hoặc null-chấm dứt +' fputs' nên là nhanh nhất, theo sau là null chấm dứt + 'printf' (có thể chậm hơn bởi vì nó có thể phải phân tích chuỗi định dạng, trừ khi trình biên dịch rất thông minh), sau đó 'printf' bằng'. * '(chắc chắn cần phải phân tích chuỗi định dạng) và lần in cuối cùng bằng char (có thể là chậm nhất, vì tất cả các cuộc gọi chức năng - tuy nhiên có thể được gạch chân). –

3

Bạn có thể đặt một NUL (0x0) trong bộ đệm sau khi nhận được ký tự cuối cùng.

buffer[i] = 0;

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