Різниця між fprintf, printf та sprintf?


233

Може хто - небудь пояснити на простому англійською мовою про відмінності між printf, fprintfі sprintfз прикладами?

У якому потоці він знаходиться?

Я дуже заплутався між трьома з них, читаючи про "Обробку файлів на С".


4
Експериментуйте з ними, написавши якийсь зразок коду. Це дуже простий спосіб чітко зрозуміти різницю між ними.
Наваз

14
Віддайте перевагу snprintf () до sprintf (), щоб уникнути дурних переливів буфера.
Максим Єгорушкін

3
Віддайте перевагу потокам або форматникам Boost, щоб уникнути нерозумних переповнень буфера та неприємних помилок щодо типу
John Dibling

7
@Maxim, в той час як ви піднімете дійсну точку, я візьмусь за безпеку, знаючи, що мої буфери не переповнюватимуться і не розриватимуть додаток на частини. Я б коли-небудь дивився на ці функції, тільки якщо було показано, що формати потоків / прискорення викликають помітні вузькі місця. :)
Moo-Juice

1
@Maxim: Справа в тому, що немає потреби. Мій код не є вузьким місцем. 5 м / сек - це кількість повідомлень, які надсилає обмін, а не скільки ми здатні обробити. Так чому передчасно оптимізувати?
Джон Дайблінг

Відповіді:


237

У С "потік" - це абстракція; з точки зору програми, це просто виробник (вхідний потік) або споживач (вихідний потік) байтів. Це може відповідати файлу на диску, трубі, терміналу або іншому пристрою, наприклад принтеру або tty. FILEТипу містить інформацію про потік. Зазвичай ви не псуєтесь із FILEвмістом об'єкта безпосередньо, просто передаєте вказівник на нього до різних підпрограм вводу / виводу.

Існує три стандартних потоки: stdinвказівник на стандартний вхідний потік, stdoutвказівник на стандартний вихідний потік і stderrвказівник на вихідний потік помилок. В інтерактивному сеансі три зазвичай посилаються на вашу консоль, хоча ви можете перенаправити їх, щоб вказати на інші файли чи пристрої:

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

У цьому прикладі stdinзараз вказується inputfile.dat, stdoutвказується output.txtі stderrвказується на errors.txt.

fprintf записує відформатований текст у вихідний потік, який ви вказуєте.

printfеквівалентно запису fprintf(stdout, ...)та запису відформатованого тексту туди, куди в даний момент вказується стандартний вихідний потік.

sprintfзаписує відформатований текст у масив char, на відміну від потоку.


4
"це просто виробник (вхідний потік) або споживач (вихідний потік) байтів." Це назад? Невже виробник не створить (випустить) щось? Прошу, бо я справді не знаю.
Дейв Войлес

6
@DaveVoyles: це з точки зору вашої програми. Потік введення виробляє байти для вашої програми для читання; вихідний потік споживає байти, вироблені з вашої програми.
Джон Боде

153

printfвиходи в стандартний вихідний потік ( stdout)

fprintfпереходить до файлової ручки ( FILE*)

sprintfпереходить до виділеного вами буфера. ( char*)


39

printf ("формат", аргументи) використовується для друку даних на стандартний вихід, який часто є монітором комп'ютера.

sprintf (char *, "format", args) - це як printf. Замість того, щоб відображати відформатований рядок на стандартному виході, тобто на моніторі, він зберігає відформатовані дані у рядку, на який вказує покажчик char (найперший параметр). Розташування рядка є єдиною різницею між синтаксисом printf та спринту.

fprintf (FILE * fp, "формат", аргументи) знову як printf. Тут замість відображення даних на моніторі або збереження їх у якійсь рядку форматовані дані зберігаються у файлі, на який вказує покажчик файлу, який використовується в якості першого параметра для fprintf. Покажчик файлу - єдине доповнення до синтаксису printf.

Якщо файл stdout використовується як перший параметр у fprintf, його робота вважається еквівалентною роботі printf.


24

printf(...)еквівалентно fprintf(stdout,...).

fprintf використовується для виведення потоку.

sprintf(buffer,...) використовується для форматування рядка в буфер.

Примітка є також vsprintf, vfprintfіvprintf


У vароматах нестандартні я вважаю
Джон Dibling

8
Ці vаромати дуже , звичайно , в стандарті C.
Фред Фоо

@larsmans: ах, добре. дякую за виправлення Це питання було в один момент позначено [c ++]
Джон Діблінг

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це нестандартна функція. Більшість реалізацій, які я бачив, реалізують це чи щось подібне, але це конкретно для реалізації.
Джон Дайблінг

1
@larsmans вище зазначає, що це насправді частина стандарту С, тому я повертаюсь назад
Джон Діблінг

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]…]);

Ось

Рядок посилається на вказівник на буфер в пам'яті, куди слід записати дані.

Формат відноситься до вказівника на символьну рядок, що визначає формат.

Кожен елемент - це змінна чи вираз, що визначає дані для запису.

Значення, повернене sprintf, більше або дорівнює нулю, якщо операція успішна, або іншими словами, кількість записаних символів, не враховуючи закінчуючий нульовий символ, повертається і повертає значення менше нуля, якщо сталася помилка.

printf: друкує до stdout

Синтаксис для printf:

printf format [argument]…

Єдина відмінність між sprintf () і printf () полягає в тому, що sprintf () записує дані в масив символів, тоді як printf () записує дані в stdout, стандартний пристрій виводу.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.