ความแตกต่างระหว่าง fprintf, printf และ sprintf หรือไม่


233

ทุกคนสามารถอธิบายในภาษาอังกฤษง่าย ๆ เกี่ยวกับความแตกต่างระหว่างprintf, fprintfและsprintfมีตัวอย่าง?

กระแสข้อมูลคืออะไร

ฉันสับสนระหว่างสามสิ่งนี้ในขณะที่อ่านเกี่ยวกับ "การจัดการไฟล์ใน C"


4
ทดลองกับพวกเขาโดยเขียนโค้ดตัวอย่าง นั่นเป็นวิธีที่ง่ายมากที่จะเข้าใจความแตกต่างระหว่างพวกเขาอย่างชัดเจน
นาวาซ

14
ต้องการ snprintf () ถึง sprintf () เพื่อหลีกเลี่ยงบัฟเฟอร์ล้นที่ไม่ได้รับอนุญาต
Maxim Egorushkin

3
ชอบกระแสข้อมูลหรือเพิ่มตัวฟอร์แมตเตอร์เพื่อหลีกเลี่ยงบัฟเฟอร์ล้นอย่างล้นหลามและข้อผิดพลาดประเภทความไม่ปลอดภัยที่น่ารังเกียจ
John Dibling

7
@ Maxim ในขณะที่คุณเพิ่มจุดที่ถูกต้องฉันจะใช้ความปลอดภัยในความรู้ที่บัฟเฟอร์ของฉันจะไม่ล้นและระเบิดแอปของฉันเป็นชิ้น ๆ ฉันเคยดูที่ฟังก์ชั่นเหล่านี้หากสตรีม / ตัวเพิ่มฟอร์แมตเตอร์แสดงว่าเป็นสาเหตุของปัญหาคอขวด :)
Moo-Juice

1
@ Maxim: จุดคือไม่จำเป็นต้องมี รหัสของฉันไม่ใช่คอขวด 5m / วินาทีคือจำนวนข้อความที่แลกเปลี่ยนส่งไม่ใช่จำนวนที่เราสามารถดำเนินการได้ เหตุใดจึงต้องปรับให้เหมาะสมก่อนกำหนด
John Dibling

คำตอบ:


237

ใน C หมายถึง "กระแส" เป็นนามธรรม จากมุมมองของโปรแกรมมันเป็นเพียงผู้ผลิต (อินพุตสตรีม) หรือผู้บริโภค (เอาต์พุตสตรีม) ของไบต์ สามารถตรงกับไฟล์บนดิสก์ไปป์ไปยังเทอร์มินัลของคุณหรือกับอุปกรณ์อื่นเช่นเครื่องพิมพ์หรือ tty FILEประเภทมีข้อมูลเกี่ยวกับกระแส โดยปกติแล้วคุณจะไม่ยุ่งกับFILEเนื้อหาของวัตถุโดยตรงคุณเพียงส่งตัวชี้ไปยังรูทีน I / O ที่หลากหลาย

มีสามสตรีมมาตรฐานstdinคือตัวชี้ไปยังสตรีมอินพุตมาตรฐานstdoutเป็นตัวชี้ไปยังสตรีมเอาต์พุตมาตรฐานและstderrเป็นตัวชี้ไปยังสตรีมเอาต์พุตข้อผิดพลาดมาตรฐาน ในเซสชันแบบโต้ตอบทั้งสามคนมักจะอ้างถึงคอนโซลของคุณแม้ว่าคุณจะสามารถเปลี่ยนเส้นทางให้ชี้ไปที่ไฟล์หรืออุปกรณ์อื่น ๆ ได้:

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

ในตัวอย่างนี้stdinในขณะนี้ชี้ไปinputfile.dat, stdoutคะแนนไปoutput.txtและจุดที่จะต้อง stderrerrors.txt

fprintf เขียนข้อความที่จัดรูปแบบลงในเอาต์พุตสตรีมที่คุณระบุ

printfเทียบเท่ากับการเขียนfprintf(stdout, ...)และเขียนข้อความที่จัดรูปแบบไปทุกที่ที่กระแสข้อมูลขาออกมาตรฐานชี้ไปในขณะนี้

sprintfเขียนข้อความที่จัดรูปแบบลงในอาร์เรย์charซึ่งตรงข้ามกับสตรีม


4
"เป็นเพียงผู้ผลิต (อินพุตสตรีม) หรือผู้บริโภค (สตรีมเอาต์พุต) ไบต์" ข้างหลังนี้ไหม โปรดิวเซอร์จะไม่สร้างบางสิ่ง (เอาท์พุท) ใช่ไหม ถามเพราะฉันไม่รู้จริงๆ
Dave Voyles

6
@DaveVoyles: สิ่งเหล่านี้มาจากมุมมองของโปรแกรมของคุณ สตรีมอินพุตสร้างไบต์เพื่อให้โปรแกรมของคุณอ่าน สตรีมเอาต์พุตจะใช้ไบต์ที่สร้างจากโปรแกรมของคุณ
John Bode


39

printf ("format", args) ใช้เพื่อพิมพ์ข้อมูลลงในเอาต์พุตมาตรฐานซึ่งมักจะเป็นจอคอมพิวเตอร์

