Sự khác biệt giữa fprintf, printf và sprintf?


233

Bất cứ ai có thể giải thích tại đơn giản bằng tiếng Anh về sự khác biệt giữa printf, fprintfsprintfvới các ví dụ?

Nó nằm trong luồng nào?

Tôi thực sự bối rối giữa ba điều này trong khi đọc về "Xử lý tệp trong C".


4
Thử nghiệm với họ bằng cách viết một số mã mẫu. Đó là cách rất dễ dàng để rõ ràng hiểu sự khác biệt giữa chúng.
Nawaz

14
Thích snprintf () hơn sprintf () để tránh tràn bộ đệm ngớ ngẩn.
Maxim Egorushkin

3
Thích các luồng hoặc tăng cường trình định dạng để tránh tràn bộ đệm ngớ ngẩn và các lỗi không an toàn loại khó chịu
John Dibling

7
@Maxim, trong khi bạn nêu lên một điểm hợp lệ, tôi sẽ đảm bảo an toàn về kiến ​​thức rằng bộ đệm của tôi sẽ không tràn và làm nổ ứng dụng của tôi thành từng mảnh. Tôi chỉ bao giờ nhìn vào các chức năng này nếu các bộ định dạng luồng / tăng cường được hiển thị là gây ra các tắc nghẽn đáng chú ý. :)
Moo-Juice

1
@Maxim: Điểm là, không cần. Mã của tôi không phải là một nút cổ chai. 5m / giây là số lượng tin nhắn trao đổi gửi, chứ không phải số lượng chúng tôi có khả năng xử lý. Vậy tại sao tối ưu hóa sớm?
John Dibling

Câu trả lời:


238

Trong C, một "luồng" là một sự trừu tượng; từ quan điểm của chương trình, nó chỉ đơn giản là một nhà sản xuất (luồng đầu vào) hoặc người tiêu dùng (luồng đầu ra) của byte. Nó có thể tương ứng với một tệp trên đĩa, với đường ống, đến thiết bị đầu cuối của bạn hoặc với một số thiết bị khác như máy in hoặc tty. Các FILEloại chứa thông tin về các dòng suối. Thông thường, bạn không gây rối FILEtrực tiếp với nội dung của một đối tượng, bạn chỉ cần chuyển một con trỏ tới nó cho các thói quen I / O khác nhau.

Có ba luồng tiêu chuẩn: stdinlà một con trỏ tới luồng đầu vào tiêu chuẩn, stdoutlà một con trỏ tới luồng đầu ra tiêu chuẩn và stderrlà một con trỏ tới luồng đầu ra lỗi tiêu chuẩn. Trong phiên tương tác, cả ba thường đề cập đến bảng điều khiển của bạn, mặc dù bạn có thể chuyển hướng chúng để trỏ đến các tệp hoặc thiết bị khác:

$ myprog < inputfile.dat > output.txt 2> errors.txt

Trong ví dụ này, stdinbây giờ trỏ đến inputfile.dat, stdouttrỏ đến output.txtstderrtrỏ đến errors.txt.

fprintf ghi văn bản được định dạng vào luồng đầu ra mà bạn chỉ định.

printftương đương với việc viết fprintf(stdout, ...)và ghi văn bản có định dạng vào bất cứ nơi nào luồng đầu ra tiêu chuẩn hiện đang trỏ.

sprintfghi văn bản có định dạng vào một mảng char, trái ngược với luồng.


4
"nó chỉ đơn giản là một nhà sản xuất (luồng đầu vào) hoặc người tiêu dùng (luồng đầu ra) của byte." Là những ngược? Nhà sản xuất sẽ không tạo ra (đầu ra) một cái gì đó chứ? Hỏi vì tôi thực sự không biết.
Dave Voyles

6
@DaveVoyles: Đây là từ quan điểm của chương trình của bạn. Một luồng đầu vào tạo ra các byte để chương trình của bạn đọc; một luồng đầu ra tiêu thụ các byte được tạo ra từ chương trình của bạn.
John Bode

153

printfđầu ra cho luồng đầu ra tiêu chuẩn ( stdout)

fprintfđi đến một tập tin xử lý ( FILE*)

sprintfđi đến một bộ đệm bạn đã phân bổ. ( char*)


40

printf ("format", args) được sử dụng để in dữ liệu lên đầu ra tiêu chuẩn thường là màn hình máy tính.

sprintf (char *, "format", args) giống như printf. Thay vào đó, hiển thị chuỗi được định dạng trên đầu ra tiêu chuẩn, tức là một màn hình, nó lưu trữ dữ liệu được định dạng trong một chuỗi được trỏ bởi con trỏ char (tham số đầu tiên). Vị trí chuỗi là sự khác biệt duy nhất giữa printf và cú pháp chạy nước rút.

