2013-07-10 38 views
6
#include <stdio.h> 

int main() 
{ 
    printf("%*.*d\n", -6 , 7,20000); 
    printf("%*.*d\n", 5, -6, 2000); 
    return 0; 
} 

Output:% *. * D hoạt động như thế nào trong printf()?

0020000 
2000 

Tôi không hiểu làm thế nào để giải thích các printf format specifier *. *?

Trong khi trong cuộc gọi đầu tiên printf(), hiện sau override cựu -6? Vì vậy, kích thước của chiều rộng đầu ra biến thành 7?

Trả lời

8

Đối số cho các * trước . là chiều rộng lĩnh vực và lập luận cho * sau .chính xác.

Độ rộng trường là số byte tối thiểu sẽ được xuất dưới dạng kết quả của chuyển đổi; đầu ra sẽ được đệm (theo mặc định, ở bên trái có dấu cách, nhưng trái không đệm và đệm không gian bên phải cũng là các tùy chọn, được kiểm soát bởi cờ) nếu ít byte hơn sẽ được tạo ra. Đối số phủ định cho chiều rộng * được hiểu là giá trị dương tương ứng với cờ -, sẽ di chuyển phần đệm sang bên phải (nghĩa là trái minh họa trường này).

Mặt khác, chính xác có ý nghĩa khác nhau theo chuyển đổi đang được thực hiện. Các precisions tiêu cực được xử lý như thể không có độ chính xác nào được xác định. Đối với số nguyên, đó là số lượng tối thiểu là chữ số (không phải tổng sản lượng) được tạo; nếu ít chữ số hơn sẽ được tạo, số 0 sẽ được thêm vào bên trái. Độ chính xác rõ ràng của 0 kết quả không có chữ số nào được tạo khi giá trị bằng 0 (thay vì một đơn 0 được tạo ra). Đối với chuỗi, độ chính xác giới hạn số byte đầu ra, cắt xén chuỗi (và cho phép mảng dài hơn, không null kết thúc, nhập) nếu cần. Đối với các điểm số dấu chấm động, độ chính xác kiểm soát số lượng các địa điểm được in, hoặc sau điểm gốc (đối với %f) hoặc tổng số vị trí có ý nghĩa (đối với các định dạng khác).

Trong ví dụ của bạn:

printf("%*.*d\n", -6 , 7,20000); 

đây lĩnh vực này được canh trái (padding trên bên phải) có chiều rộng tối thiểu là 6, nhưng lĩnh vực này kết thúc lên được rộng hơn anyway, do đó chiều rộng được bỏ qua. Độ chính xác của 7 lực đầu ra số nguyên phải có ít nhất 7 chữ số, vì vậy bạn kết thúc với 0020000 làm nội dung trường được chuyển đổi, đã vượt quá chiều rộng.

Trong một trong những khác:

printf("%*.*d\n", 5, -6, 2000); 

Chiều rộng lĩnh vực là 5, với mặc định sắp xếp đúng; đệm là với không gian bên trái.Độ chính xác âm được bỏ qua, như thể nó không được chỉ định, vì vậy nội dung trường được chuyển đổi là 2000, chỉ 4 byte, được đệm lên đến 5 byte để lấp đầy chiều rộng bằng phương tiện của một không gian chính.

+2

+1, nhưng tôi nghĩ rằng đó phải là "ký tự" hoặc "chữ số" chứ không phải "byte". – unwind

+6

@unwind: Tôi đã sử dụng từ "byte" một cách có chủ ý. Nó không phải là "chữ số" vì chiều rộng đếm những thứ như dấu, điểm radix (cho phao), v.v. đối với tổng số, và trong trường hợp của một miền địa phương nơi điểm gốc là một ký tự nhiều byte, mỗi byte sẽ được tính theo chiều rộng. Lưu ý rằng trong tiêu chuẩn C, "byte" và "ký tự" là tương đương; Tôi tránh sử dụng từ "ký tự" vì nó không rõ ràng đối với hầu hết mọi người, do các ký tự nhiều byte. POSIX đã thay đổi tất cả các tham chiếu thành "ký tự" trong đặc tả cho các hàm này thành "byte" để tránh nhầm lẫn. –

+0

Cảm ơn rất nhiều. Tôi nghĩ rằng tôi đã tìm thấy điểm mấu chốt, đó là độ rộng trường * kiểm soát chiều rộng đầu ra với căn chỉnh mặc định và đệm với các khoảng trống ở bên trái nếu ít byte hơn sẽ được tạo ra và * Precision * kiểm soát số lượng tối thiểu chữ số để xuất. –

3
printf("%*.*d\n", -6 , 7,20000); 

là giống như

printf("%-6.7d\n, 20000); 

này chỉ cung cấp một cách để định dạng động.

0

đây là mã nguồn của printf trong glibc

/* VARARGS1 */ 
int __printf (const char *format, ...) 
{ 
va_list arg; 
int done; 

va_start (arg, format); 
done = vfprintf (stdout, format, arg); 
va_end (arg); 

return done; 

}

như bạn có thể nhìn thấy printf được thông số từ va_list

đây là một ví dụ khác, để chỉ cho bạn cách printf công trình:

/* va_start example */ 
#include <stdio.h>  /* printf */ 
#include <stdarg.h>  /* va_list, va_start, va_arg, va_end */ 

void PrintFloats (int n, ...) 
{ 
    int i; 
    double val; 
    printf ("Printing floats:"); 
    va_list vl; 
    va_start(vl,n); 
    for (i=0;i<n;i++) 
    { 
    val=va_arg(vl,double); 
    printf (" [%.2f]",val); 
    } 
    va_end(vl); 
    printf ("\n"); 
} 

int main() 
{ 
    PrintFloats (3,3.14159,2.71828,1.41421); 
    return 0; 
} 
Các vấn đề liên quan