sprintf (อักขระ *, "รูปแบบ", args) เหมือนกับ printf แทนที่จะแสดงสตริงที่จัดรูปแบบบนเอาต์พุตมาตรฐานเช่นมอนิเตอร์มันเก็บข้อมูลที่จัดรูปแบบไว้ในสตริงที่ชี้โดยตัวชี้ถ่าน (พารามิเตอร์ตัวแรก) แทน ตำแหน่งสตริงเป็นความแตกต่างเพียงอย่างเดียวระหว่างไวยากรณ์ printf และ sprint

fprintf (FILE * fp, "format", args) ก็เหมือน printf อีกครั้ง ที่นี่แทนการแสดงข้อมูลบนจอภาพหรือบันทึกในสตริงบางส่วนข้อมูลที่จัดรูปแบบจะถูกบันทึกไว้ในไฟล์ที่ชี้โดยตัวชี้ไฟล์ซึ่งใช้เป็นพารามิเตอร์แรกของ fprintf ตัวชี้ไฟล์เป็นส่วนเพิ่มเติมเฉพาะกับไวยากรณ์ของ printf

หากใช้ไฟล์stdoutเป็นพารามิเตอร์ตัวแรกใน fprintf การทำงานนั้นจะถือว่าเทียบเท่ากับของ printf


24

printf(...)fprintf(stdout,...)เทียบเท่ากับ

fprintf จะใช้ในการส่งออกไปยังกระแส

sprintf(buffer,...) ใช้เพื่อจัดรูปแบบสตริงไปยังบัฟเฟอร์

หมายเหตุนอกจากนี้ยังมีvsprintf, vfprintfและvprintf


vรสชาติที่ไม่ได้มาตรฐานผมเชื่อ
จอห์น Dibling

8
vรสชาติที่มีความแน่นอนในมาตรฐานซี
Fred Foo

@larsmans: อ่าโอเค ขอบคุณสำหรับการแก้ไข คำถามนี้อยู่ที่จุดหนึ่งติดแท็ก [c ++]
John Dibling

2

คุณยังสามารถทำสิ่งที่มีประโยชน์มากด้วยฟังก์ชั่น 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 มีประโยชน์แน่นอน แต่ระวังว่าvsnprintfเป็นฟังก์ชั่นที่ไม่ได้มาตรฐาน การใช้งานส่วนใหญ่ที่ฉันเคยเห็นการใช้งานนี้หรือสิ่งที่ชอบ แต่ก็เฉพาะการใช้งาน
John Dibling

1
@larsmans กล่าวไว้ข้างต้นว่านี่คือความจริงแล้วเป็นส่วนหนึ่งของมาตรฐาน C ดังนั้นฉันจึงนำมันกลับมา
John Dibling

2
สิ่งนี้เกี่ยวข้องกับ C หรือไม่?
onemasse

2

printf

  1. printf ใช้สำหรับแสดงผลบนหน้าจอ
  2. วากยสัมพันธ์ = printf("control string ", argument );
  3. ไม่เกี่ยวข้องกับไฟล์อินพุต / เอาท์พุต

fprintf

  1. fprintf ที่ใช้เพื่อดำเนินการเขียนในไฟล์ที่ชี้ไปตามจุดจับ FILE
  2. ไวยากรณ์คือ fprintf (filename, "control string ", argument );
  3. มันเกี่ยวข้องกับไฟล์อินพุต / เอาต์พุต

หากมีการอ้างอิงจากที่อื่นการอ้างอิงแหล่งที่มาพร้อมกับลิงก์นั้นเป็นสิ่งที่ดีที่สุด แต่ยังคงรักษาข้อความที่คุณยกมาไว้ที่นี่
SuperBiasedMan

0

fprintfสิ่งนี้เกี่ยวข้องกับสตรีมโดยที่เป็นprintfคำสั่งที่คล้ายกับfprintfแต่ไม่เกี่ยวข้องกับสตรีมนั่นfprintfคือไฟล์ที่เกี่ยวข้อง


0

sprintf: เขียนข้อมูลที่จัดรูปแบบลงในสตริงอักขระในหน่วยความจำแทน stdout

ไวยากรณ์ของ sprintf คือ:

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

ที่นี่

String หมายถึงตัวชี้ไปยังบัฟเฟอร์ในหน่วยความจำที่จะทำการเขียนข้อมูล

Format หมายถึงตัวชี้ไปยังสตริงอักขระที่กำหนดรูปแบบ

แต่ละรายการเป็นตัวแปรหรือนิพจน์ที่ระบุข้อมูลที่จะเขียน

ค่าที่ส่งคืนโดย sprintf มีค่ามากกว่าหรือเท่ากับศูนย์หากการดำเนินการสำเร็จหรือกล่าวอีกนัยหนึ่งว่าจำนวนอักขระที่เขียนไม่นับการสิ้นสุดอักขระ null ที่ถูกยกเลิกและส่งคืนค่าน้อยกว่าศูนย์หากเกิดข้อผิดพลาด

printf: พิมพ์ไปยัง stdout

ไวยากรณ์สำหรับ printf คือ:

printf format [argument]…

ข้อแตกต่างระหว่าง sprintf () และ printf () คือ sprintf () เขียนข้อมูลลงในอาร์เรย์อักขระขณะที่ printf () เขียนข้อมูลไปยัง stdout ซึ่งเป็นอุปกรณ์เอาต์พุตมาตรฐาน

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.