fprintf (FILE * fp, "format", args) giống như printf một lần nữa. Ở đây thay vì hiển thị dữ liệu trên màn hình hoặc lưu nó trong một số chuỗi, dữ liệu được tạo sẽ được lưu trên một tệp được trỏ bởi con trỏ tệp được sử dụng làm tham số đầu tiên cho fprintf. Con trỏ tệp là sự bổ sung duy nhất cho cú pháp của printf.

Nếu tệp xuất chuẩn được sử dụng làm tham số đầu tiên trong fprintf, thì hoạt động của nó được coi là tương đương với tham số của printf.


24

printf(...)tương đương với fprintf(stdout,...).

fprintf được sử dụng để xuất ra luồng.

sprintf(buffer,...) được sử dụng để định dạng một chuỗi thành một bộ đệm.

Lưu ý là cũng có vsprintf, vfprintfvprintf


Các vhương vị không theo tiêu chuẩn tôi tin
John Dibling

8
Các vhương vị rất chắc chắn trong tiêu chuẩn C.
Fred Foo

@larsmans: à, ok. Cảm ơn vì sự đúng đắn của bạn. Câu hỏi này đã có lúc được gắn thẻ [c ++]
John Dibling

2

Bạn cũng có thể làm những việc rất hữu ích với hàm vsnprintf ():

$ cat test.cc
#include <exception>
#include <stdarg.h>
#include <stdio.h>

struct exception_fmt : std::exception
{
    exception_fmt(char const* fmt, ...) __attribute__ ((format(printf,2,3)));
    char const* what() const throw() { return msg_; }
    char msg_[0x800];
};

exception_fmt::exception_fmt(char const* fmt, ...)
{
    va_list ap;
    va_start(ap, fmt);
    vsnprintf(msg_, sizeof msg_, fmt, ap);
    va_end(ap);
}

int main(int ac, char** av)
{
    throw exception_fmt("%s: bad number of arguments %d", *av, ac);
}

$ g++ -Wall -o test test.cc

$ ./test
terminate called after throwing an instance of 'exception_fmt'
  what():  ./test: bad number of arguments 1
Aborted (core dumped)

+1 thực sự hữu ích, nhưng lưu ý rằng đó vsnprintflà một hàm không chuẩn. Hầu hết các triển khai tôi đã thấy thực hiện điều này hoặc một cái gì đó tương tự, nhưng nó là cụ thể thực hiện.
John Dibling

1
@larsmans đề cập ở trên rằng trên thực tế, đây là một phần của tiêu chuẩn C, vì vậy tôi lấy lại
John Dibling

2
Điều này có liên quan gì đến C?
onemasse

2

in

  1. printf được sử dụng để thực hiện đầu ra trên màn hình.
  2. cú pháp = printf("control string ", argument );
  3. Nó không được liên kết với đầu vào / đầu ra File

fprintf

  1. Fprintf nó được sử dụng để thực hiện thao tác ghi trong tệp được chỉ ra bởi tay cầm FILE.
  2. Cú pháp là fprintf (filename, "control string ", argument );
  3. Nó được liên kết với đầu vào / đầu ra tập tin

Nếu điều này được trích dẫn từ một nơi khác, tốt nhất là trích dẫn nguồn bằng một liên kết, nhưng chắc chắn vẫn giữ văn bản bạn đã trích dẫn ở đây.
SuperBiasedMan

0

fprintfĐiều này có liên quan đến các luồng trong đó printflà một tuyên bố tương tự fprintfnhưng không liên quan đến các luồng, đó là fprintfliên quan đến tệp


0

sprintf: Ghi dữ liệu được định dạng vào chuỗi ký tự trong bộ nhớ thay vì thiết bị xuất chuẩn

Cú pháp của sprintf là:

#include <stdio.h>
int sprintf (char *string, const char *format
[,item [,item]…]);

Đây,

Chuỗi tham chiếu đến con trỏ tới bộ đệm trong bộ nhớ trong đó dữ liệu sẽ được ghi.

Định dạng đề cập đến con trỏ đến một chuỗi ký tự xác định định dạng.

Mỗi mục là một biến hoặc biểu thức chỉ định dữ liệu cần ghi.

Giá trị được trả về bởi sprintf lớn hơn hoặc bằng 0 nếu thao tác thành công hoặc nói cách khác, số ký tự được viết, không tính ký tự null kết thúc được trả về và trả về giá trị nhỏ hơn 0 nếu xảy ra lỗi.

printf: In ra thiết bị xuất chuẩn

Cú pháp cho printf là:

printf format [argument]…

Sự khác biệt duy nhất giữa sprintf () và printf () là sprintf () ghi dữ liệu vào một mảng ký tự, trong khi printf () ghi dữ liệu vào thiết bị xuất chuẩn, thiết bị đầu ra tiêu chuẩn.

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.