Diferença entre fprintf, printf e sprintf?


233

Alguém pode explicar em Inglês simples sobre as diferenças entre printf, fprintfe sprintfcom exemplos?

Em que fluxo está?

Estou realmente confuso entre os três enquanto lê sobre "File Handling in C".


4
Experimente-os escrevendo um código de exemplo. Essa é uma maneira muito fácil de entender claramente a diferença entre eles.
Nawaz

14
Prefira snprintf () a sprintf () para evitar estouros de buffer tolos.
Maxim Egorushkin

3
Prefere córregos ou Boost formatadores para evitar bobo buffer overflows e desagradável erros de tipo insegurança
John Dibling

7
@ Maxim, enquanto você levanta um ponto válido, tomarei a segurança de que meus buffers não vão transbordar e explodirei meu aplicativo em pedaços. Eu só olhava para essas funções se os formatadores de fluxos / boost mostrassem causar gargalos visíveis. :)
Moo-Juice

1
@ Maxim: O ponto é que não há necessidade. Meu código não é um gargalo. 5m / s é quantas mensagens a central envia, não quantas somos capazes de processar. Então, por que otimizar prematuramente?
John Dibling

Respostas:


238

Em C, um "fluxo" é uma abstração; da perspectiva do programa, é simplesmente um produtor (fluxo de entrada) ou consumidor (fluxo de saída) de bytes. Pode corresponder a um arquivo em disco, a um tubo, ao seu terminal ou a algum outro dispositivo, como uma impressora ou tty. O FILEtipo contém informações sobre o fluxo. Normalmente, você não mexe FILEdiretamente no conteúdo de um objeto, apenas passa um ponteiro para ele para as várias rotinas de E / S.

Existem três fluxos padrão: stdiné um ponteiro para o fluxo de entrada padrão, stdouté um ponteiro para o fluxo de saída padrão e stderré um ponteiro para o fluxo de saída de erro padrão. Em uma sessão interativa, os três geralmente se referem ao seu console, embora você possa redirecioná-los para apontar para outros arquivos ou dispositivos:

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

Neste exemplo, stdinagora aponta para inputfile.dat, stdoutaponta para output.txte stderraponta para errors.txt.

fprintf grava texto formatado no fluxo de saída que você especificar.

printfé equivalente a escrever fprintf(stdout, ...)e gravar texto formatado para onde o fluxo de saída padrão estiver apontando no momento.

sprintfgrava texto formatado em uma matriz de char, ao contrário de um fluxo.


4
"é simplesmente um produtor (fluxo de entrada) ou consumidor (fluxo de saída) de bytes." São estes ao contrário? Um produtor não criaria (saída) alguma coisa? Perguntando porque eu realmente não sei.
Dave Voyles

6
@DaveVoyles: Estes são da perspectiva do seu programa. Um fluxo de entrada produz bytes para o seu programa ler; um fluxo de saída consome os bytes produzidos a partir do seu programa.
John Bode

153

printfsaídas para o fluxo de saída padrão ( stdout)

fprintfvai para um identificador de arquivo ( FILE*)

sprintfvai para um buffer que você alocou. ( char*)


40

printf ("formato", args) é usado para imprimir os dados na saída padrão, que geralmente é um monitor de computador.

sprintf (char *, "format", args) é como printf. Em vez de exibir a string formatada na saída padrão, ou seja, um monitor, ele armazena os dados formatados em uma string apontada pelo ponteiro char (o primeiro parâmetro). A localização da string é a única diferença entre a sintaxe printf e sprint.

fprintf (FILE * fp, "format", args) é como printf novamente. Aqui, em vez de exibir os dados no monitor ou salvá-los em alguma sequência, os dados formatados são salvos em um arquivo que é apontado pelo ponteiro do arquivo que é usado como o primeiro parâmetro para fprintf. O ponteiro do arquivo é a única adição à sintaxe do printf.

Se o arquivo stdout for usado como o primeiro parâmetro no fprintf, seu funcionamento será considerado equivalente ao do printf.


24

printf(...)é equivalente a fprintf(stdout,...).

fprintf é usado para gerar a saída para transmitir.

sprintf(buffer,...) é usado para formatar uma string em um buffer.

Nota também existe vsprintf, vfprintfevprintf


Os vsabores são não-padrão eu acredito
John Dibling

8
Os vsabores estão certamente no padrão C.
Fred Foo

@larsmans: ah, ok. Obrigado pela correção. Esta questão foi etiquetada em um ponto [c ++]
John Dibling

2

Você também pode fazer coisas muito úteis com a função 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 é útil, mas lembre-se de que essa vsnprintfé uma função não padrão. A maioria das implementações que vi implementam isso ou algo parecido, mas é específico da implementação.
John Dibling

1
@larsmans menciona acima que este é, de facto, uma parte do padrão C, então eu retiro o que disse
John Dibling

2
O que isso tem a ver com C?
onemasse

2

printf

  1. printf é usado para executar a saída na tela.
  2. sintaxe = printf("control string ", argument );
  3. Não está associado à entrada / saída de arquivo

fprintf

  1. O fprintf usado para executar a operação de gravação no arquivo apontado pelo identificador FILE.
  2. A sintaxe é fprintf (filename, "control string ", argument );
  3. Está associado à entrada / saída do arquivo

Se isso for citado em outro lugar, é melhor citar a fonte com um link, mas definitivamente mantenha o texto que você citou aqui.
SuperBiatedMan #

0

fprintfIsso está relacionado aos fluxos em que, como printfé uma instrução semelhante, fprintfmas não relacionada aos fluxos, ou seja, fprintfestá relacionada ao arquivo


0

sprintf: Grava dados formatados em uma cadeia de caracteres na memória em vez de stdout

A sintaxe do sprintf é:

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

Aqui,

String refere-se ao ponteiro para um buffer na memória onde os dados devem ser gravados.

Formato refere-se ao ponteiro para uma cadeia de caracteres que define o formato.

Cada item é uma variável ou expressão que especifica os dados a serem gravados.

O valor retornado pelo sprintf é maior ou igual a zero se a operação for bem-sucedida ou, em outras palavras, o número de caracteres gravados, sem contar o caractere nulo final, é retornado e retorna um valor menor que zero se ocorrer um erro.

printf: imprime em stdout

A sintaxe para printf é:

printf format [argument]…

A única diferença entre sprintf () e printf () é que sprintf () grava dados em uma matriz de caracteres, enquanto printf () grava dados no stdout, o dispositivo de saída padrão.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.