“%. * S” trong printf có nghĩa là gì?


112

Tôi nhận được một đoạn mã trong đó có

printf("%.*s\n")

những gì hiện các %.*snghĩa là gì?


26
Nếu không có các đối số bổ sung, đó không phải là một printfcuộc gọi hợp lệ .
Andrew Marshall,

Câu trả lời:


119

Bạn có thể sử dụng dấu hoa thị ( *) để chuyển mã định nghĩa / độ chính xác chiều rộng printf(), thay vì mã hóa cứng nó vào chuỗi định dạng, tức là

void f(const char *str, int str_len)
{
  printf("%.*s\n", str_len, str);
}

3
Cần lưu ý rằng str_lenđối số phải có kiểu int(hoặc kiểu tích phân hẹp hơn, sẽ được thăng cấp thành int). Nó sẽ là một lỗi để vượt qua long, size_tvv
MM

9
Điều đáng nói là mục đích có thể xảy ra của mã này, đặc biệt khi được sử dụng với %s, là để in một chuỗi con của chuỗi gốc. Trong trường hợp sử dụng này, strsẽ trỏ đến một nơi nào đó bên trong chuỗi gốc (có thể ở đầu) và str_lensẽ chỉ định độ dài của chuỗi con sẽ được in.
Sonic Atom

2
Bằng cách chỉ định độ dài, chúng ta có thể xử lý việc in (hoặc sprintf) 'trong một chuỗi không có dấu chấm dứt rỗng, ví dụ: một chuỗi được nhập từ bất kỳ nguồn nào dựa trên tệp hoặc luồng. Đây là trường hợp sử dụng mà tôi đã gặp thường xuyên hơn nhiều, chứ không chỉ đơn thuần là các bản in trước.
Conrad B

23

Chi tiết hơn tại đây .

giá trị số nguyên hoặc *chỉ định độ rộng trường tối thiểu. Kết quả được đệm bằng các ký tự khoảng trắng (theo mặc định), nếu được yêu cầu, ở bên trái khi căn phải hoặc ở bên phải nếu căn trái. Trong trường hợp khi * được sử dụng, chiều rộng được chỉ định bởi một đối số bổ sung kiểu int. Nếu giá trị của đối số là âm, nó dẫn đến - cờ được chỉ định và độ rộng trường dương. (Lưu ý: Đây là chiều rộng tối thiểu: Giá trị không bao giờ bị cắt ngắn.)

.theo sau là số nguyên hoặc *, hoặc không chỉ định độ chính xác của chuyển đổi. Trong trường hợp khi * được sử dụng, độ chính xác được chỉ định bởi một đối số bổ sung kiểu int. Nếu giá trị của đối số này là âm, nó sẽ bị bỏ qua. Nếu cả số và * đều không được sử dụng, độ chính xác được coi là 0. Xem bảng dưới đây để biết chính xác ảnh hưởng của độ chính xác.

Vì vậy, nếu chúng tôi thử cả hai đặc điểm kỹ thuật chuyển đổi

#include <stdio.h>

int main() {
    int precision = 8;
    int biggerPrecision = 16;
    const char *greetings = "Hello world";

    printf("|%.8s|\n", greetings);
    printf("|%.*s|\n", precision , greetings);
    printf("|%16s|\n", greetings);
    printf("|%*s|\n", biggerPrecision , greetings);

    return 0;
}

chúng tôi nhận được đầu ra:

|Hello wo|
|Hello wo|
|     Hello world|
|     Hello world|

12

Tôi không nghĩ rằng đoạn mã trên là chính xác nhưng (theo mô tả này của printf()) .*phương tiện

Chiều rộng không được chỉ định trong chuỗi định dạng, nhưng là một đối số giá trị số nguyên bổ sung trước đối số phải được định dạng. '

Vì vậy, đó là một chuỗi có độ rộng có thể truyền được làm đối số.


2
Tôi đã thêm tham chiếu chéo URL để bạn có thể tránh bị buộc tội đạo văn. Tất nhiên, câu trích dẫn chính xác nói rằng "Độ chính xác không phải là…" chứ không phải là " Chiều rộng không phải là ...".
Jonathan Leffler

Như @MattMcNabb đã chỉ ra, mọi tham chiếu đến trang đó phải làm nổi bật rằng “ giá trị số nguyên ” là chính xác int(hoặc một tập hợp con của nó) - không chỉ là bất kỳ giá trị tích phân nào như trực quan hơn size_thoặc bí danh có thể có của nó, chẳng hạn std::string::size_type. Điều này thậm chí còn khó hiểu hơn, có tính đến việc trang được tham chiếu đề cập đến size_tlà một trong các mã định nghĩa loại được hỗ trợ.
Anton Samsonov

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.