2010-09-22 47 views
78

Giả sử bạn có một chuỗi không bị null chấm dứt và bạn biết kích thước chính xác của nó, vậy làm thế nào bạn có thể in chuỗi đó với printf trong C? Tôi nhớ lại một phương pháp như vậy nhưng tôi không thể tìm ra ngay bây giờ ...Sử dụng printf với chuỗi không bị null

+6

Trong bối cảnh 'C', tất cả các chuỗi được null chấm dứt. Mảng char mà không có một null trong chúng không phải là chuỗi ... chúng là mảng char :) – pmg

+3

có thể trùng lặp của [Làm thế nào để in một chuỗi không null-chấm dứt bằng printf?] (Http://stackoverflow.com/ câu hỏi/2137779/cách-do-i-in-a-không-null-chấm dứt-chuỗi-sử dụng-printf) – Justin

+0

https://stackoverflow.com/questions/2239519/is-there-a-way-to-specify -nhưng-nhiều-ký tự-of-a-string-to-print-out-sử dụng-pri –

Trả lời

129

Có một khả năng với printf, nó đi như thế này:

printf("%.*s", stringLength, pointerToString); 

Không cần phải sao chép bất cứ điều gì, không cần phải sửa đổi bản gốc chuỗi hoặc bộ đệm.

+9

Nhưng dù sao nó nguy hiểm, ai đó sẽ một ngày nào đó printf chuỗi này với% s – pmod

+0

Vâng, đó là nó! – whoi

+4

@Pmod: Không nhất thiết nếu bộ đệm không được tiếp xúc với thế giới bên ngoài. Nó cũng rất hữu ích để chỉ in * phần * của một chuỗi (mà có thể là null chấm dứt, tất nhiên). Nếu bạn thực sự muốn thấy điều này trong hành động, hãy xem proxy SIP của OpenSER/Kamailio nơi họ tránh sao chép nội dung do kỹ thuật này rất nhiều (cũng sử dụng sprintf). – DarkDust

1
#include<string.h> 
int main() 
{ 
/*suppose a string str which is not null terminated and n is its length*/ 
int i; 
for(i=0;i<n;i++) 
{ 
printf("%c",str[i]); 
} 
return 0; 
} 

tôi chỉnh sửa mã, heres một cách khác:

#include<stdio.h> 
int main() 
{ 
printf ("%.5s","fahaduddin");/*if 5 is the number of bytes to be printed and fahaduddin is the string.*/ 

return 0; 

} 
+0

Hiệu suất rất kém do nhiều lần đọc byte không cần thiết (đi kèm với một hình phạt hiệu suất nếu byte không nằm trên một địa chỉ liên kết từ trên hầu hết các CPU) và việc phân tích cú pháp định dạng và áp dụng được thực hiện cho mỗi và mọi ký tự. Đừng làm điều đó :-) Xem câu trả lời của tôi cho giải pháp. – DarkDust

+0

Cảm ơn bạn đã đề cập đến –

+0

@DarkDust: chỉ một máy bệnh lý sẽ phạt số lần đọc byte không được căn chỉnh với các ranh giới từ. Bạn có nghĩ đến việc đọc từ không phù hợp với các ranh giới từ không? Hoặc một số crap cổ đại hay cái gì đó? –

5

printf("%.*s", length, string) sẽ không hoạt động.

Điều này có nghĩa là in LÊN TO chiều dài byte HOẶC byte trống, tùy điều kiện nào đến trước. Nếu mảng-of-char không null của bạn chứa các byte null TRƯỚC KHI độ dài, printf sẽ dừng lại trên các giá trị đó và không tiếp tục.

+13

làm thế nào một null có thể xuất hiện trong một mảng không-null kết thúc-of-char? Hãy suy nghĩ về nó ... – pmg

+2

nó sẽ làm việc cho anh ta vì anh ta biết chiều dài chính xác – BlackBear

+4

Và làm thế nào là một câu trả lời cho câu hỏi của OP? – Shahbaz

12

Bạn có thể sử dụng hàm fwrite() để stdout!

fwrite(your_string, sizeof(char), number_of_chars, stdout); 

Bằng cách này, bạn sẽ xuất các ký tự đầu tiên (số được định nghĩa trong biến số_of_chars) thành tệp, trong trường hợp này là stdout (đầu ra chuẩn, màn hình của bạn)!

+0

Rất hữu ích khi bạn muốn kiểm tra một bộ đệm dài chứa các chuỗi và số không! – Elist

19

Dưới đây là giải thích về cách hoạt động của %.*s và vị trí được chỉ định.

Các thông số kỹ thuật chuyển đổi trong một printf mẫu chuỗi có dạng tổng quát:

% [ param-no $] flags width [ . precision ] type conversion 

hoặc

% [ param-no $] flags width . * [ param-no $] type conversion 

Hình thức thứ hai là để có được sự chính xác trong danh sách đối số:

Bạn cũng có thể chỉ định độ chính xác của ‘*’. Điều này có nghĩa là đối số tiếp theo trong danh sách đối số (trước khi giá trị thực tế được in) được sử dụng như độ chính xác. Giá trị phải là một int và bị bỏ qua nếu nó là số âm.

- Output conversion syntax trong cuốn hướng dẫn glibc

Đối %s định dạng chuỗi, độ chính xác có một ý nghĩa đặc biệt:

Một chính xác có thể được xác định để chỉ ra số ký tự tối đa để viết; nếu không các ký tự trong chuỗi lên đến nhưng không bao gồm ký tự null kết thúc được ghi vào luồng đầu ra.

- trong cuốn hướng dẫn glibc

biến thể hữu ích khác:

  • "%*.*s", maxlen, maxlen, val sẽ phải biện minh, chèn khoảng trắng trước;
  • "%-*.*s", maxlen, maxlen, val sẽ căn trái.
+0

Nếu tôi hiểu chính xác, điều sau đây sẽ tạo đầu ra nhưng vẫn ngăn chặn tình trạng tràn chuỗi? '"% - *. * S ", đệm, str_view.size(), str_view.data()' – scx

1
printf("%.5s", pointerToNonNullTerminatedString); 

Chiều dài chuỗi sẽ 5.

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