Alô mundo !

Vamos escrever nosso programa Alô mundo em C. Se você estiver usando o Linux abra qualquer editor de textos, pode ser o vi, o emacs, o gedit, etc.....e digite o código abaixo:
#include <stdio.h> int main() { printf("Alô mundo!"); return(0); }

Grave o programa com o nome de alo.c. Para compilar o programa digite o seguinte na linha de comando: $ gcc alo.c -o alo Para executar o programa: $ alo Lembre-se que para executar o programa: 1. Ele deve estar no PATH 2. Você deve ter permissão de execução para o arquivo.

Se você estiver usando o Windows, provavelmente estará usando um compilador tipo o Turbo C2. Neste tipo de compilador para iniciar um novo programa clique em File/New ou digite ALT+F para abrir o menu File e, neste, escolha a opção New. Digite o código. Para salvar o arquivo fonte clique em File/Save Para compilar o programa, clique em Compile/Make ou digite ALT+C para abrir o menu Compile e, neste, escolha a opção Make. Ao executar o arquivo será exibida a mensagem Alo mundo! Vamos analisar o código do programa: #include <stdio.h> Esta linha usa a diretiva #include para inserir o arquivo de cabeçalho stdio.h no seu programa. Os arquivos de cabeçalho são arquivos que contém definições, macros e funções que são muito utilizadas em todos os programas. Normalmente todo compilador C já vem com muitos arquivos de cabeçalho, mas você também pode escrever os seus. Os arquivos de cabeçalho tem a extensão .h int main()

Esta linha indica a definição da função main. Um programa em C é formado por várias funções. Quando o programa é executado main é a primeira função a ser chamada, assim todo programa deve ter uma função main. { As chaves delimitam um bloco de comandos. printf("Alo mundo!"); A função printf exibe o conteúdo do seu argumento na tela. No caso a mensagem Alo mundo !. Esta função faz parte do arquivo de cabeçalho stdio.h por isso ele foi incluído no programa. O comando é terminado com um ; (ponto-e-vírgula). Todo comando em C deve terminar com ; return(0); Este comando indica que a função main retorna 0 (zero). } A última chave fecha o bloco de comandos da função main. Se você não entendeu algum dos conceitos ditos acima não se preocupe, apenas aceite e no futuro você entenderá o porque disso tudo.

Tipos de dados
A linguagem C possui quatro tipos básicos de dados: char - usado para armazenar caracteres int - usado para armazenar números inteiros float - usado para armazenar números de ponto flutuante (decimais) de precisão simples double - usado para armazenar números de ponto flutuante de precisão dupla Para definir uma constante usa-se a diretiva #define. Abaixo segue um exemplo do seu uso:

#include <stdio.h> #define IDADE 34 int main() { printf("Sua idade é %d anos",IDADE); return(0); }

No exemplo acima, toda ocorrência da constante IDADE no código do programa será substituída pelo valor inteiro 34. É importante observar que entre #define e IDADE deve haver apenas um espaço, e entre IDADE e 34 também só deve haver um espaço.

Variáveis
As variáveis devem ser declaradas antes de ser usadas. Para declarar uma variável basta digitar seu tipo, seguido de espaço e de seu nome. Não esqueça o ponto-e-vírgula encerrando o comando.Exemplo: int idade; float nota; As variáveis devem ser declaradas no início da função. Exemplo:
#include <stdio.h> int main() { int idade; float nota1, nota2,nota3, nota4; printf("idade = %d",idade); return(0); }

Observe no exemplo acima que é permitido declarar mais de uma variável na mesma linha.

Nomeando constantes e variáveis
Para nomear as constantes e variáveis siga as seguintes regras:
· · · · ·

Os nomes devem começar com um caractere alfabético O caractere de sublinhado ( _ ) é considerado um caractere alfabético Os nomes podem ser constituídos de caracteres alfabéticos ou numéricos Os nomes não devem conter caracteres especiais (!, @, #, $, %, ¨, &, *, etc ......) Não devem ser utilizadas palavras reservadas da linguagem C que são: int char float short goto for do while switch

unsigned return auto sizeof break

double extern struct union long register typedef static

continue case if else default entry

Por conveção os nomes das constantes devem ser em letras maiúsculas e os nomes das variáveis em letras minúsculas.

char letra. assim este arquivo deve ser incluído no programa para a utilização desta função. printf("O valor de letra é %c\n". . Ela faz parte do arquivo de cabeçalho stdio.letra). letra = 's'.nr).h.Operadores aritméticos OPERADOR + * / % OPERAÇÃO soma subtração multiplicação divisão módulo (resto da divisão inteira) Operadores relacionais OPERADOR > >= < <= == != SIGNIFICADO maior que maior ou igual a menor que menor ou igual a igual a diferente de Operadores lógicos OPERADOR && || SIGNIFICADO e ou Comando de atribuição = A saída de dados é proporcionada pela função printf. nr = 5. printf("O valor de nr é %d\n". Exemplo da utilização de printf: #include <stdio.h> int main() { int nr.

Após a vírgula estão os argumentos que substituirão os especificadores de formato. printf("O número é %d e a letra é %s\n". printf("Entre com o valor do número :").h> int main() { int nr. /* O especificador de formato %s é usado com strings */ scanf("%s". scanf("%s". } Inserindo comentários Para inserir comentários em seu código basta colocá-los entre os sinais /* e */ Exemplo: /* Utilizando a função scanf() para entrada de dados */ #include <stdio.h> int main() { int nr. printf("Entre com a letra :").letra). printf("Entre com o valor do número :").return(0). printf("O número é %d e a letra é %s\n".nr. char letra[2]. } . return(0). return(0). Sua sintaxe é: scanf("EF". scanf("%d".letra). Estes argumentos são posicionais.&nr). scanf("%d". printf("Entre com a letra :").&VARIÁVEL). } Observe que para exibir as variáveis utiliza-se os especificadores de formato %d e %c.&nr).&letra). O caracter de escape \n provoca o avanço para a próxima linha. onde EF é um especificador de formato e VARIÁVEL é variável onde o dado entrado será armazenado.nr. Os especificadores de formato básicos são: %d => int %c => char %f => float Entrada de dados A entrada de dados é feita com a função scanf. char letra[2].&letra). Exemplo: #include <stdio.

E a análise: if (0) É falsa. cuja sintaxe é: if (CONDICÃO) COMANDOS1 else COMANDOS2 Se CONDIÇÃO for verdadeira. printf("Você tem que arrumar um emprego !!!\n").h> /* o conteúdo de main() é um bloco de instruções * por isso está entre chaves */ int main() { int idade. Este conceito é muito usado na linguagem C pois muitas funções retornam valores inteiros. Assim. Para a linguagem C qualquer valor diferente de zero é verdadeiro e o valor zero é considerado falso. } else printf("Você é de menor !!!\n"). /* outro bloco de instruções por isso está entre chaves */ if(idade > 21) { printf("Você já é de maior !!!\n"). .h> int main() { int idade. return(0). Exemplo do uso de if: #include <stdio. } } . scanf("%d". Desvio condicional O desvio condicional é uma estrutura de fluxo onde o programa analisa uma condição e: · · caso esta condição seja verdadeira executa alguns comandos caso esta condição seja falsa executa outros comandos Em C esta estrutura é representada pelo comando if. COMANDOS2 serão executados. a análise: if (1) É verdadeira. COMANDOS1 serão executados. printf("Entre com a idade :"). caso contrário.Bloco de instruções Todo bloco de instruções em C deve ser delimitado por chaves { Exemplo: #include <stdio. É importante saber como a linguagem C representa um valor verdadeiro ou falso.&idade).

. Se um VALOR igual a VARIÁVEL for encontrado. Pesquisar......... } Observe que se o comando é único não há necessidade das chaves para delimitar o bloco de instruções......... ...... os comandos abaixo são executados independente do teste. printf("1... else { printf("Você é de menor !!!\n")...... default: COMANDO.&opcao)....... } return(0)... break.....printf("Entre com sua idade :")....... Múltipla escolha A estrutura de múltipla escolha é implementada pelo comando switch.... Pesquisar\n")........ Comprar\n").... printf("3... sem ele. ...... break. break.... switch (opcao) { case 1: printf("Você escolheu a opção 1. Sair\n").. if(idade > 21) printf("Você é de maior !!!\n")..... . } O entendimento é o seguinte: a VARIÁVEL é comparada com cada VALOR especificado nos cases.. Sua sintaxe é: switch (VARIÁVEL) { case VALOR1: COMANDO1.. printf("2....... Se não houver nenhuma correspondência com os valores dos cases........ case VALOR2: COMANDO2....... o referido COMANDO é executado.&idade).... printf("Tem que amadurecer !!!\n"). scanf("%d".......\n")... Exemplo: #include <stdio.. break..h> int main() { int opcao. scanf("%d".. O comando break deve existir pois.. printf("Entre com sua opção :"). o comando de default é executado.. printf("\n").

scanf("%d".&nr).\n"). os COMANDOS são executados.\n"). caso seja verdadeira. caso seja verdadeira.case 2: printf("Você escolheu a opção 2. A característica importante deste tipo de construção é que. cuja sintaxe é: while (CONDIÇÃO) COMANDOS. os COMANDOS não serão executados nenhuma vez. Sair. Isto se repete até que a avaliação da CONDIÇÃO resulte em falso.&nr). caso a CONDIÇÃO seja avaliada como falsa já na primeira vez.\n"). while (nr != -1) { printf("Você digitou %d\n". Exemplo: #include <stdio. } return(0). }. } Repetição com teste no início Esta estrutura é representada pelo comando while. printf("Você digitou -1 para sair. os COMANDOS são executados de novo. Comprar.\n"). case 3: printf("Você escolheu a opção 3. printf("Digite um número : (-1 para sair)"). printf("Digite outro número (-1 para sair) :"). break.nr). A CONDIÇÃO é avaliada e. } . return(0). break. a CONDIÇÃO é avaliada novamente e. scanf("%d". default:printf("Você não escolheu nenhuma das três opções. break. Então.h> int main() { int nr.

} while (nr != -1).&nr). printf("Você digitou -1 para sair. A característica importante deste tipo de construção é que os COMANDOS são executados pelo menos uma vez.\n").h> int main() { int nr. return(0). scanf("%d". Caso. } Observe que o código não funciona corretamente. scanf("%d".&nr). Sua sintaxe é: do COMANDOS while (CONDICÃO). printf("Digite um número : (-1 para sair)").nr). seja verdadeira os COMANDOS são executados novamente e a CONDIÇÃO novamente é avaliada. Este ciclo continua até que a CONDIÇÃO seja falsa. mesmo assim as instruções do laço do são executadas. . O que não ocorre no código do exemplo da seção anterior. Os COMANDOS são executados e depois a CONDIÇÃO é avaliada. independente da CONDIÇÃO. printf("Digite outro número (-1 para sair) :"). Observe o código do exemplo da seção anterior usando do: #include <stdio. Digite -1 logo de início para encerrar o programa e.Repetição com teste no final Esta estrutura é implementada com o comando do. do { printf("Você digitou %d\n".

int provavelmente terá 16 bits. os COMANDOS são executados O ciclo continua até que CONDIÇÃO seja falsa Exemplo: #include int main() { int contador. Os modificadores de tipo do C são quatro: signed. long e short. Destes não vimos ainda os dois últimos: O double é o ponto flutuante duplo e pode ser visto como um ponto flutuante com muito mais precisão.INCREMENTO) COMANDOS.contador < 51. void. for(contador=1. Os quatro modificadores podem ser aplicados a inteiros. com a única restrição de que shorts ints e ints devem ocupar pelo menos 16 bits. caso seja verdadeira. os COMANDOS são executados A variável de controle é incrementada de acordo com INCREMENTO CONDIÇÃO é novamente testada e.contador = contador + 1) { printf("%d ". que não pode ser maior que long int. unsigned.contador). } Linguagem C . O modificador unsigned serve para especificar variáveis sem sinal. printf("Exibindo os números de 1 até 50\n"). Na verdade.CONDIÇÃO. Um unsigned int será um inteiro que assumirá apenas valores positivos. o entendimento é o seguinte: · · · · · · · A variável de controle é inicializada em INICIALIZAÇÃO CONDIÇÃO é testada e. } printf("\n"). e short int não pode ser maior que int. double. A seguir estão listados os tipos de dados permitidos e seu valores máximos e mínimos em um compilador típico para um hardware de 16 bits. numa máquina de 16 bits. Para cada um dos tipos de variáveis existem os modificadores de tipo. cada compilador é livre para escolher tamanhos adequados para o seu próprio hardware. Também nesta tabela está especificado o formato que deve ser utilizado para ler os tipos de dados com a função scanf(): . ou um "tipo sem tipo". caso seja verdadeira.tipos de dados O C tem 5 tipos básicos: char. os COMANDOS são executados A variável de controle é incrementada CONDIÇÃO é novamente testada e. int normalmente terá o tamanho natural para uma determinada máquina. Inteiros menores (short) ou maiores (long).Repetição com variável de controle Esta estrutura é implementada pelo comando for. Numa máquina de 32. Ao float não se pode aplicar nenhum e ao double pode-se aplicar apenas o long. A aplicação deste "tipo" será vista posteriormente. int deverá ter 32 bits. int. return(0). longs ints pelo menos 32 bits. O void é o tipo vazio. float. caso seja verdadeira. cuja sintaxe é: for(INICIALIZAÇÃO. A intenção é que short e long devam prover tamanhos diferentes de inteiros onde isto for prático. Assim.

4E-38 1.535 32. É importante observar que os intervalos de ponto flutuante.4E-38 a 3.4E+38 1.767 char -128 a 127 1 float 3. estão indicados em faixa de expoente.768 -2.767 65.483.Tipo char unsigned char signed char int unsigned int signed int short int unsigned short int signed short int long int signed long int unsigned long int float double long double Num de bits 8 8 8 16 16 16 16 16 16 32 32 32 32 64 80 Formato para leitura com scanf %c %c %c %i %u %i %hi %hu %hi %li %li %lu %f %lf %Lf Intervalo Inicio -128 0 -128 -32.767 65.768 0 -32.647 2.967.4E+38 4 double -1.647 4.648 -2. 1.768 a 32.768 0 -32.147.535 2 .483.535 32.483. Variáveis Abaixo segue uma tabela com os tipos básicos de variáveis usadas na linguagem C.483.4E+4932 O tipo long double é o tipo de ponto flutuante com maior precisão.768 -32.648 0 3. mas os números podem assumir valores tanto positivos quanto negativos.147.767 32.7E+308 8 unsigned int 0 a 65.147. TIPO VALOR ARMAZENADO números inteiros positivos e negativos caracteres e números inteiros positivos e negativos números em ponto flutuante positivos e negativos com precisão simples números em ponto flutuante positivos e negativos com precisão dupla números inteiros positivos INTERVALO TAMANHO (bytes) 2 int -32. na tabela acima.294.7E+308 3.767 2.7E-308 a 1.295 3.147.4E-4932 Fim 127 255 127 32.7E-308 3.

768 a 32.\n". Exemplo /* usando o operador sizeof */ #include <stdio.967.147.767 char -128 a 127 1 float 3.1 Determinando o tamanho de uma variável Quando você precisar determinar o tamanho de uma variável use o operador sizeof. printf("A variável nr é um inteiro e tem %d bytes.265 4 4 1.\n". Variáveis Abaixo segue uma tabela com os tipos básicos de variáveis usadas na linguagem C.648 a 2. Sua sintaxe é: sizeof(VARIÁVEL).unsigned char caracteres e números inteiros positivos números inteiros positivos e negativos números inteiros positivos 0 a 255 1 long int unsigned long int -2.h> int main() { int nr.292.147.483.sizeof(char)).sizeof(nr)).483. return(0). Ele retorna o número de bytes de uma variável.7E+308 8 .7E-308 a 1.647 0 a 4.4E-38 a 3.4E+38 4 double -1. } 1. printf("Já o tipo de dado char tem %d bytes. onde VARIÁVEL pode ser uma variável ou um tipo de dado. TIPO VALOR ARMAZENADO números inteiros positivos e negativos caracteres e números inteiros positivos e negativos números em ponto flutuante positivos e negativos com precisão simples números em ponto flutuante positivos e negativos com INTERVALO TAMANHO (bytes) 2 int -32.

....483. aumentando a performance do programa..\n". printf("Já o tipo de dado char tem %d bytes.... printf("A variável nr é um inteiro e tem %d bytes.... Você deverá usá-las com as variáveis que seu programa deverá acessar repetidamente como as variáveis controladoras de laço..292... Exemplo: int main() { register int contador.1 Determinando o tamanho de uma variável Quando você precisar determinar o tamanho de uma variável use o operador sizeof...647 0 a 4..h> int main() { int nr. } ....535 0 a 255 2 1 long int unsigned long int -2.....sizeof(char)). é armazenada dentro dos registradores. Ele retorna o número de bytes de uma variável. ...... .147......precisão dupla unsigned int unsigned char números inteiros positivos caracteres e números inteiros positivos números inteiros positivos e negativos números inteiros positivos 0 a 65..sizeof(nr)).483... Exemplo /* usando o operador sizeof */ #include <stdio. onde VARIÁVEL pode ser uma variável ou um tipo de dado.\n".... } 2..147.265 4 4 1..........967...... Sua sintaxe é: sizeof(VARIÁVEL)... return(0)..648 a 2. sempre que possível.... Register Uma váriavel do tipo register... ....

3. seja ele um laço for ou um laço while.1 Especificadores de formato ESPECIFICADOR %d %o %x inteiro em formato hexadecimal %X %u %ld %f %c %e float em formato exponencial %E %g %G %s %p %n float. printf 4. Interrompendo um laço Para interromper um laço. 4. O comando continue interrompe o laço e continua na próxima iteração. você pode usar os comandos continue e break. O comando break interrompe o laço e continua na próxima instrução de programa após o laço. C escolhe melhor maneira de exibição entre normal e exponencial string endereço de um ponteiro quantos caracteres a função printf exibiu unsigned int long int float char inteiro inteiro em formato octal VALOR .

Exemplo: #include <stdio. Exemplo: #include <stdio.h> int main() { int nr_pos.2 Exibindo o sinal de positivo ou negativo antes de um número Por padrão o sinal de subtração precede um número negativo. /* Exibe valor com um mínimo de 5 caracteres e com 3 dígitos a direita do ponto decimal */ 4. valor).nr_neg.4 Formatando valores float printf(" %5. printf(" %05d ".h> int main() { .nr_pos).4.valor).3 Formatando valores inteiros SINTAXE printf (" %5d ". } 4. #%o #%x exibe um valor hexadecimal precedido de 0x #%X EFEITO exibe valor com um mínimo de 5 caracteres exibe valor com um mínimo de 5 caracteres precedendo-o com zeros exibe um valor octal precedido de 0 (zero) 4. nr_pos = 3. printf("nr_pos = %+d\n".valor). return(0). Para que o sinal de adição preceda um número positivo inclua um sinal de adição logo após o % no especificador de formato. printf justifica o texto à direita. printf("nr_neg = %d\n". nr_neg = -3. Para justificar à esquerda coloque um sinal de subtração após o %.5 Justificando à esquerda Por padrão.3f ".nr_neg).

return(0). printf("Justificado a esquerda => %-5d\n".int valor = 1. } 4.7 Caracteres de escape CARACTERE \a \b \f \n \r \t \v \\ \' \" \? \nnn aviso sonoro retrocesso avanço de formulário nova linha retorno do carro (sem alimentação de linha) tabulação horizontal tabulação vertical caractere de barra invertida apóstrofe aspas interrogação valor ASCII em octal SIGNIFICADO . return(0).valor).h> int main() { printf("Esta string é muito grande e por isso foi\ quebrada em mais de uma linha. printf("Justificado a direita => %5d\n". } 4.6 Quebrando uma string em duas linhas #include <stdio.valor). Para fazer isso você\ deve usar o sinal de barra invertida.").

9 Usando o controlador ANSI para exibir em cores.\xnnn valor ASCII em hexadecimal 4. 4. o especificador %n coloca o número de caracteres exibidos por printf na variável &nr_caracteres. printf("\nA frase acima tem %d caracteres. return(0).nr_caracteres). } No exemplo acima.h> int main() { int nr_caracteres.8 Verificando quantos caracteres printf exibiu #include <stdio. printf("Verificando quantos caracteres printf exibiu.".&nr_caracteres). limpar a tela e posicionar o cursor Exibindo em cores SEQUÊNCIA DE ESCAPE \033[30m \033[31m \033[32m \033[33m \033[34m \033[35m \033[36m \033[37m \033[40m \033[41m \033[42m \033[43m COR Cor do primeiro plano preta Cor do primeiro plano vermelha Cor do primeiro plano verde Cor do primeiro plano laranja Cor do primeiro plano azul Cor do primeiro plano magenta Cor do primeiro plano ciano Cor do primeiro plano branca Cor do fundo preta Cor do fundo vermelha Cor do fundo verde Cor do fundo laranja .%n".

\n"). return(0). /* fundo vermelho */ printf("\033[37m").yH \033[xA \033[xB \033[yC \033[yD \033[S \033[U \033[2J \033[K FUNÇÃO posiciona o cursor na linha x. coluna y move o cursor x linhas para cima move o cursor x linhas para baixo move o cursor y colunas para a direita move o cursor y colunas para a esquerda armazena a posição atual do cursor restaura a posição do cursor limpa a tela limpa a linha atual Exemplo: #include <stdio. } Posicionando o cursor SEQUÊNCIA DE ESCAPE \033[x.h> int main() { printf("\033[41m").h> int main() { printf("\033[2J"). /* limpa a tela */ return(0). /* primeiro plano branco */ printf("Exibindo o fundo em vermelho e o primeiro plano em branco.\033[44m \033[45m \033[46m \033[47m Cor do fundo azul Cor do fundo magenta Cor do fundo ciano Cor do fundo branca Exemplo : #include <stdio. } .

4.2 Exibindo o sinal de positivo ou negativo antes de um número Por padrão o sinal de subtração precede um número negativo. printf 4.1 Especificadores de formato ESPECIFICADOR %d %o %x inteiro em formato hexadecimal %X %u %ld %f %c %e float em formato exponencial %E %g %G %s %p %n float. Para que o sinal de adição preceda um número positivo inclua um sinal de adição logo após o % no especificador de formato.h> int main() . C escolhe melhor maneira de exibição entre normal e exponencial string endereço de um ponteiro quantos caracteres a função printf exibiu unsigned int long int float char inteiro inteiro em formato octal VALOR 4. Exemplo: #include <stdio.

nr_pos = 3. printf("Justificado a esquerda => %-5d\n".3 Formatando valores inteiros SINTAXE printf (" %5d ". printf justifica o texto à direita. Para justificar à esquerda coloque um sinal de subtração após o %. valor).valor).5 Justificando à esquerda Por padrão. } 4. printf("nr_pos = %+d\n".{ int nr_pos. printf(" %05d ". } 4.h> int main() { int valor = 1. nr_neg = -3. return(0).nr_neg. return(0). printf("Justificado a direita => %5d\n".nr_pos).nr_neg).3f ".valor). #%o #%x exibe um valor hexadecimal precedido de 0x #%X EFEITO exibe valor com um mínimo de 5 caracteres exibe valor com um mínimo de 5 caracteres precedendo-o com zeros exibe um valor octal precedido de 0 (zero) 4.4 Formatando valores float printf(" %5. /* Exibe valor com um mínimo de 5 caracteres e com 3 dígitos a direita do ponto decimal */ 4. Exemplo: #include <stdio.valor).valor). printf("nr_neg = %d\n".h> .6 Quebrando uma string em duas linhas #include <stdio.

printf("Verificando quantos caracteres printf exibiu. Para fazer isso você\ deve usar o sinal de barra invertida. .int main() { printf("Esta string é muito grande e por isso foi\ quebrada em mais de uma linha.8 Verificando quantos caracteres printf exibiu #include <stdio. } 4.&nr_caracteres).h> int main() { int nr_caracteres. return(0).%n".7 Caracteres de escape CARACTERE \a \b \f \n \r \t \v \\ \' \" \? \nnn \xnnn aviso sonoro retrocesso avanço de formulário nova linha retorno do carro (sem alimentação de linha) tabulação horizontal tabulação vertical caractere de barra invertida apóstrofe aspas interrogação valor ASCII em octal valor ASCII em hexadecimal SIGNIFICADO 4.").

". return(0). o especificador %n coloca o número de caracteres exibidos por printf na variável &nr_caracteres. } No exemplo acima. 4.9 Usando o controlador ANSI para exibir em cores.printf("\nA frase acima tem %d caracteres.nr_caracteres). limpar a tela e posicionar o cursor Exibindo em cores SEQUÊNCIA DE ESCAPE \033[30m \033[31m \033[32m \033[33m \033[34m \033[35m \033[36m \033[37m \033[40m \033[41m \033[42m \033[43m \033[44m \033[45m \033[46m \033[47m COR Cor do primeiro plano preta Cor do primeiro plano vermelha Cor do primeiro plano verde Cor do primeiro plano laranja Cor do primeiro plano azul Cor do primeiro plano magenta Cor do primeiro plano ciano Cor do primeiro plano branca Cor do fundo preta Cor do fundo vermelha Cor do fundo verde Cor do fundo laranja Cor do fundo azul Cor do fundo magenta Cor do fundo ciano Cor do fundo branca Exemplo : .

/* primeiro plano branco */ printf("Exibindo o fundo em vermelho e o primeiro plano em branco. coluna y move o cursor x linhas para cima move o cursor x linhas para baixo move o cursor y colunas para a direita move o cursor y colunas para a esquerda armazena a posição atual do cursor restaura a posição do cursor limpa a tela limpa a linha atual Exemplo: #include <stdio.#include <stdio. return(0). /* fundo vermelho */ printf("\033[37m"). /* limpa a tela */ return(0).h> int main() { printf("\033[2J").\n"). } 4.h> int main() { printf("\033[41m").yH \033[xA \033[xB \033[yC \033[yD \033[S \033[U \033[2J \033[K FUNÇÃO posiciona o cursor na linha x. } Posicionando o cursor SEQUÊNCIA DE ESCAPE \033[x. printf 4.1 Especificadores de formato ESPECIFICADOR %d inteiro VALOR .

printf("nr_neg = %d\n". } .nr_pos).%o %x inteiro em formato octal inteiro em formato hexadecimal %X %u %ld %f %c %e float em formato exponencial %E %g %G %s %p %n float.h> int main() { int nr_pos. return(0). nr_pos = 3. printf("nr_pos = %+d\n". nr_neg = -3.nr_neg).nr_neg. Exemplo: #include <stdio. Para que o sinal de adição preceda um número positivo inclua um sinal de adição logo após o % no especificador de formato.2 Exibindo o sinal de positivo ou negativo antes de um número Por padrão o sinal de subtração precede um número negativo. C escolhe melhor maneira de exibição entre normal e exponencial string endereço de um ponteiro quantos caracteres a função printf exibiu unsigned int long int float char 4.

return(0). return(0). } 4.3 Formatando valores inteiros SINTAXE printf (" %5d ". } 4. printf("Justificado a esquerda => %-5d\n".3f ". printf("Justificado a direita => %5d\n".7 Caracteres de escape . printf justifica o texto à direita.5 Justificando à esquerda Por padrão.valor). Para justificar à esquerda coloque um sinal de subtração após o %.valor). printf(" %05d ". Para fazer isso você\ deve usar o sinal de barra invertida. Exemplo: #include <stdio.4 Formatando valores float printf(" %5. #%o #%x exibe um valor hexadecimal precedido de 0x #%X EFEITO exibe valor com um mínimo de 5 caracteres exibe valor com um mínimo de 5 caracteres precedendo-o com zeros exibe um valor octal precedido de 0 (zero) 4.h> int main() { printf("Esta string é muito grande e por isso foi\ quebrada em mais de uma linha. /* Exibe valor com um mínimo de 5 caracteres e com 3 dígitos a direita do ponto decimal */ 4. valor).").4.valor).h> int main() { int valor = 1.valor).6 Quebrando uma string em duas linhas #include <stdio.

". } No exemplo acima.8 Verificando quantos caracteres printf exibiu #include <stdio. printf("Verificando quantos caracteres printf exibiu.&nr_caracteres).CARACTERE \a \b \f \n \r \t \v \\ \' \" \? \nnn \xnnn aviso sonoro retrocesso SIGNIFICADO avanço de formulário nova linha retorno do carro (sem alimentação de linha) tabulação horizontal tabulação vertical caractere de barra invertida apóstrofe aspas interrogação valor ASCII em octal valor ASCII em hexadecimal 4.h> int main() { int nr_caracteres. return(0). printf("\nA frase acima tem %d caracteres.9 Usando o controlador ANSI para exibir em cores. o especificador %n coloca o número de caracteres exibidos por printf na variável &nr_caracteres.nr_caracteres). 4. limpar a tela e posicionar o cursor .%n".

h> int main() { printf("\033[41m"). /* fundo vermelho */ printf("\033[37m").\n"). /* primeiro plano branco */ printf("Exibindo o fundo em vermelho e o primeiro plano em branco. } Posicionando o cursor .Exibindo em cores SEQUÊNCIA DE ESCAPE \033[30m \033[31m \033[32m \033[33m \033[34m \033[35m \033[36m \033[37m \033[40m \033[41m \033[42m \033[43m \033[44m \033[45m \033[46m \033[47m COR Cor do primeiro plano preta Cor do primeiro plano vermelha Cor do primeiro plano verde Cor do primeiro plano laranja Cor do primeiro plano azul Cor do primeiro plano magenta Cor do primeiro plano ciano Cor do primeiro plano branca Cor do fundo preta Cor do fundo vermelha Cor do fundo verde Cor do fundo laranja Cor do fundo azul Cor do fundo magenta Cor do fundo ciano Cor do fundo branca Exemplo : #include <stdio. return(0).

printf 4.1 Especificadores de formato ESPECIFICADOR %d %o %x inteiro em formato hexadecimal %X %u unsigned int inteiro inteiro em formato octal VALOR . coluna y move o cursor x linhas para cima move o cursor x linhas para baixo move o cursor y colunas para a direita move o cursor y colunas para a esquerda armazena a posição atual do cursor restaura a posição do cursor limpa a tela limpa a linha atual Exemplo: #include <stdio.SEQUÊNCIA DE ESCAPE \033[x.h> int main() { printf("\033[2J"). /* limpa a tela */ return(0). } 4.yH \033[xA \033[xB \033[yC \033[yD \033[S \033[U \033[2J \033[K FUNÇÃO posiciona o cursor na linha x.

%ld %f %c %e

long int float char

float em formato exponencial %E %g %G %s %p %n float. C escolhe melhor maneira de exibição entre normal e exponencial string endereço de um ponteiro quantos caracteres a função printf exibiu

4.2 Exibindo o sinal de positivo ou negativo antes de um número
Por padrão o sinal de subtração precede um número negativo. Para que o sinal de adição preceda um número positivo inclua um sinal de adição logo após o % no especificador de formato. Exemplo:
#include <stdio.h> int main() { int nr_pos,nr_neg; nr_pos = 3; nr_neg = -3; printf("nr_pos = %+d\n",nr_pos); printf("nr_neg = %d\n",nr_neg); return(0); }

4.3 Formatando valores inteiros
SINTAXE printf (" %5d ",valor); EFEITO exibe valor com um mínimo de 5 caracteres

printf(" %05d ",valor); #%o #%x

exibe valor com um mínimo de 5 caracteres precedendo-o com zeros exibe um valor octal precedido de 0 (zero)

exibe um valor hexadecimal precedido de 0x #%X

4.4 Formatando valores float
printf(" %5.3f ", valor); /* Exibe valor com um mínimo de 5 caracteres e com 3 dígitos a direita do ponto decimal */

4.5 Justificando à esquerda
Por padrão, printf justifica o texto à direita. Para justificar à esquerda coloque um sinal de subtração após o %. Exemplo:
#include <stdio.h> int main() { int valor = 1; printf("Justificado a direita => %5d\n",valor);

printf("Justificado a esquerda => %-5d\n",valor); return(0); }

4.6 Quebrando uma string em duas linhas
#include <stdio.h> int main() { printf("Esta string é muito grande e por isso foi\ quebrada em mais de uma linha. Para fazer isso você\ deve usar o sinal de barra invertida."); return(0); }

4.7 Caracteres de escape
CARACTERE \a aviso sonoro SIGNIFICADO

\b \f \n \r \t \v \\ \' \" \? \nnn \xnnn

retrocesso avanço de formulário nova linha retorno do carro (sem alimentação de linha) tabulação horizontal tabulação vertical caractere de barra invertida apóstrofe aspas interrogação valor ASCII em octal valor ASCII em hexadecimal

4.8 Verificando quantos caracteres printf exibiu
#include <stdio.h> int main() { int nr_caracteres; printf("Verificando quantos caracteres printf exibiu.%n",&nr_caracteres); printf("\nA frase acima tem %d caracteres.",nr_caracteres); return(0); }

No exemplo acima, o especificador %n coloca o número de caracteres exibidos por printf na variável &nr_caracteres.

4.9 Usando o controlador ANSI para exibir em cores, limpar a tela e posicionar o cursor
Exibindo em cores SEQUÊNCIA DE ESCAPE COR

} Posicionando o cursor SEQUÊNCIA DE ESCAPE FUNÇÃO . /* fundo vermelho */ printf("\033[37m").\033[30m \033[31m \033[32m \033[33m \033[34m \033[35m \033[36m \033[37m \033[40m \033[41m \033[42m \033[43m \033[44m \033[45m \033[46m \033[47m Cor do primeiro plano preta Cor do primeiro plano vermelha Cor do primeiro plano verde Cor do primeiro plano laranja Cor do primeiro plano azul Cor do primeiro plano magenta Cor do primeiro plano ciano Cor do primeiro plano branca Cor do fundo preta Cor do fundo vermelha Cor do fundo verde Cor do fundo laranja Cor do fundo azul Cor do fundo magenta Cor do fundo ciano Cor do fundo branca Exemplo : #include <stdio.h> int main() { printf("\033[41m"). return(0).\n"). /* primeiro plano branco */ printf("Exibindo o fundo em vermelho e o primeiro plano em branco.

\033[x;yH \033[xA \033[xB \033[yC \033[yD \033[S \033[U \033[2J \033[K

posiciona o cursor na linha x, coluna y move o cursor x linhas para cima move o cursor x linhas para baixo move o cursor y colunas para a direita move o cursor y colunas para a esquerda armazena a posição atual do cursor restaura a posição do cursor limpa a tela limpa a linha atual

Exemplo:
#include <stdio.h> int main() { printf("\033[2J"); /* limpa a tela */ return(0); }

5. Outros operadores
operador de incremento => ++ contador++ ==> é o mesmo que contador = contador + 1 contador++ ==> a variável contador é utiliizada e depois incrementada ++contador ==> a variável contador é incrementada e depois utilizada

operador de decremento => -contador-- ==> é o mesmo que contador = contador - 1 contador-- ==> a variável contador é utiliizada e depois decrementada --contador ==> a variável contador é decrementada e depois utilizada

simplificando atribuições de expressão a uma variável

EXPRESSÃO NORMAL
total = total + 100 conta = conta - 5 metade = metade / 2

EXPRESSÃO SIMPLIFICADA
total + = 100 conta - = 5 metade / = 2

operador condicional (CONDIÇÃO) ? COMANDO_V : COMANDO_F; CONDIÇÃO é avaliada. Se for verdadeira, COMANDO_V será executado. Caso contrário, COMANDO_F será executado.

6. strings

6.1 Determinando o tamanho de uma string
Para determinar o tamanho de uma string use a função strlen( ). Esta função faz parte do arquivo de cabeçalho string.h. Sua sintaxe é:

strlen(string) Exemplo:
/* Determinando o tamanho de uma string usando * a função strlen() */ #include <stdio.h> #include <string.h> int main() { char string[20]; printf("\n"); printf("Determinando o tamanho de uma string\n"); printf("------------------------------------\n"); printf("\n"); printf("Digite a string :"); scanf("%s",&string); printf("\n"); printf("A string tem %d carateres.\n\n",strlen(string)); return(0); }

6.2 Copiando uma string em outra
Para copiar uma string em outra use a função strcpy( ). Esta função faz parte do arquivo de cabeçalho string.h. Sua sintaxe é:

strcpy(destino, origem) Exemplo:

/* Copiando uma string em outra usando a * função strcpy() */ #include <stdio.h> #include <string.h> int main() { char string1[10], string2[10]; printf("\n"); printf("Copiando uma string em outra\n"); printf("----------------------------\n"); printf("\n"); printf("Digite string1 :"); scanf("%s",&string1); printf("\n"); printf("string1 = %s\n",string1); printf("string2 = %s\n",strcpy(string2,string1)); return(0); }

Na prática, todo conteúdo de string2 é substituído por string1.

6.3 Unindo duas strings
Para unir duas strings use a função strcat( ). Esta função faz parte do arquivo de cabeçalho string.h. Sua sintaxe é:

strcat(destino, origem) Exemplo:
/* Unindo duas strings usando a * função strcat() */ #include <stdio.h> #include <string.h> int main() { char string1[100], string2[10]; printf("\n"); printf("Unindo duas strings\n"); printf("-------------------\n"); printf("\n"); printf("Digite string1 :"); scanf("%s",&string1); printf("\n"); printf("Digite string2 :"); scanf("%s",&string2); printf("\n"); printf("Unindo string1 a string2 : %s\n\n",strcat(string2,string1)); return(0); }

6.4 Anexando caracteres de uma string em outra
Para anexar caracteres de uma string em outra use a função strncat( ). Esta função faz parte do arquivo de cabeçalho string.h. Sua sintaxe é :

strncat(destino, origem, nr_caracteres)

printf("------------------------------------\n").string2).&string). printf("\n"). printf("\n"). } 6. printf("\n"). printf("string digitada : %s\n".Exemplo: /* Anexando caracteres de uma string * em outra usando a função strncat()*/ #include <stdio.&string1).h> int main() { char string1[20]. Esta função faz parte do arquivo de cabeçalho string.h. .3)). char *str2) { while((*str1 == *str2) && (*str1)) { str1++. printf("\n"). Sua sintaxe é: strupr(string) Exemplo: /* Convertendo uma string em maiúsculas * usando a função strupr() */ #include <stdio. str2++. printf("string1 + 3 caracteres de string 2 = %s\n".strncat(string1. printf("string2 = %s\n\n". scanf("%s".h> #include <string. printf("------------------------------------------\n").6 Convertendo uma string para maiúsculas Para converter uma string para maiúsculas use a função strupr( ). } return((*str1 == NULL) && (*str2 == NULL)).h> #include <string. printf("Convertendo uma string para maiúsculas\n").string2[6]="aeiou". printf("Entre com a string :").string). return(0). printf("\n").h> int main() { char string[20]. printf("Entre com string1 :"). scanf("%s". } 6. printf("Anexando caracteres de uma string em outra\n").5 Função que determina se duas strings são iguais int streql(char *str1. printf("\n").string2.

h> int main() { char string[30] = "Teste da função strchr(). 's'). printf("Convertendo para minúsculas : %s\n". printf("------------------------------------\n").strupr(string)). printf("Convertendo uma string para minúsculas\n"). Exemplo: /* Localizando o primeiro caracter numa string * usando a função strchr()*/ #include <stdio. Sua sintaxe é: strchr(string.".h. Ela faz parte do arquivo de cabeçalho string.strlwr(string)).h. ptr = strchr(string. return(0). printf("\n%s\n". printf("string digitada : %s\n".8 Localizando a primeira ocorrência de um caractere numa string Para isso use a função strchr( ). printf("Convertendo para maiúsculas : %s\n". caracter) Este função retorna um ponteiro para a primeira ocorrência de "caracter". } 6. ela retornará um ponteiro para o caractere NULL que marca o final da string. printf("\n"). Sua sintaxe é: strlwr(string) Exemplo: /* Convertendo uma string em minúsculas * usando a função strlwr() */ #include <stdio. char *ptr.7 Convertendo uma string para minúsculas Para converter uma string para minúsculas use a função strlwr( ). } 6. Caso "caracter" não seja encontrado.printf("\n"). printf("\n"). printf("\n").string). return(0).&string). Esta função faz parte do arquivo de cabeçalho string.string). .h> int main() { char string[20].h> #include <string.h> #include <string. printf("\n"). scanf("%s". printf("Entre com a string :").

} 6. printf("A primeira ocorrência de s é na posição %d\n". 's').10 Função que conta o número de ocorrências de um caractere numa string int contachar(char string[].if (*ptr) { printf("\n"). caracter) Este função retorna um ponteiro para a última ocorrência de "caracter".".\n"). tamanho = strlen(string).h>: . ocorrencia = 0.contador++) if(string[contador] == letra) ocorrencia++. printf("A última ocorrência de s é na posição %d\n". } Abaixo segue um exemplo com a utilização da função contachar().string). Ela faz parte do arquivo de cabeçalho string.9 Localizando a última ocorrência de um caractere numa string Para isso use a função strrchr( ). tamanho.h. Exemplo: /* Localizando o último caracter numa string * usando a função strrchr()*/ #include <stdio.h> int main() { char string[30] = "Teste da função strrchr().ptr . Caso "caracter" não seja encontrado. char *ptr. return(0). char letra) { int contador. if (*ptr) { printf("\n"). return(0).ptr . for(contador=1. Sua sintaxe é: strrchr(string. ptr = strrchr(string. printf("\n%s\n".\n"). ela retornará um ponteiro para o caractere NULL que marca o final da string.contador <= tamanho. } else printf("Caractere não encontrado.string). } else printf("Caractere não encontrado. return(ocorrencia).h> #include <string. O exemplo considera que ela faz parte do arquivo de cabeçalho <samfunc.string). } 6.

#include <stdio. Ela faz parte do arquivo de cabaçalho string. printf("Invertendo ==> %s". Sua sintaxe é: strrev(string) Exemplo: /* Invertendo uma string usando a * função strrev() */ #include <stdio. printf("Entre com a string :"). printf("\n"). char letra[2].12 Substituindo os caracteres da string por um único caracter Para substituir todos os caracteres da string pelo mesmo caracter use a função strset( ). printf("Entre com a letra :"). printf("---------------------------\n"). printf("\n").h. printf("\n"). printf("Testando a função contachar()\n"). printf("---------------------\n"). printf("Entre com a string :"). } 6.h> int main() { char string[20]. return(0).11 Invertendo uma string utilizando a função strrev( ) Para inverter o conteúdo de uma string use a função strrev( ). printf("Invertendo uma string\n"). scanf("%s".&string). Ela faz parte do arquivo de cabeçalho string.&string).h> #include <samfunc.nr). } 6. printf("\n").h> int main() { char *string[20].&letra). scanf("%s". Sua sintaxe é: strset(string. printf("\n").letra[0]).h> #include <string.h> #include <string.strrev(string)). return(0).caracter) Exemplo: . scanf("%s". printf("Contando o número de ocorrências : %d\n". int nr. nr = contachar(string. printf("\n").h.

13 Comparando duas strings Para comparar duas strings use a função strcmp( ). Ela faz parte do arquivo de cabeçalho string. return(0).string2).h> int main() { char string[20]. printf("\n"). printf("Substituindo os caracteres da string\n"). printf("\n"). maior. printf("\n"). else . printf("Digite a string :").string2) Se as strings forem iguais a função retorna zero.&string). } 6. printf("\n"). char caracter[2]. printf("\n").caracter[0])). else if(retorno < 0) printf("A string1 .&caracter). printf("Entre com a segunda string :"). Sua sintaxe é: strcmp(string1. printf("-----------------------\n"). printf("\n").&string1). if(retorno == 0) printf("As strings são iguais. scanf("%s". printf("Entre com a primeira string :").\n").h> int main() { char string1[20]. printf("Caractere :"). printf("------------------------------------\n"). scanf("%s". retorno = strcmp(string1.strset(string. int retorno. Exemplo: /* Comparando duas strings com a função strcmp() */ #include <stdio.&string2). scanf("%s". se string1 for maior a função retorna um valor menor que zero e se string2 for maior a função retorna um valor maior que zero. scanf("%s". printf("\n").\n").string2[20]. printf("\n")./* Substituindo todos os caracteres da string * pelo mesmo caracter usando a função strset() */ #include <stdio.h.h> #include <string.h> #include <string. printf("Comparando duas strings\n"). printf("Substituindo ==> %s".

&string2).h> int main() { char string1[20].h Exemplo: /* Convertendo strings em números */ #include <stdio.string2[20]. maior.nr_caracteres) 2. a função strncmp( ) que compara os n primeiros caracteres de duas strings. 6.string2. printf("Entre com a segunda string :"). } OBSERVAÇÕES: 1. printf("Convertendo strings em números\n").atof(string1) + atof(string2)). printf("\n"). printf("string1 + string2 = %f". printf("\n").&string1). Sua sintaxe é: strncmp(string1. return(0). A função strcmp( ) possui uma variante. printf("------------------------------\n").h> #include <stdlib. scanf("%s".14 Convertendo strings em números Para converter strings em números utilize as funções abaixo: FUNÇÃO atof(string) atoi(string) atol(string) strtod(string) strtol(string) float int long int double long CONVERTE STRINGS EM Estas funções fazem parte do arquivo de cabeçalho stdlib. return(0). } . Existem ainda as funções stricmp( ) e strncmpi( ) que comparam duas strings sem considerar a caixa das letras (maiúsculas ou minúsculas). scanf("%s".printf("A string2 .\n"). printf("Entre com a primeira string :"). printf("\n"). printf("\n").

Ela pertence ao arquivo de cabeçalho string.substring) Se a substring existir dentro da string. printf("Entre com a string :"). printf("\n"). printf("\n"). printf("Duplicando uma string\n"). printf("string ==> %s\n". printf("Entre com a string :"). Exemplo: /* Localizando uma substring dentro de uma string */ #include <stdio.h> #include <string.16 Localizando uma substring dentro da string Para localizar uma substring dentro da string use a função strstr( ).h e sua sintaxe é: strstr(string.h> int main() { char string[20]. printf("\n"). printf("---------------------\n"). int tamanho. a função retornará um ponteiro para a primeira letra da substring. Sua sintaxe é: *strdup(string) Exemplo: /* Duplicando uma string */ #include <stdio. Ela está no arquivo de cabeçalho string.&string).h.substring[20]. printf("cópia ==> %s\n". copia = strdup(string). .6. printf("\n"). senão retornará NULL. printf("Entre com a substring :"). printf("------------------------------------------\n"). char *extrai.15 Duplicando uma string Para duplicar uma string use a função strdup( ). scanf("%s". printf("\n"). return(0).copia).string).h> int main() { char string[20].h> #include <string.&string). char *copia. } 6. scanf("%s". printf("\n"). printf("Localizando uma substring dentro da string\n").

return(0).h> char *subs_str(char *string.substring)). char *substring.substring). } 6.\n"). extrai = strstr(string. } else printf("A string não contém a substring.tamanho).string) + contador]. int tamanho. tamanho = strlen(substring). } int main() { char string[20].h> char *sstr(char *string.substring[20].contador < tamanho. printf("\n").scanf("%s". char *nova) { char *extrai. printf("\n").&string).17 Função que remove uma substring de dentro de uma string #include <stdio. if(extrai) { for(contador = 0. extrai[contador] = NULL. return(0).tamanho2. . } else return(" "). contador++) extrai[contador] = string[(extrai . printf("A substring começa na posição %d. printf("\n"). printf("\n").substring).18 Função que substitui uma subtring por outra #include <stdio. int tamanho1. printf("Entre com a substring :").contador.\n". scanf("%s". printf("A substring tem %d caracteres. printf("Entre com a string :").h> #include <string. tamanho = strlen(substring). } 6. if(extrai) { printf("A string contém a substring.&substring).\n".extrai-string).\n").h> #include <string. return(extrai).contador. printf("substring ==> %s\n". scanf("%s".&substring). char *substring) { char *extrai.sstr(string. extrai = strstr(string.

} } int main() { char string[20].subs_str(string. printf("nova string ==> %s\n".&substring). printf("---------------------\n"). return(0).string) + contador] = nova[contador].&string).&string). printf("Entre com a nova substring :"). while(*caracter) { . scanf("%s". if(extrai) { for(contador = 0.&nova). printf("Entre com a substring :").h> int main() { char string[100].substring).substring[20]. printf("Invertendo uma string\n"). } 6. printf("\n"). else { extrai = strstr(string. scanf("%s". printf("\n").19 Invertendo uma string sem o uso da função strrev( ) /* Invertendo uma string */ #include <stdio.h> #include <string. char *caracter. scanf("%s". contador = tamanho. caracter = &string.substring. printf("Entre com a string :"). printf("\n"). tamanho = strlen(string).nova)). tamanho2 = strlen(nova).tamanho1 = strlen(substring). } else return(" "). scanf("%s". printf("\n"). printf("\n"). if((tamanho1 > tamanho2) || (tamanho2 > tamanho1)) return(" ").contador < tamanho1.invertida[100]. return(string). printf("Entre com a string :"). contador++) string[(extrai . int tamanho.contador. printf("\n").nova[20].

Ela faz parte do arquivo de cabeçalho ctype.h> int main() { char caracter. printf("Invertendo ==> %s\n\n".invertida). } 7. printf("\n").h. printf("\n").\n"). return(0). else printf("O caracter não é uma letra.\n").invertida[(contador . Sua sintaxe é: isalpha(caracter) Exemplo: /* Verificando se um caracter é uma letra * usando a macro isalpha() */ #include <stdio.h.h> int main() { char caracter.2 Verificando se o caracter é um valor ASCII Um valor ASCII é um valor entre 0 e 127. contador--.1 Verificando se o caracter é uma letra Para fazer esta verificação utilize a macro isalpha( ). *(caracter++). } 7. Para verificar se um caractere é um valor ASCII utilize a macro isascii( ) que faz parte do arquivo de cabeçalho ctype.h> #include <ctype. if (isalpha(caracter)) printf("O caracter é uma letra.h> #include <ctype. caracter = getchar(). Caracter 7.1)] = *caracter. } invertida[tamanho] = NULL. . printf("Digite um caracter :"). return(0). Sua sintaxe é: isascii(caracter) Exemplo : /* Verificando se um caracter contém um valor ASCII * usando a macro isascii() */ #include <stdio.

if (isascii(caracter)) printf("O caracter contém o valor ASCII %d. return(0)..\n".h> int main() { char caracter. . printf("\n"). } 7.h e sua sintaxe é: iscntrl(caracter) Exemplo: /* Verificando se um caracter é de controle * usando a macro iscntrl() */ #include <stdio. caracter = getchar(). printf("\n").. ^B...printf("\n").\n")... printf("\n"). ^c . printf("Digite um caracter :"). Ela pertence ao arquivo de cabeçalho ctype.h> #include <ctype. ^z). printf("Digite um caracter :"). if (iscntrl(caracter)) { printf("O caracter digitado é um caracter de controle\n"). else printf("O caracter não contém um valor ASCII. printf("e equivale ao código ASCII %d. ^Z ou ^a. } 7. printf("\n").caracter).3 Verificando se o caracter é um caracter de controle Um caracter de controle é composto pelo pressionamento da tecla control (CTRL) e uma letra ( ^A . ^C. } else printf("O caracter digitado não é um caracter de controle.\n"). return(0).. ^b. printf("\n").. Para verificar se um caractere é de controle use a macro iscntrl( )..4 Verificando se o caracter é um dígito Para verificar se o caracter é um dígito use a macro isdigit( ).\n"..h e sua sintaxe é: isdigit(caracter) Exemplo : /* Verificando se um caracter é um dígito * usando a macro isdigit() */ . Ela faz parte do arquivo de cabeçalho ctype. caracter = getchar().caracter).

\n").h> int main() { char caracter. Ela pertence ao arquivo de cabeçalho ctype. caracter = getchar().\n").\n"). printf("\n").h e sua sintaxe é: islower(caractere) Exemplo: /* Verificando se um caracter é minúsculo * usando a macro islower() */ .h> int main() { char caracter.h> #include <ctype. caracter = getchar(). printf("\n"). printf("\n").#include <stdio. printf("Digite um caracter :").\n").5 Verificando se o caracter é maiúsculo Para verificar se o caracter é maiúsculo use a macro isupper( ). if (isdigit(caracter)) printf("O caracter é um dígito. printf("\n"). Ela pertence ao arquivo de cabeçalho ctype. printf("\n"). else printf("O caracter não é um maiúsculo. return(0). printf("Digite um caracter :").h> #include <ctype. if (isupper(caracter)) printf("O caracter é maiúsculo.6 Verificando se o caracter é minúsculo Para verificar se o caracter é minúsculo use a macro islower( ). else printf("O caracter não é um dígito. } 7.h e sua sintaxe é: isupper(caractere) Exemplo: /* Verificando se um caracter é maiúsculo * usando a macro isupper() */ #include <stdio. return(0). } 7. printf("\n").

printf("\n").h> #include <ctype. Se você tiver certeza que o caractere é uma letra minúscula use a macro que é mais rápida. Se você tiver certeza que o caractere é uma letra maiúscula use a macro que é mais rápida.8 Convertendo um caracter para minúsculo Para executar esta conversão você pode usar a macro _tolower( ) ou a função tolower( ).#include <stdio. return(0). printf("Convertendo com a função toupper( ) ==> %c\n". caso contrário use a função. printf("\n").h> #include <ctype. As duas estão no arquivo de cabeçalho ctype. Assim. se o caracter não for uma letra minúscula a macro fará uma conversão errada. return(0).h> int main() { char caracter. caracter = getchar().7 Convertendo um caracter para maiúsculo Para executar esta conversão você pode usar a macro _toupper( ) ou a função toupper( ). As duas estão no arquivo de cabeçalho ctype. A diferença entre as duas é que a macro não testa se o caractere a ser convertido é um maiúsculo.toupper(caracter)). caso contrário use a função. printf("\n"). printf("Convertendo com a macro _toupper( ) ==> %c\n". printf("\n"). if (islower(caracter)) printf("O caracter é minúsculo. se o caracter não for uma letra maiúscula a macro fará uma conversão errada. printf("Digite um caracter minúsculo. A diferença entre as duas é que a macro não testa se o caractere a ser convertido é um minúsculo. Assim.\n"). um dígito ou um símbolo qualquer :")._toupper(caracter)). caracter = getchar().h. printf("\n"). printf("\n"). } 7. printf("\n"). else printf("O caracter não é um minúsculo. } 7. printf("Digite um caracter :").h.\n").h> int main() { char caracter. A sintaxe das duas segue abaixo: . A sintaxe das duas segue abaixo: _toupper(caracter) toupper(caracter) Exemplo : /* Convertendo um caracter para maiúsculo */ #include <stdio.

.. Se nada for especificado o compilador considera que será retornado um valor inteiro. printf("Convertendo com a macro _tolower( ) ==> %c\n".._tolower(caracter) tolower(caracter) Exemplo : /* Convertendo um caracter para minúsculo */ #include <stdio. Deve incluir o tipo e nome de cada variável. tipo variável2.1 Forma geral de uma função TIPO NOME(PARÂMETROS) { CORPO DA FUNÇÃO } Onde: · · · TIPO é o tipo de valor retornado pela função. printf("\n").h> int main() { char caracter. caracter = getchar(). tipo variáveln) · CORPO é onde estão as instruções da função Exemplo: int soma(int a. printf("\n"). Funções 8. NOME é o nome da função PARÂMETROS é a lista das variáveis que recebem os argumentos quando a função é chamada.. . return(0). resultado = a + b. printf("Convertendo com a função tolower( ) ==> %c\n". } 8._tolower(caracter)). assim serão destruídas após o término da função. printf("\n").h> #include <ctype..int b) { int resultado. } 8. printf("Digite um caracter maiúsculo.tolower(caracter)). Sua sintaxe é:(tipo variável1.. printf("\n").2 Variáveis em funções As variáveis criadas numa função são locais. . um dígito ou um símbolo qualquer :"). return(resultado).

} int main() { printf("\n").soma_1(nr)).h> int a = 1. exibe(). } BIZÚ: Evite variáveis globais.a).soma_1(nr)). printf("Chamando a função a primeira vez: valor + 1 = %d\n". } Caso uma variável local a função tenha o mesmo nome de uma variável global. int main() { int nr = 1. printf("a dentro de main = %d\n". /* variável local a função exibe() */ printf("a dentro da função = %d\n".valor). Exemplo: /* Entre variáveis locais e globais com o mesmo nome * dentro de uma função. printf("\n").Caso você queira manter o valor de uma variável entre as chamadas a uma função você deve declarar esta variável como static. /* variável global */ void exibe(void) { int a = 10. printf("Chamando a função pela terceira vez: : valor + 1 = %d\n". 8.soma_1(nr)). a variável local é escolhida */ #include <stdio.3 Argumentos e parâmetros . printf("Chamando a função pela segunda vez: : valor + 1 = %d\n".a). return(valor). return(0). a variável local será usada e não a global. Exemplo: /* Mantendo o valor de uma variável entre as * chamadas de uma função */ #include <stdio. return(0). valor = valor + a. printf("valor = %d\n".h> int soma_1(int a). } int soma_1(int a) { static int valor = 1.

que recebem estes argumentos... TIPO DO PARÂMETRO2. } .Argumentos são os valores usados para chamar a função e parâmetros são as variáveis.. { int resultado. b) int a. . Os parâmetros formais são os parâmetros propriamente ditos. declaradas na definição da função.. . resultado = a + b. } int main() { printf("A soma entre 5 e 2 é %d\n". } Os tipos dos argumentos devem ser compatíveis com os tipos dos parâmetros. return(resultado). . . return(resultado). TIPO PARÂMETROn) { CORPO DA FUNÇÃO } Abaixo segue um exemplo de função com os dois tipos de declaração de parâmetros. TIPO DO PARÂMETROn. /* No comando printf acima a função "soma" é chamada * com os argumentos 5 e 2 */ return(0). { CORPO DA FUNÇÃO } Já a forma moderna tem a seguinte sintaxe: TIPO NOME(TIPO PARÂMETRO1.h> int soma(int a. 8.. TIPO PARÂMETRO2. int b. A forma clássica tem a seguinte sintaxe: TIPO NOME(PARÂMETRO1. resultado = a + b. Observe o exemplo abaixo: /* Argumentos e parâmetros */ #include <stdio.2)). PARÂMETRO2. int b) /* "a" e "b" são os parâmetros da função "soma" */ { int resultado. . . /* Com declaração clássica */ int soma(a.. PARÂMETROn) TIPO DO PARÂMETRO1.. Você encontrará também referência aos parâmetros formais e paramêros reais..4 Parâmetros Existem duas formas de declaração de parâmetros em funções: a forma clássica e a forma moderna. enquanto que os parâmtros reais são os argumentos.soma(5.

printf("nr1 = %d\n". Abaixo segue um exemplo de uma chamada por valor: /* Testando a chamada por valor */ #include <stdio. em programas mais antigos você encontrará a forma clássica. nr2 = 3. int b) { a = a + 3.nr2). valor(nr1. /* Modificando o segundo argumento */ printf("Valores modificados dentro da função:\n"). } Atualmente utiliza-se a forma moderna. } . return(resultado). printf("nr2 = %d\n". /* Neste tipo de chamada são passados os argumentos * normalmente. printf("=================\n"). printf("\n\nChamando a função\n"). printf("Chamada por valor\n"). } int main() { int nr1 = 2. porém. Neste tipo de chamada os valores podem ser modificados.nr1). printf("nr1 = %d\n". resultado = a + b. printf("\n"). Utilizando esta chamada os valores dos argumentos passados não são modificados. printf("nr2 = %d\n". printf("Valores iniciais de nr1 e nr2\n"). Na verdade a função recebe uma cópia * destes argumentos */ printf("\n\nValores após a chamada da função\n"). 8.nr2). total.nr1).5 Chamada por valor e chamada por referência A chamada por valor é a passagem normal do valor dos argumentos para a função. Na realidade é passada uma cópia dos valores para a função. int b) { int resultado. printf("nr1 = %d\n".b).a).h> /* Função com chamada por valor */ int valor(int a.nr2)./* Com declaração moderna */ int soma(int a. printf("nr2 = %d\n". Na chamada por referência são passados os endereços de memória onde estão os argumentos. /* Modificando o primeiro argumento */ b = b + 2. return(0).

8. printf("Valores iniciais de nr1 e nr2\n").*a).nr1). } int main() { int nr1 = 2. printf("Chamada por referência\n"). printf("nr2 = %d\n". /* Neste tipo de chamada é passado o endereço do * argumento. printf("nr1 = %d\n". /* Modificando o primeiro argumento */ 2. printf("\n").6 Argumentos da linha de comando Caso queira. geralmente seu nome.h> /* Função com int valor(int { *a = *a + *b = *b + chamada por referência */ *a. /* Modificando o segundo argumento */ printf("Valores modificados dentro da função:\n"). printf("nr2 = %d\n". printf("nr2 = %d\n". return(0).Agora o mesmo exemplo com a chamada por referência: /* Testando a chamada por referência */ #include <stdio. argv[1] armazena o primeiro . total. char *argv[]) { printf("Olá %s. printf("======================\n"). nr2 = 3. } Os argumentos da linha de comando são argc e argv.h> int main(int argc. valor(&nr1. argv[0] armazena o nome do programa. Estes argumentos são conhecidos como argumentos da linha de comando.nr2). int *b) 3. Observe o exemplo abaixo: #include <stdio. Neste tipo de chamada os valores * podem ser modificados */ printf("\n\nValores após a chamada da função\n"). argc armazena o número de argumentos passados para o programa. Como main () é a primeira função a ser chamada quando você chama o programa os argumentos para ela são passados junto com o comando que chama o programa.argv[1]). Quando C passa uma matriz ou string para uma função é passado o endereço inicial da matriz ou função. você pode passar argumentos diretamente para a função main().&nr2).*b). inclusive o nome do programa. argv é uma matriz de strings e armazena o nome do programa e os argumentos passados.nr1). } OBSERVAÇÃO: As strings e matrizes sempre são chamadas por referência. return(0).\n".nr2). printf("nr1 = %d\n". printf("nr1 = %d\n".

taxa_juros.h> float total(float preco. float total(float preco. preco_final = preco + juros.h> void nao_retorna() { printf("Esta função não retorna nada.\n"). como mostrado acima.preco_final). Os argumentos são seprarados por um espaço. scanf("%f". Alguns compiladores ainda aceitam que main seja declarada como void caso não retorne nenhum valor.&taxa_juros). que geralmente é o sistema operacional. float taxa_juros) { float preco_final. } int main() { float preco. printf("\n"). } De acordo com o padrão ANSI. juros.argumento passado para o programa. scanf("%f". . preco_final = total(preco.2f\n\n". } int main() { nao_retorna().7 O comando return O comando return é usado para encerrar a função e retornar um valor para a função chamadora. } O valor retornado por return deve ser compatível com o tipo da função. return(0). printf("\n"). e assim por diante. return(preco_final). printf("\n"). Isto é equivalente a chamar exit com o mesmo valor. printf("Preço na etiqueta :"). a função main devolve um inteiro para o processo chamador. taxa_juros). Se uma função não retornar nenhum valor ela é do tipo void.&preco). return(0). printf("Taxa de juros :"). Isto é determinado pela colocação do tipo float antes do nome da função. o qual é definido quando da sua declaração. float taxa_juros) No exemplo. 8. argv[2] armazena o segundo argumento passado para o programa. Exemplo: #include <stdio. Exemplo: #include <stdio. printf("Total a pagar : %4. a função total retorna um valor float. juros = preco * (taxa_juros / 100). preco_final.

printf("Entre com o segundo número :"). return(resultado). /* protótipo da função */ int main() { int nr1.&nr2).nr2)). a princípio.h> int soma(int a. fatorial de 5 = 5 * 4 * 3 * 2 * 1 Se você observar com cuidado verá que: fatorial fatorial fatorial fatorial de de de de 5 4 3 2 = = = = 5 4 3 2 * * * * fatorial fatorial fatorial fatorial de de de de 4 3 2 1 Ou seja fatorial de um número = número * (fatorial de número . scanf("%d".8 Protótipo de função A chamada a uma função deve vir. printf("Entre com o primeiro número :"). } 8. return(0). int b) /* função propriamente dita */ { int resultado. scanf("%d". resultado = a + b. } int soma(int a.nr2. Para isso declare apenas um protótipo da função. nr2. Porém. Uma função que chama a ela mesma é chamada função recursiva.nr1.h> int fatorial(nr) { int resposta. O exemplo padrão de função recursiva é uma função que calcula o fatorial de um número.9 Recursão Recursão é o ato de uma função chamar ela mesma. O fatorial de um número é igual ao produto dos números inteiros de 1 até o número. if(nr == 1) . int b).8.soma(nr1. após sua definição para o compilador conhecer os tipos de parâmetros e o tipo de retorno da função. Observe o exemplo abaixo: #include <stdio.1) Desta conclusão podemos escrever nosso exemplo de função recursiva: /* Exemplo de função recursiva */ #include <stdio.&nr1). printf("\n%d + %d = %d\n\n". o qual tem apenas o valor de retorno e os parâmetros da função. você pode chamar a função antes da definição desta.

&a).return(1). caracter = getchar(). Abaixo segue um exemplo da utilização de getchar: /* Exemplo da utilização de getchar */ #include <stdio. return(0).h. return(0). printf("\n"). return(resposta).caracter). } 9.2 Exibindo um caracter Para exibir um caracter você pode usar a função putchar( ) que está no arquivo de cabeçalho stdio. Caso ocorra um erro. Sua sintaxe é: . printf("O fatorial de %d é %d\n\n". scanf("%d".h. Ela faz parte do arquivo de cabeçalho stdio. 9. } int main() { int a. Esta função retorna o valor inteiro referente ao código ASCII do caractere lido. printf("\n"). printf("--------------------\n"). } A recursão sempre deve ser evitada basicamente por dois fatores. resposta = nr * fatorial(nr-1). printf("\nVocê digitou o caracter %c\n\n". Segundo que as funções recursivas são mais lentas que suas correspondentes não recursivas.h> int main() { char caracter.1 Lendo um caracter do teclado Para ler um caracter do teclado utilize a função getchar( ). Normalmente uma função recursiva também pode ser escrita com laços de repetição tipo for ou while de modo a remover a recursão. Sua utilização é: variavel = getchar(). porém você pode atribuir este valor a uma variável do tipo caracter.fatorial(a)). Primeiro que uma função recursiva é difícil de compreender. E/S (Entrada/Saída) 9. ela retorna EOF. printf("Entre com um caracter :").a. printf("\nEntre com um valor inteiro :"). printf("Utilizando getchar()\n").

porém você pode passar variavel como um caracter. printf("\n").putchar(variavel) Onde variavel é um número inteiro.h> int main() . return(0). putchar retorna o caracter exibido ou EOF. ela é extremamente perigosa de usar.h. e porque gets() vai continuar a guardar caracteres ultrapassado o fim do 'buffer'.TAMANHO. para ler do teclado o valor padrão para isto é stdin Exemplo do uso de fgets: /* usando fgets para ler uma string do teclado */ #include <stdio. caso ocorra algum erro. Este comportamento tem sido utilizado para quebrar a segurança de computadores. Use fgets() no seu lugar.h> int main() { char caracter. printf("\n"). printf("Utilizando putchar()\n"). printf("\n\n"). printf("--------------------\n"). caracter = getchar(). onde: · · · STRING é a variável onde a string será armazenada TAMANHO é o tamanho máximo da string STREAM é de onde os caracteres serão lidos.3 Lendo uma string do teclado Você pode ler uma string do teclado usando as funções gets( ) e fgets(). putchar(caracter). O gcc desencoraja o uso de gets . quantos caracteres gets() vai ler. printf("Entre com um caracter :"). Elas fazem parte do arquivo de cabeçalho stdio. Exemplo: /* Exemplo da utilização de putchar */ #include <stdio. } 9. que é a seguinte: fgets(STRING. Porque é impossível saber. sem conhecer antecipada mente os dados. A própria man page de gets declara o seguinte em sua seção PROBLEMAS : PROBLEMAS Nunca use gets(). printf("\nExibindo o caracter com putchar => ").STREAM). Por isso que só abordarei a sintaxe de fgets.

stdin). } 9.h> int main() { char string[30]. printf("Digite uma string :"). fgets(frase. Exemplo: #include <stdio. printf("\n").30. printf("---------------------------------------------\n").frase). fgets(string.string). printf("\n\n"). puts(string). Elas fazem parte do arquivo de cabeçalho stdio. printf("Exemplo do uso de printf para exibir strings\n").4 Exibindo uma string Você pode exibir uma string usando a função printf ou a função puts( ).stdin).50. } A sintaxe de puts é: puts(string) Exemplo: #include <stdio. return(0). return(0). printf("%s". printf("\n"). printf("A string digitada foi :%s".h. printf("Digite uma string :").{ char frase[50].30. printf("Exemplo do uso de puts\n"). printf("Digite uma frase qualquer:"). printf("%s\n".STRING). fgets(string.h> int main() { char string[30]. printf("\n\n"). printf("----------------------\n"). printf("\n").stdin). printf("\n"). printf("\n"). printf("Exibindo\n\n").string). . A sintaxe de printf para a exibir uma string é. printf("\n"). printf("A string digitada foi :".

qde. printf("\n").total. printf("Preço :"). Observe que o valor entrado é passado para o endereço da variável. printf faz parte do arquivo de cabeçalho stdio.preco. float preco.6 Entrada formatada (scanf) A entrada formatada é feita utilizando a função scanf. printf("\n"). printf("Produto :").2f\n\n".h e sua sintaxe é: abs(número) Exemplo do uso da função abs: #include <stdio. printf("%s\t%.return(0).5 Saída formatada (printf) A saída formatada é feita utilizando a função printf vista anteriormente. Sua sintaxe é: scanf("especificador de formato". printf("\n").produto.&variável) O especificador de formato segue a mesma sintaxe da função printf. } 10.1 Obtendo o valor absoluto de um número inteiro Para obter o valor absoluto de um número inteiro use a função abs( ).h 9.Ela faz parte do arquivo de cabeçalho stdio. scanf("%s". No caso de leitura de uma string não há necessidade do operador &.h> int main() { int qde.h> int main() . return(0). } 9.&qde).produto).h. char produto[20]. printf("Produto\tPreço\tQde\tTotal\n").&preco). Funções matemáticas 10. já que o nome de uma string sem o índice é entendido pela linguagem C como um ponteiro para o início da string. scanf("%f". printf("\n").qde*preco).2f\t%d\t%. Abaixo segue um exemplo do uso de scanf: # include<stdio. Ela faz parte do arquivo de cabaçalho stdlib. scanf("%d". printf("Quantidade :").

co-seno e tangente hiperbólicos.3 Gerando números aleatórios Para gerar números aleatórios alguns compiladores possuem em seu arquivo de cabeçalho stdlib. Para maiores detalhes dê uma estudada no arquivo de cabeçalho referente na biblioteca de seu compilador. Todas recebem e retornam um valor double.abs(nr2)). arco co-seno e arco tangente e: sinh(angulo) cosh(angulo) tanh(angulo) Para o cálculo do seno. co-seno e tangenge de angulo. printf("nr2=%d\tabs(nr2)=%d\n\n".nr1. printf("nr1=%d\tabs(nr1)=%d\n".h. Sua sintaxe é: random(número) Já a função rand gera um número aleatório entre zero e RAND_MAX que é definido no próprio arquivo stdlib.h. printf("\n"). A função random gera um número aleatório entre zero e um número inteiro passado como argumento.nr2.nr2 = -7. 10.h (ou math. } 10.{ int nr1 = 5. Além destas devem ser encontradas as funções: asin(angulo) acos(angulo) atan(angulo) Para o cálculo de arco seno. return(0).2 Funções trigonométricas O arquivo de cabeçalho tgmath. dependendo do seu compilador) fornece as seguintes funções trigonométricas: sin(angulo) cos(angulo) tan(angulo) Estas calculam o seno.abs(nr1)).h as funções random( ) e rand( ). A sintaxe de rand é: rand( ) Abaixo segue um exemplo do uso destas funções: /* gerando números aleatórios */ . O argumento angulo passado para as funções é especificado em radianos.

h> #include <stdlib. ao executar o programa acima várias vezes.h> int main() { int contador.h> int main() { int contador. contador++) printf("%d\n".random(10)). for(contador=1. printf("Gerando 5 números aleatórios com rand\n").random(10)). random e rand RAND_MAX. geram números aleatórios entre zero e . inicia o gerador de números aleatórios usando o relógio do computador para produzir uma semente aleatória e srand( ) lhe permite especificar o valor inicial do gerador de números aleatórios. você verá que ele sempre gera os mesmos números aleatórios. for(contador=1. printf("Gerando 5 números aleatórios com random\n"). aparentemente tem a mesma função.rand()).contador <= 5.contador <= 5. Sua sintaxe é: randomize srand(número) Veja como fica nosso exemplo inicial usando randomize para iniciar o gerador de números aleatórios: /* gerando números aleatórios */ #include <stdio. } Até aqui tudo bem. ou seja.contador <= 5.rand()). Para resolver isso basta utilizar as funções randomize( ) e srand( ) que iniciam o gerador de números aleatórios. contador++) printf("%d\n". printf("Gerando 5 números aleatórios com random\n"). return(0). contador++) printf("%d\n". Porém ao utilizar este código no gcc obtive uma mensagem de erro dizendo que a função random tinha muitos argumentos.contador <= 5. } Porém. for(contador=1. Dei uma olhada no arquivo de cabeçalho stdlib. contador++) printf("%d\n".h e vi que neste compilador as coisas funcionam de maneira um pouco diferente.#include <stdio. printf("Gerando 5 números aleatórios com rand\n"). for(contador=1. randomize().h> #include <stdlib. return(0).

h */ int main() { int contador. contador++) printf("%d\n". for(contador=1. a função srandom existe.rand()/100000000).random()/100000000). printf("Gerando 5 números aleatórios com rand\n"). Assim eu dividi o resultado de random por 100000000 e consegui alguns aleatórios com dois dígitos: RAND_MAX /* gerando números aleatórios no gcc */ #include <stdio.h> #include <stdlib. return(0).h */ int main() { int contador. printf("Gerando 5 números aleatórios com random\n").rand()/100000000).1 Introdução .contador <= 5.h> #include <stdlib. for(contador=1. printf("Gerando 5 números aleatórios com rand\n"). return(0). for(contador=1. contador++) printf("%d\n". } Para iniciar o gerador de números aleatórios a função randomize não existe. contador++) printf("%d\n".contador <= 5. /* iniciando o gerador de números aleatórios */ printf("Gerando 5 números aleatórios com random\n"). for(contador=1.contador <= 5. O código anterior ficou assim: /* gerando números aleatórios no gcc */ #include <stdio. srandom(time(NULL)). porém.contador <= 5. Então eu a utilizei juntamente com a função time e consegui gerar números aleatórios diferentes a cada execução do programa.h> /* random() gera um long int entre 0 e RAND_MAX = 2147483647 * * RAND_MAX é definido em stdlib.random()/100000000). } 11. contador++) printf("%d\n". Arquivos 11.é definido como igual a 2147483647.h> /* random() gera um long int entre 0 e RAND_MAX = 2147483647 * * RAND_MAX é definido em stdlib.

abrí-lo inicializa o indicador de posição apontando para o começo do arquivo. um arquivo em disco pode suportar acesso aleatório enquanto um teclado não. Se um arquivo aberto para saída por fechado. a função que manipula uma stream pode escrever tanto em um arquivo no disco quanto em algum outro dispositivo. Existem dois tipos de streams: de texto e binária. a quantidade de caracteres pode não ser a mesma.O sistema de E/S de C utiliza o conceito de streams e arquivos. Você associa um arquivo a uma stream através de uma operação de abertura. mas não todos os arquivos. Por exemplo. O número de bytes é o mesmo do dispositivo.h 11. Uma stream é um dispositivo lógico que representa um arquivo ou dispositivo. A stream associa o arquivo a uma estrutura do tipo FILE.2 Funções utilizadas para manipulação de arquivos As principais funções para manipulação de arquivos são: FUNÇÃO fopen( ) FINALIDADE Abrir um arquivo fclose( ) Fechar um arquivo putc( ) Escrever um caracter em um arquivo Idem putc( ) Ler um caracter de um arquivo fputc( ) getc( ) . não ocorre nenhuma tradução de caracteres. Por exemplo. A stream binária é uma sequência de bytes com uma correspondência de um para um com os bytes encontrados no dispositivo externo. desde um arquivo em disco até um terminal ou uma impressora. como o monitor. Esse processo é geralmente chamado de descarga (flushing) da stream e garante que nenhuma informação seja acidentalmente deixada no buffer de disco. Do que foi até aqui exposto concluímos que todas as streams são iguais. isto é. o conteúdo de sua stream será escrito no dispositivo externo. um caracter de nova linha pode ser convertido para os caracteres retorno de carro e alimentação de linha. A stream é independente do arquivo ou dispositivo. Se o arquivo suporta acesso aleatório. Para utilizar um arquivo você deve associá-lo a uma stream e. manipular a stream. Nem todos os arquivos tem os mesmos recursos. o indicador de posição é incrementado. então. Devido a isso pode não haver uma correspondência entre os caracteres da stream e do dispositivo externo. Um arquivo é desassociado de uma stream através de uma operação de fechamento. Em uma stream de texto podem ocorrer certas traduções de acordo com o sistema hospedeiro. Um arquivo é interpretado pela linguagem C como qualquer dispositivo. Esta estrutura é definida no arquivo de cabeçalho stdio. Devido a isso. Quando cada caracter é lido ou escrito no arquivo.

fgetc( ) Idem getc( ) Posicionar o ponteiro de arquivo num byte específico É para o arquivo o que printf é para o console fseek( ) fprintf( ) fscanf( ) É para o arquivo o que scanf é para o console feof( ) Devolve verdadeiro se o fim do arquivo foi atingido ferror( ) Devolve verdadeiro se ocorreu um erro rewind( ) Posicionar o ponteiro de arquivo no início deste remove( ) Apagar um arquivo fflush( ) Descarregar um arquivo Todas estas funções estão no arquivo de cabeçalho stdio. SEEK_CUR e SEEK_END. fpos_t e FILE.3 O ponteiro de arquivo Basicamente um ponteiro de arquivo identifica um arquivo específico e é usado pela stream para direcionar as operações das funções de E/S. SEEK_SET. 11. Este arquivo de cabeçalho define três tipos: size_t. Para ler ou escrever em arquivos seu programa precisa usar os poteiros de arquivo. EOF geralmente é definida como -1 e devolve este valor quando uma função de entrada tenta ler além do final do arquivo. SEEK_CUR e SEEK_END são usadas com a função fssek( ) para o acesso aleatório a um arquivo. EOF. SEEK_SET. NULL define um ponteiro nulo.4 Abrindo um arquivo . As importantes para a manipulação de arquivos são: NULL. Este arquivo de cabeçalho também define várias macros. Normalmente ela é definida no arquivo de cabeçalho stdio. Para declarar uma variável como ponteiro de arquivo use a seguinte sintaxe: FILE *arquivo. Um ponteiro de arquivo é uma variável ponteiro do tipo FILE. Os dois primeiros são o mesmo que unsigned e o terceiro é discutido mais abaixo. mas isso depende do seu compilador.h. FOPEN_MAX define um valor inteiro que determina o número de arquivos que podem ser abertos ao mesmo tempo. FOPEN_MAX. 11.h. Esta variável é um tipo pré-definido pela linguagem C.

Se um arquivo com o mesmo nome existir. MODO é uma string que representa como o arquivo será aberto de acordo com a tabela abaixo: MODO r COMO O ARQUIVO SERÁ ABERTO Abre um arquivo texto para leitura. Abre um arquivo texto para anexação. Se o arquivo não existir. ou seja. será criado. . Para abrir uma stream e associá-la a um arquivo você usa a função fopen( ) . w a rb wb ab r+ w+ a+ r+b w+b a+b rb+ wb+ ab+ Abre um arquivo texto para leitura/escrita.cuja sintaxe é: fopen(ARQUIVO. algo como "C:\docs\arquivo. Se o arquivo não existir. será criado.MODO) Onde ARQUIVO é um ponteiro para uma string que representa o nome do arquivo. Se o arquivo não existir. a sequência de caracteres retorno de carro/alimentação de linha são traduzidas para nova linha na entrada. será sobrescrito. Abre um arquivo binário para leitura/escrita. Na saída ocorre o inverso: caracteres de nova linha são convertidos em retorno de carro/alimentação de linha. Para abrir um arquivo texto chamado "teste" para escrita você poderia escrever assim: FILE *arquivo. será sobrescrito. arquivo = fopen("teste". no modo texto. É importante lembrar que em muitas implementações. Abre um arquivo binário para anexação. Abre um arquivo texto para escrita.Apesar do sistema de E/S de C considerar arquivo como qualquer dispositivo. será criado.txt" no linux. consideraremos arquivo como um arquivo em disco. Se um arquivo com o mesmo nome existir. Abre um arquivo binário para escrita. será criado. caso ocorra algum problema ela devolve NULL. no windows. Se o arquivo não existir. Abre um arquivo binário para leitura. a função fopen devolve um ponteiro de arquivo. Na prática é o nome do arquivo propriamente dito e pode ser um PATH. Caso tudo corra bem. para os conceitos apresentados daqui pra frente.txt"."w"). Em arquivos binários não ocorre nenhuma tradução. ou algo como "/home/samu/arquivo.

arquivos destruídos e erros intermitentes em seu programa.5 Fechando um arquivo Para fechar uma stream você deve usar a função fclose( ). normalmente definida em stdio. Sua sintaxe é: . Existem as duas para preservar a compatibilidade com versões mais antigas do C. O número máximo de arquivos que pode ser aberto ao mesmo tempo é definido pela macro FOPEN_MAX. Caso o fechamento do arquivo ocorra sem problemas. 11. fclose também libera o bloco de controle de arquivo associado à stream deixando-o disponível para reutilização. você deve usar um código parecido com este: FILE *arquivo. sempre que for abrir um arquivo. Uma falha ao fechar uma stream pode provocar problemas tipo perda de dados. Ela escreve qualquer dado que ainda permanece no buffer de disco no arquivo e o fecha em nível de sistema operacional. Elas são identicas."w")) == NULL) { printf("Erro ao abrir arquivo!!!\n"). É lógico que para escrever num arquivo este deve ter sido aberto num modo que permita a escrita.ARQUIVO). Onde ARQUIVO é o ponteiro de arquivo devolvido por fopen quando esta abriu o arquivo. Erros possíveis são floppy drive sem disquete ou disco cheio. 11. A sintaxe de fclose é: fclose(ARQUIVO). exit(1). if((arquivo = fopen("teste". Existem duas também pelo motivo da compatibilidade com versões mais antigas da linguagem C. é recomendável sempre testar se o arquivo foi aberto sem problemas. Onde CARACTER é o caracter a ser escrito no arquivo e ARQUIVO é um ponteiro de arquivo. Como. a função retorna o caracter escrito. caso contrário ela retorna EOF. normalmente. você deve fechar um arquivo antes de abrir outro. Sua sintaxe é: putc(CARACTER. há um limite do sistema operacional para o número de arquivos abertos ao mesmo tempo. Assim.Porém. fclose retorna zero. Veremos getc( ).6 Escrevendo e lendo caracteres Para escrever um caracter num arquivo aberto você pode usar duas funções: putc( ) ou fputc( ). O arquivo deve ter sido aberto num modo que permita a leitura. Confira se é o caso do seu compilador. } Este tipo de teste detectará algum problema tipo disco cheio ou protegido contra gravação antes que seu programa tente gravar nele. Veremos putc( ). Qualquer outro valor indica erro.h. Se ocorrer tudo bem. Para ler um caracter temos também duas funções: getc( ) e fgetc( ).

putchar(caracter). } printf("\n%s\n\n". Onde ARQUIVO é um ponteiro de arquivo. }. Sendo caracter uma variável char e arquivo uma variável ponteiro para uma estrutura FILE. } while(caracter != EOF). Um bom exercício é reescrever este código de modo que este caracter não seja exibido. exit(1).getc(ARQUIVO). printf("\n\n")."r")) == NULL) { printf("Erro ao abrir arquivo!!!\n\n"). 11. } Observe que este código exibe também o caracter EOF. fclose(arquivo).8 Programa que escreve caracteres num arquivo . exit(1). do { caracter = getc(arquivo). É importante observar que getc também devolve EOF caso ocorra algum erro.7 Programa que lê e exibe o conteúdo de um arquivo texto /* lendo e exibindo o conteúdo de um arquivo texto */ #include <stdio. char *argv[]) { char caracter. if((arquivo = fopen(argv[1].h> int main(int argc. } while(caracter != EOF). 11. if(argc < 2) { printf("\nErro: Digite o nome do arquivo !!!\n\n"). return(0). Quando o final do arquivo é alcançado a função devolve EOF. FILE *arquivo. Para ler o conteúdo de um arquivo você poderia usar um trecho de código parecido com: do { caracter = getc(arquivo).argv[1]).

Para ler um arquivo binário você poderia usar o seguinte trecho de código: while(!feof(arquivo)) caracter = getc(arquivo).argv[1])."w")) == NULL) { printf("Erro ao abrir arquivo!!!\n\n"). exit(1).*copia. putc(caracter. 11. Esta função faz parte de stdio. return(0).10 Programa que copia arquivo /* programa que copia arquivo */ #include <stdio. } if((arquivo = fopen(argv[1]. Ela tem a seguinte sintaxe: feof(ARQUIVO). printf("\nGravado com sucesso em %s\n\n". } while(caracter != '$'). } 11. if(argc < 2) { printf("\nErro: Digite o nome do arquivo !!!\n\n")./* escrevendo caracteres num arquivo */ #include <stdio. Isso poderia fazer com que fosse indicado o fim de arquivo antes deste ter chegado. } do { caracter = getchar(). char *argv[]) { FILE *arquivo. caso contrário ela devolve 0.h> int main(int argc. fclose(arquivo). Para resolver este problema C inclui a função feof( ) que determina quando o final de um arquivo foi atingido. char caracter. onde ARQUIVO é um ponteiro de arquivo. exit(1).9 Verificando o final de um arquivo binário Quando manipulando dados binários um valor inteiro igual a EOF pode ser lido por engano. char *argv[]) { FILE *original.h e devolve verdadeiro caso o final de arquivo seja atingido. char caracter.arquivo). if(argc < 3) .h> int main(int argc.

"rb")) == NULL) { printf("\nErro ao abrir o arquivo original. } fclose(original). Caso ocorra algum erro esta função retorna EOF.\n\n"). retornará um ponteiro nulo.ARQUIVO).ARQUIVO). printf("copiar ARQUIVO_ORIGEM ARQUIVO_DESTINO\n\n"). } while(!feof(original)) { caracter = getc(original). cujos protótipos encontramse em stdio. fgets( ) lê uma string da stream especificada.11 Escrevendo e lendo strings Para escrever e ler strings em um arquivo use as funções fputs( ) e fgets( ).\n\n"). fclose(copia). } if((copia = fopen(argv[2]. }. if((original = fopen(argv[1]. A string resultante terminará em nulo. sua sintaxe é: fputs(STRING. fputs( ) escreve uma string na stream especificada.TAMANHO.argv[1]. return(0).{ printf("\nSintaxe correta:\n\n"). exit(1). . onde ARQUIVO é um ponteiro de arquivo. caso contrário. exit(1). printf("\nO nome do arquivo original não pode ser igual ao da\ cópia. Ela lê STRING até que um caractere de nova linha seja lido ou que TAMANHO .argv[2]).\n\n").\n\n". } while(argv[1]) { if(*argv[1] == *argv[2]) break.h. } 11. Caso ocorra tudo bem esta função retornará um ponteiro para STRING. printf("\n%s copiado com sucesso com o nome de %s."wb")) == NULL) { printf("\nErro ao abrir o arquivo cópia. Sua sintaxe é: fgets(STRING. if(!feof(original)) putc(caracter. exit(1).copia). exit(1). Se uma nova linha é lida ela será parte da string.1 caracteres tenham sido lidos.

char *argv[]) { char string[80].arquivo). if(argc < 2) { printf("\nErro: Digite o nome do arquivo !!!\n\n"). fputs(string. sendo ARQUIVO um ponteiro de arquivo.h> #include <string. posteriormente. Sua sintaxe é: rewind(ARQUIVO). exit(1). FILE *arquivo. */ #include <stdio. 11.12 Programa que escreve strings num arquivo /* Programa que escreve strings num arquivo. cujo protótipo está no arquivo de cabeçalho stdio. .h.h e sua sintaxe é: ferror(ARQUIVO). strcat(string.14 Verificando se a operação com o arquivo produziu um erro Para determinar se uma operação com o arquivo produziu um erro use a função ferror( ). exit(1). * é adicionado um antes da string ser gravada no arquivo. } do { gets(string). } 11. } if((arquivo = fopen(argv[1]. * * Como gets() não armazena o caractere de nova linha.13 Apontando para o início do arquivo Para apontar para o início do arquivo use a função rewind( )."w")) == NULL) { printf("Erro ao abrir arquivo!!!\n\n"). * * Para encerrar o programa o usuário deverá inserir uma * linha em branco. * com fgets() já que esta função lê a string até que seja * encontrado um caracter de nova linha. return(0)."\n").11. * Isto é feito para que a string possa ser lida. Seu protótipo está em stdio.h> int main(int argc. fclose(arquivo). } while(*string != '\n').

exit(1). NOVO_NOME). } else printf("Arquivo apagado com sucesso. if(toupper(*opcao) == 'S') if(remove(argv[1])) { printf("Erro ao tentar apagar arquivo. if(argc != 2) { printf("Erro !!! \n"). Se a função for bem sucedida ela retornará zero. caso contrário.sendo ARQUIVO um ponteiro de arquivo. caso contrário retorna falso. Basta incluir a nova localização como parte do NOVO_NOME do arquivo. Esta mesma função serve para mover um arquivo.\n"). gets(opcao). 11.h> . Esta função retorna verdadeiro se ocorreu um erro durante a última operação com o arquivo. Ela faz parte de stdio. Como cada operação modifica a condição de erro.h e sua sintaxe é: remove(ARQUIVO). } printf("Deseja realmente apagar o arquivo %s (S/N)?". onde NOME_ANTIGO e NOVO_NOME são ponteiros string. return(0).\n").h> #include <ctype. printf("Sintaxe correta: apagar ARQUIVO\n").char *argv[]) { FILE * arquivo. Ela está em stdio. char opcao[5].argv[1]).h> int main(int argc. Observe o exemplo abaixo: /* renomeando ou movendo um arquivo */ #include <stdio.15 Apagando um arquivo Para apagar uma arquivo use a função remove( ). exit(1). sendo ARQUIVO um ponteiro de arquivo. ela deve ser chamada logo após cada operação realizada com o arquivo. } 11. Exemplo: /* Apagando um arquivo */ #include <stdio. retornará um valor diferente de zero.h e sua sintaxe é: rename(NOME_ANTIGO.16 Renomeando ou Movendo um arquivo Para renomear um arquivo use a função rename( ).

11.ARQUIVO). } Este programa renomeia um arquivo. printf("Sintaxe correta: renomear NOME_ANTIGO NOVO_NOME\n").TAMANHO. será movido.h. sendo ARQUIVO um ponteiro de arquivo. Se tudo ocorrer bem fflush retornará zero.17 Esvaziando uma stream Para esvaziar o conteúdo de uma stream aberta para saída use a função fflush( ). A sintaxe de fread( ) é: fread(VARIÁVEL. mostrando que teste123 foi movido e renomeado. } if(rename(argv[1]. digite o seguinte comando: $ renomear teste teste123 liste o conteúdo do diretório e você verá que o arquivo foi renomeado. Crie um arquivo chamado teste em seu diretório de usuário e. se você especificar um outro local para o novo nome do arquivo. Ela escreve o conteudo do buffer para o arquivo passado como argumento. Elas são definidas em stdio. mas em lixo foi criado o arquivo teste456. Para calcular isso você deve usar o operador sizeof QUANTIDADE indica quantos itens serão lidos (cada item do tamanho de TAMANHO) . Agora crie um diretório chamado lixo e digite o comando: $ renomear teste123 lixo/teste456 dê uma checada e você verá que o arquivo teste123 não existe mais no diretório atual.char *argv[]) { if(argc != 3) { printf("Erro !!! \n").18 Escrevendo e lendo tipos de dados definidos pelo usuário Veremos mais a frente que C permite que o usuário crie seus próprios tipos de daos. Porém. após compilar o exemplo acima com o nome de renomear. return(0). Sua sintaxe é: fflush(ARQUIVO). exit(1). devolverá EOF. 11.int main(int argc.QUANTIDADE. indicando sucesso. Este tipos de dados são estruturas compostas de tipos de dados simples e com estas estruturas podemos construir registros. este. Para escrever e ler estas estruturas podemos usar as funções fread( ) e fwrite( ). onde: · · · VARIÁVEL é o endereço da variável que receberá os dados lidos do arquivo TAMANHO é o número de bytes a ser lido. todos os arquivos abertos para saída serão descarregados. além de ser renomeado.argv[2])) printf("Erro ao renomear arquivo!\n"). Se for passado um valor nulo. Caso contrário.

Vamos escrever alguns dados num arquivo.arquivo).sizeof(idade). float altura. return(0). /* Usando fwrite para escrever dados num arquivo */ #include <stdio. .dat". } fwrite(&nome.arquivo).1. fread(&idade.sizeof(altura). exit(1).sizeof(altura). fclose(arquivo).arquivo). O ponteiro de arquivo "ARQUIVO" deve ser aberto em modo binário. int idade=34. fwrite(&altura. } fread(&nome. } Agora veremos um exemplo com o uso de fread que lerá o arquivo "samu.dat" criado no exemplo acima: /* Usando fread para ler dados de um arquivo */ #include <stdio. com a exceção que VARIÁVEL é o endereço da variável com os dados a serem escritos no arquivo. Esse valor poderá ser menor que QUANTIDADE se o final do arquivo for atingido ou ocorrer um erro. if((arquivo = fopen("samu. fwrite(&idade. Esse valor será igual a QUANTIDADE a menos que ocorra um erro. exit(1)."wb")) == NULL) { printf("Erro ao abrir arquivo!!!\n\n"). fread fwrite devolve o número de itens escritos. char nome[5]="samu".sizeof(nome).1. if((arquivo = fopen("samu. int idade.1.h> int main() { FILE *arquivo.arquivo).h> int main() { FILE *arquivo.arquivo)."rb")) == NULL) { printf("Erro ao abrir arquivo!!!\n\n").dat".82. fread(&altura. para podermos ler e escrever qualquer tipo de informação.arquivo).1.sizeof(nome). Abaixo segue um exemplo do uso de fwrite. Também deve ser aberto de acordo com a operação a ser feita (leitura ou escrita). devolve o número de itens lidos. char nome[5].1.· ARQUIVO é um ponteiro para o arquivo aberto anteriormente A sintaxe para fwrite( ) é idêntica.1. float altura=1.sizeof(idade).

é interessante.sizeof(nome). 11.arquivo) != 1) printf("Erro de leitura.. printf("idade : %d\n".1. Isto pode ser feito com o uso da função fseek( ). Por exemplo.19 Apontando para uma posição específica dentro do arquivo Você pode apontar para um byte específico dentro do arquivo movimentando o indicador de posição. autor. return(0).nome). deve ser usado em conjunto com sizeof para que possamos acessar os tipos de dados prédefinidos. onde ARQUIVO é um ponteiro de arquivo aberto para onde são direcionados os resultados das funções.VARIÁVEL). em programas maiores. NÚMERO_DE_BYTES. fclose(arquivo). onde ARQUIVO é um ponteiro de arquivo aberto anteriormente. fscanf(ARQUIVO.cuja sintaxe é: fseek(ARQUIVO. editora.h.."ESPECIFICADOR". printf("altura: %. Se quisermos apontar o indicador de posição para o quinto registro deste arquivo deveremos usar algo como: NÚMERO_DE_BYTES fseek(arquivo. } Embora não tenha sido feito nestes dois exemplos. 11. ORIGEM)."ESPECIFICADOR".\n"). Abaixo segue um exemplo do uso destas funções: /* exemplo do uso de fscanf e fprintf * este programa lê uma string do teclado e a escreve num arquivo texto .VARIÁVEL).2f\n". a análise do retorno de fread e fwrite para ver se não ocorreram erros. Abaixo você pode ver a sintaxe destas funções: fprintf(ARQUIVO. NÚMERO_DE_BYTES é a quantidade de bytes que o indicador de posição será movimentado e ORIGEM é a partir de onde o movimento do indicador de posição iniciará.20 Entrada e saída formatadas direcionadas para arquivos Existem as funções fprintf( ) e fscanf( ) que são semelhantes a printf e a scanf mas que direcionam os dados para arquivos. Isto pode ser feito com uma instrução deste tipo: if(fread(&nome. e escrevemos vários dados em um arquivo. digamos que criamos um tipo de dado chamado "ficha".4*sizeof(struct ficha).idade).SEEK_SET). etc. onde armazenamos os dados de um livro como título.altura).printf("nome : %s\n". ORIGEM deve ser uma das seguintes macros: SEEK_SET para a origem no início do arquivo SEEK_CUR para a origem na posição atual do indicador de posição SEEK_END para a origem no final do arquivo estas macros estão definidas em stdio.

printf("Digite uma string\n\n"). Estas streams são ponteiros de arquivos e podem ser redirecionadas. if((arquivo = fopen("adtexto.21 Streams padrão Quando um programa em linguagem C é iniciado são abertas três streams: stdin. } printf("Exemplo do uso de fscanf e fprintf\n"). /* lê string do teclado */ onde o programa leu a variável string do teclado através da streams padrão stdin.string).1 Introdução as matrizes Uma matriz é uma estrutura de dados que pode armazenar vários valores do mesmo tipo. nas funções que você utiliza ponteiros de arquivos para entrada e saída de dados você pode muito bem usar estas streams de modo ao seu programa receber dados do teclado e escrever no monitor."%s". normalmente o monitor.string). 11. exit(1). estas funções devem ser evitadas pois trabalham com dados ASCII e não binários o que ocasiona uma perda de desempenho no programa. fscanf(stdin. /* escreve string no arquivo */ fclose(arquivo). normalmente o teclado. .txt". do mesmo jeito que foram criadas."%s". stdout e stderr. char string[80].string). stderr define a saída padrão dos erros. Porém esteja consciente que estas streams não são variáveis e não podem receber um valor.* compilado com o nome de adtexto */ #include <stdio. Isto foi mostrado no exemplo da seção anterior na linha. É preferível o uso de fread e fwrite. } Embora sejam uma opção atraente para ler e escrever dados em arquivos. /* lê string do teclado */ fprintf(arquivo. você não pode abrí-las com fopen. você não deve nunca tentar abrí-las ou fechá-las. Ou seja. Matrizes 12. 12."w")) == NULL) { printf("Erro ao abrir o arquivo!\n"). stdout define a saída padrão do sistema. return(0). stdin define a entrada padrão do sistema."%s". Assim.h> int main() { FILE *arquivo. Quando o programa é encerrado estas streams são fechadas automaticamente. normalmente também é o monitor. fscanf(stdin.

printf("O segundo elemento tem o valor %d\n".notas[0]). Assim.68}.contador++) printf("O %do elemento tem o valor %d\n". Todos os dados colocados na matriz devem ser deste tipo. printf("Analisando os elementos da matriz notas\n"). onde TIPO é o tipo dos dados que serão armazenados na matriz. As strings manipuladas em C são matrizes de caracteres. /* esta matriz pode armazenar até 30 valores do tipo float */ Os valores armazenados na matriz são chamados de "elementos da matriz".68}.35. printf("Analisando os elementos da matriz notas\n"). para nossa matriz nota. printf("O quarto elemento tem o valor %d\n".notas[contador]). /* esta matriz pode armazenar até 50 valores do tipo int */ float nota[30].h> .50.35.notas[2]).70.68}.h> int main() { int notas[5] = {60. #include <stdio. Para melhorar o entendimento observe o código abaixo: #include <stdio. Este nome identificará a matriz no código do programa.notas[4]). o primeiro elemento é nota[0] e o último elemento é nota[29]. Observe abaixo.contador < 5. for(contador = 0. mostrada no exemplo acima. Você pode inicializar os elementos de uma matriz na sua declaração usando a sintaxe: int notas[5] = {60. return(0). e assim por diante. return(0). O primeiro elemento da matriz é indexado como item zero e o último é indexado como QUANTIDADE menos 1. Exemplos: int nr_de_livros[50]. o elemento 1 receberá o valor 70. E QUANTIDADE é a quantidade máxima de itens a ser armazenados. printf("O terceiro elemento tem o valor %d\n". printf("O primeiro elemento tem o valor %d\n". NOME é o nome a ser dado a matriz.contador+1.70. } Este código pode ser otimizado usando um laço for e uma variável para manipular os elementos da matriz.notas[1]). } Uma das matrizes mais comuns utilizadas em C é a matriz de caracteres. No exemplo acima o elemento zero da matriz notas receberá o valor 60.70. printf("O quinto e último elemento tem o valor %d\n".A sintaxe para declarar uma matriz é: TIPO NOME[QUANTIDADE]. int contador.35.notas[3]).50.50. Observe o exemplo abaixo para um melhor entendimento: /* visualizando strings como matrizes de caracteres */ #include <stdio.h> int main() { int notas[5] = {60.

h> void exibe(int matriz[]. for(contador = 0. int contador. return(0). Não há necessidade de passar o tamanho da matriz.contador < 7. Exemplo: #include <stdio.palavra).int elementos) { int contador.contador++) printf("O %do elemento tem o valor %d\n".50.palavra[contador]).5). Isto indica que a variável é uma matriz. Por exemplo.int main() { char palavra[7] = "matriz".35. } Observe os colchetes após a variável matriz na declaração da função exibe.matriz[contador]). } int main() { int notas[5] = {60. 12.68}.70.contador++) printf("%c\n". 12.3 Matrizes bidimensionais Imagine uma matriz bidimensional como uma tabela de linhas e colunas. return(0). printf("Analisando os elementos da matriz notas\n").2 Passando uma matriz para uma função Uma função que manipula uma matriz deve receber a matriz e a quantidade de elementos. printf("Em C strings são matrizes de caracteres e podem ser manipuladas como tal. Logicamente ao chamar a função você deve passar a matriz propriamente dita e seu número de elementos. exibe(notas. for(contador = 0. printf("\nExibindo cada elemento da matriz palavra\n").\n").contador+1. int contador.contador < elementos. a matriz pesos[3][5] pode ser imaginada como: . printf("\nA string é %s\n".

2 1.1 0.63. } .Observe que o primeiro índice ([3]) indica as linhas da matriz e o segundo ([5]) indica as colunas.63.1 1.0 2. for(linha = 0.44.80}.30.61.linha < 3. Observe o código abaixo: /* manipulando uma matriz bidimensional */ #include <stdio. {70.linha++) for(coluna = 0.80}.coluna.pesos[linha][coluna]). {86.4 Visto a posição de cada índice vamos preencher nossa matriz pesos com valores 10 86 70 30 44 61 45 63 52 70 82 63 36 80 74 De tudo que foi exposto acima podemos entender que: pesos[1][3] = 82 pesos[0][4] = 36 pesos[0][0] = 10 pesos[2][4] = 74 Para preencher nossa matriz com os valores mostrados na tabela acima podemos usar uma declaração como: int pesos[3][5] = {{10.82.45. int linha.4 1.30.h> int main() { int pesos[3][5] = {{10. coluna++) printf("elemento[%d][%d] = %d\n".36}.3 2.44.52.63.0 0. return(0).4 2.36}.1 2.61. Como sabemos que [3] varia de zero a 2 e [5] varia de zero a 4.coluna.82.linha. fica fácil determinar os índices de cada posição da matriz: 0. {86.63.52.45.coluna < 5.2 2.0 1.74}}.70.3 1.74}}.70. Podemos manipular os elementos de nossa matriz bidimensional usando duas variáveis e um laço for da mesma maneira que fizemos com as matrizes comuns. {70.2 0.3 0.

contador.linha < 3. for(contador = 0. /* realizando a pesquisa sequencial */ contador=0.61. } 12.69}. } int main() { int pesos[3][5] = {{10. else printf("A matriz pesos não possui o valor %d\n". int ok=0.contador++) printf("pesos[%d] = %d\n". Exemplo: /* manipulando uma matriz bidimensional */ #include <stdio.valor).74}}.12. Observe abaixo o código de uma pesquisa sequencial numa matriz: /* exemplo de uma pesquisa sequencial numa matriz */ #include <stdio. else contador++. O número de colunas da matriz também deve estar especificado nesta declaração.matriz[linha][coluna]). coluna++) printf("elemento[%d][%d] = %d\n".52.3). int linhas) { int linha. exibe(pesos. {70.63. deve-se passar a matriz e o número de linhas.valor.30.45.h> void exibe(int matriz[][5]. scanf("%d". while((contador < 5) && (!ok)) if(pesos[contador] == valor) ok = 1.pesos[contador]).77.linha++) for(coluna = 0.82.84. Ao chamar a função.70.63.contador).80.coluna < 5.&valor). for(linha = 0.valor. if(contador < 5) printf("O valor %d está no elemento pesos[%d]\n".80}. {86.linha.contador < 5. .36}.contador.h> int main() { int pesos[5]={65. A pesquisa sequencial inicia no primeiro elemento da matriz e vai até o último procurando o valor desejado.4 Passando uma matriz bidimensional para uma função Uma função que manipula uma matriz bidimensional deve receber a matriz e o número de linhas desta matriz.5 Pesquisa sequencial Para procurar um valor específico numa matriz você pode usar a pesquisa sequencial. return(0).coluna.44.coluna. printf("\nEntre com o valor a ser pesquisado :"). printf("\nmatriz pesos\n\n").

consome mais tempo do processador. que é 55. até que todos os elementos da matriz estivessem na ordem crescente. pelo método da bolha: /* ordenando uma matriz pelo método da bolha * * * neste método a matriz é percorrida e os pares . e nossa matriz ficaria assim: nota[0] nota[1] nota[2] nota[3] nota[4] = = = = = 55 67 86 79 68 Agora nosso programa compararia nota[1] com nota[2] e como os valores estão ordenados não haveria troca. compararia nota[2] com nota[3] e haveria troca ficando nossa matriz assim: nota[0] nota[1] nota[2] nota[3] nota[4] = = = = = 55 67 79 86 68 Agora compararia nota[3] com nota[4] e novamente haveria troca: nota[0] nota[1] nota[2] nota[3] nota[4] = = = = = 55 67 79 68 86 Agora.. com o elemento nota[1]. Como nota[0] é maior que nota[1] os elementos seriam trocados. 12. então só deve ser usado para matrizes com poucos elementos (em torno de 30). apesar de simples. } Este tipo de pesquisa pode ser demorado quando a matriz possui muitos elementos. Isto é feito até que toda a matriz esteja ordenada. Imagine a seguinte matriz: nota[0] nota[1] nota[2] nota[3] nota[4] = = = = = 67 55 86 79 68 Ordenando esta matriz em ordem crescente pelo método da bolha. Neste método os elementos da matriz vão sendo percorridos e os pares adjacentes são comparados e ordenados. nosso programa iniciaria novo ciclo de comparações comparando novamente nota[0] com nota[1]. etc . Para explicar melhor vamos a um exemplo prático. nosso programa iniciaria compararando o elemento nota[0].return(0).6 Ordenando os elementos de uma matriz pelo método da bolha Este método. Nestes casos use a pesquisa binária que será vista mais a frente. nota[1] com nota[2].. em ordem crescente. Continuando. que é 67.. Abaixo segue um exercício que ordena uma matriz de cinco valores inteiros.

contador++) { /* se os elementos adjacentes não estiverem ordenados executa a troca */ if(vetor[contador] > vetor[(contador + 1)]) { auxiliar = vetor[contador].\n"). } 12. /* força outra passagem no laço while */ } } } /* imprimindo os valores ordenados */ printf("\n").ordenados.h> int main() { int vetor[5]. } /* ordenação */ ordenados = 0.contador < 5. depois procura o menor entre o segundo e o último elemento da matriz e troca-o pelo segundo elemento.contador < 4.contador++) printf("%d ". Vamos ver um exemplo prático. return(0). Nossa matriz ficaria assim: . printf("Ordenando uma matriz utilizando o método da bolha. e assim por diante. vetor[(contador + 1)] = auxiliar. /* considera todos os elementos ordenados corretamente */ for(contador=0.&vetor[contador]).auxiliar.(contador+1)). depois procura o menor valor entre o terceiro e o último elemento da matriz e troca-o pelo terceiro. for(contador=0.vetor[contador]). Neste método o programa procura o menor valor entre todos os elementos da matriz e troca-o pelo primeiro elemento. ordenados = 0.contador < 5.7 Ordenando os elementos de uma matriz pelo método da seleção Este método também só deve ser usado com matrizes pequenas. que é 55 e trocá-lo pelo primeiro elemento da matriz (nota [0]). Isto é * feito até que toda a matriz esteja ordenada */ #include <stdio. scanf("%d". /* entrada de dados */ for(contador=0. vetor[contador] = vetor[(contador + 1)]. /* indica que os elementos adjacentes não estão ordenados */ while(ordenados == 0) { ordenados = 1.* adjacentes são comparados e ordenados. contador++) { printf("Entre com o %do valor :".contador. printf("\n"). Dada a matriz: nota[0] nota[1] nota[2] nota[3] nota[4] = = = = = 67 55 86 79 68 Vamos ordená-la em ordem crescente pelo método da seleção: Primeiro nosso programa teria que determinar o menor valor da matriz.

&vetor[contador1]). printf("Ordenando uma matriz utilizando o método da seleção.contador1. que é 68. } .identifica-se o menor valor entre o terceiro e o último elemento * .troca-se este com o segundo elemento * .(contador1+1)).\n"). e este seria trocado com o segundo elemento (nota [1]).contador1 < 5. que é 67.identifica-se o menor valor entre o segundo e o último elemento * .troca-se este com o primeiro elemento * .troca-se este com o quarto elemento * * e assim por diante. pelo método da seleção: /* ordenando uma matriz pelo método da seleção * * * neste método a ordenação é feita da seguinte maneira: * . menor. até que toda a matriz esteja ordenada */ #include <stdio. scanf("%d". /* entrada de dados */ for(contador1 = 0.troca-se este com o terceiro elemento * .contador2. E nossa matriz estaria ordenada: nota[0] nota[1] nota[2] nota[3] nota[4] = = = = = 55 67 68 79 86 Abaixo segue um exercício que ordena uma matriz de cinco valores inteiros. ficando a matriz da seguinte maneira: nota[0] nota[1] nota[2] nota[3] nota[4] = = = = = 55 67 86 79 68 Agora seria determinado o menor valor entre o terceiro (nota [2]) e o último elemento (nota [4]).identifica-se o menor valor da matriz * .h> int main() { int vetor[5]. Agora a matriz está assim: nota[0] nota[1] nota[2] nota[3] nota[4] = = = = = 55 67 68 79 86 Agora seria determinado o menor valor entre nota [3] e nota [4](no caso 79) e este valor trocado com o quarto elemento da matriz.indice_do_menor.identifica-se o menor valor entre o quarto e o último elemento * . contador1++) { printf("Entre com o %do valor :". e este seria trocado com o terceiro elemento (nota [2]). em ordem crescente.nota[0] nota[1] nota[2] nota[3] nota[4] = = = = = 55 67 86 79 68 Agora seria determinado o menor valor entre o segundo (nota [1]) e o último elemento (nota [4]).

contador1 < 5. printf("\n"). vetor[contador1] = menor. /* executando a troca de valores */ menor = vetor[indice_do_menor]. Depois insere o terceiro elemento na posição ordenada em relação aos dois primeiros.contador2 < 5.contador1++) printf("%d ".8 Ordenando os elementos de uma matriz pelo método da inserção Neste método. for(contador1 = 0. o programa inicialmente ordena os dois primeiros elementos da matriz. menor = vetor[contador1]. Vamos a um exemplo prático. vetor[indice_do_menor] = vetor[contador1]. return(0)./* ordenação */ for(contador1 = 0. } } /* imprimindo os valores ordenados */ printf("\n").vetor[contador1]). também usado com matrizes pequenas.contador2++) if(vetor[contador2] < menor) { indice_do_menor = contador2.contador1 < 4. } 12. /* verificando qual o menor */ for(contador2=(contador1 + 1). e assim por diante até que toda a matriz esteja ordenada.contador1++) { indice_do_menor = contador1. Dada nossa matriz: nota[0] nota[1] nota[2] nota[3] nota[4] = = = = = 67 55 86 79 68 Vamos ordená-la em ordem crescente pelo método da inserção: Primeiro nosso programa ordenaria os dois primeiros elementos da matriz: nota[0] = 55 nota[1] = 67 Depois o programa pegaria o terceiro elemento da matriz e o introduziria na posição ordenada em relação aos dois primeiros: nota[0] = 55 nota[1] = 67 nota[2] = 86 Depois o programa pegaria o quarto elemento da matriz e o introduziria na posição ordenada em relação aos três primeiros: nota[0] = 55 nota[1] = 67 . Depois insere o quarto elemento em sua posição ordenada em relação aos três já posicionados.

o terceiro elemento é introduzido em sua posição ordenada em relação aos dois primeiros * . vetor_ordenado[5]. pelo método da inserção: /* ordenando uma matriz pelo método da inserção * * * neste método a ordenação é feita da seguinte maneira: * .&vetor_original[contador]). Abaixo segue um exercício que ordena uma matriz de cinco valores inteiros. /* entrada de dados */ for(contador=0. } else { vetor_ordenado[0] = vetor_original[1].contador < 5.nota[2] = 79 nota[3] = 86 Depois o programa pegaria o quinto elemento da matriz e o introduziria na posição ordenada em relação aos quatro primeiros: nota[0] nota[1] nota[2] nota[3] nota[4] = = = = = 55 67 68 79 86 E nossa matriz estaria ordenada. int ok = 0. contador++) { /* introduzindo o elemento vetor_original[contador] no vetor_ordenado */ . scanf("%d". em ordem crescente.contador3. printf("Ordenando uma matriz utilizando o método da inserção. vetor_ordenado[1] = vetor_original[1].(contador+1)).h> int main() { int vetor_original[5].o quinto elemento é introduzido em sua posição ordenada em relação aos quatro primeiros * * e assim por diante até que toda a matriz esteja ordenada. } /* ordenação */ /* ordenando os dois primeiros elementos */ if(vetor_original[0] < vetor_original[1]) { vetor_ordenado[0] = vetor_original[0].os dois primeiros elementos da matriz são ordenados * .contador2. } /* ordenando os outros elementos */ for(contador = 2.\n").*/ #include <stdio. int contador.o quarto elemento é introduzido em sua posição ordenada em relação aos três primeiros * . contador++) { printf("Entre com o %do valor :". vetor_ordenado[1] = vetor_original[0].contador < 5.

/* considera vetor_ordenado não ordenado */ /* verificando se algum dos elementos de vetor_ordenado é maior que * vetor_original[contador] */ for(contador2 = 0. } /* imprimindo os valores ordenados */ printf("\n"). return(0). Como estão fora de ordem. */ if(ok == 1) vetor_ordenado[contador] = vetor_original[contador].contador3--) vetor_ordenado[contador3] = vetor_ordenado[contador3 . Vamos ao nosso exemplo prático com a matriz: nota[0] nota[1] nota[2] nota[3] nota[4] nota[5] nota[6] nota[7] nota[8] nota[9] = = = = = = = = = = 67 55 86 79 68 99 0 34 18 27 Nossa matriz tem dez elementos. Agora serão comparados nota[1] e nota[6]. /* considerando vetor_ordenado ordenado */ break. Nele compara-se elementos separados por uma distância específica ordenando-os.vetor_ordenado[contador]). for(contador = 0. Vamos começar nossa ordenação ordenando os elementos separados de cinco posições.9 Ordenando os elementos de uma matriz pelo método shell Este método de ordenação oferece uma performance bem melhor que os anteriormente mostrados. nosso programa nada faria. ok =0..ok = 1. /* inserindo vetor_original[contador] em sua posição ordenada */ vetor_ordenado[contador2] = vetor_original[contador]. Como estes elementos estão ordenados..contador2 < contador.contador < 5.contador++) printf("%d ". } 12.contador3 > contador2.contador2++) { if(vetor_ordenado[contador2] > vetor_original[contador]) { /* jogando os elementos de vetor_ordenado para frente */ for(contador3 = contador. serão ordenados e nossa matriz ficará assim: nota[0] = 67 nota[1] = 0 nota[2] = 86 . } } /* se nenhum elemento de vetor_ordenado é maior que vetor_original[contador] . Então compararemos nota[0] e nota[5]. Esta distância então é dividida por dois e o processo continua até que a matriz esteja ordenada. printf("\n").1].

nota[3] nota[4] nota[5] nota[6] nota[7] nota[8] nota[9] = = = = = = = 79 68 99 55 34 18 27 Agora nota[2] e nota[7]. só que desta vez com os elementos separados por três posições. Agora vamos a outro ciclo de comparações. Como estão desordenados. já que devemos usar números inteiros para definir esta distância. sendo agora igual a três. haverá ordenação e a matriz ficará assim: nota[0] nota[1] nota[2] nota[3] nota[4] nota[5] nota[6] nota[7] nota[8] nota[9] = = = = = = = = = = 67 0 34 79 68 99 55 86 18 27 Agora nota[3] e nota[8]: nota[0] nota[1] nota[2] nota[3] nota[4] nota[5] nota[6] nota[7] nota[8] nota[9] = = = = = = = = = = 67 0 34 18 68 99 55 86 79 27 E nota[4] com nota[9]: nota[0] nota[1] nota[2] nota[3] nota[4] nota[5] nota[6] nota[7] nota[8] nota[9] = = = = = = = = = = 67 0 34 18 27 99 55 86 79 68 Terminado este ciclo de comparações a nossa distância será dividida por dois. haveria ordenação e nossa matriz agora ficará assim: nota[0] nota[1] nota[2] nota[3] nota[4] nota[5] nota[6] nota[7] nota[8] nota[9] = = = = = = = = = = 18 0 34 67 27 99 55 86 79 68 . Iniciando com a comparação de nota[0] e nota[3].

nota[3] nota[0] nota[1] nota[2] nota[3] nota[4] nota[5] nota[6] nota[7] nota[8] nota[9] com nota[6]. . matriz inalterada. como estão ordenados não há nenhuma mudança. também sem mudanças. matriz inalterada. matriz inalterada. Agora nota[2] com nota[5]. com nota[4] => estão desordenados.Agora nota[1] com nota[4]. Nossa matriz agora ficará assim: = = = = = = = = = = 18 0 34 55 27 99 67 86 79 68 Agora nota[4] com nota[7]. Agora a distância é novamente dividia por dois e nossa nova distância será dois. com nota[3] => estão ordenados.5. não há mudanças. Abaixo temos as comparações deste novo ciclo. pois não podemos usar a distância 1. matriz inalterada. Como os elementos estão ordenados. nota[5] nota[0] nota[1] nota[2] nota[3] nota[4] nota[5] nota[6] nota[7] nota[8] nota[9] com nota[8] estão desordenados. a matriz fica assim: = = = = = = = = = = 18 0 27 55 34 79 67 86 99 68 com nota[5] => estão ordenados. Estão desordenados. então haverá reordenação: = = = = = = = = = = 18 0 34 55 27 79 67 86 99 68 E terminando este ciclo a comparação de nota[6] com nota[9] não alterará a matriz pois os elementos estão ordenados. nota[0] nota[1] nota[2] nota[0] nota[1] nota[2] nota[3] nota[4] nota[5] nota[6] nota[7] nota[8] nota[9] nota[3] nota[4] com nota[2] => estão ordenados. com nota[6] => estão ordenados.

2. scanf("%d". /* entrada de dados */ for(contador1 = 0.contador1. até que toda a matriz esteja ordenada */ #include <stdio. O único detalhe a ser observado é evitar sequências de distâncias que são potência de dois.&vetor[contador1]).contador2.auxiliar.compara-se os elementos separados pela nova distância * . matriz inalterada. pois elas reduzem a eficiência deste algoritmo.1". } /* ordenação */ distancia = QDE. vetor[contador2] = auxiliar. contador1++) { printf("Entre com o %do valor :".3. com nota[8] => estão ordenados. Dividindo nossa distância atual (2) por dois teremos a comparação dos elementos separados por uma posição. vetor[contador2 + distancia] = vetor[contador2].divide-se esta distância por dois * .contador2 < (QDE . printf("Ordenando uma matriz utilizando o método shell.\n").1" não é interessante.4.nota[5] nota[6] nota[7] nota[0] nota[1] nota[2] nota[3] nota[4] nota[5] nota[6] nota[7] nota[8] nota[9] com nota[7] => estão ordenados.(contador1+1)).2. a matriz fica assim: = = = = = = = = = = 18 0 27 55 34 79 67 68 99 86 E agora o ciclo final.E ao final deste ciclo nossa matriz estaria ordenada. Abaixo segue uma codificação deste exemplo: /* ordenando uma matriz pelo método shell * * * neste método a ordenação é feita da seguinte maneira: * . contador2++) { if(vetor[contador2] > vetor[contador2 + distancia]) { auxiliar = vetor[contador2 + distancia].h> int main() { int QDE = 10. do { distancia = (distancia + 1) / 2. com nota[9] => estão desordenados.divide-se a distância por dois novamente * e assim por diante. } .contador1 < QDE. matriz inalterada. for(contador2 = 0.seria melhor "7.distancia.compara-se os elementos separados por uma distância específica * .Por exemplo: a sequência "8. int vetor[QDE].distancia).

int ultimo) { int temp. Considere a matriz formada pelos valores inteiros: 6.alto. 7 e 0. A figura abaixo mostra como poderíamos classificar esta matriz em ordem crescente usando o quick sort. baixo. /* imprimindo os valores ordenados */ printf("\n"). return(0). } 12. uma matriz de valores inteiros: /* ordenando uma matriz pelo método quick sort */ #include <stdio. 4. Inicialmente é selecionado o valor que está posicionado no meio da lista que chamaremos de elemento central. A partir daí o mesmo processo é feito com cada uma das listas recursivamente.h> void quick_sort(int matriz[]. Abaixo segue o exemplo de um código que ordena em ordem crescente.} } while (distancia > 1). 8.separador. Depois a matriz é dividida e ordenada em duas listas menores separando numa os elementos cujo valor é maior que o valor do elemento central e e na outra os elementos cujo valor é menor que o valor do elementro central.10 Ordenando os elementos de uma matriz pelo método quick sort Para matrizes com muitos elementos este é o método de ordenação mais rápido. 2. pelo método quick sort. 5. alto = ultimo. baixo = primeiro. Neste tipo de ordenação o programa considera sua matriz uma lista de valores. printf("\n").contador1++) printf("%d ". Isso continua até que a matriz esteja toda ordenada.vetor[contador1]). while(matriz[alto] > separador) alto--. for(contador1 = 0.contador1 < QDE. if(baixo <= alto) . 1. do { while(matriz[baixo] < separador) baixo++. separador = matriz[(primeiro + ultimo) / 2]. 3. int primeiro.

matriz[baixo++] = matriz[alto]. printf("Exibindo o printf("O valor da printf("O valor da printf("O valor da printf("O valor da printf("O valor da endereço variável variável variável variável variável de memória de variáveis\n\n"). contador++) { printf("Entre com o %do valor :". if(baixo < ultimo) quick_sort(matriz. idade é %d e seu endereço é %x\n". if(primeiro < alto) quick_sort(matriz.contador < QDE.2f e seu endereço é %x\n". /* imprimindo os valores ordenados */ printf("\n").peso.&vetor[contador]). } quick_sort(vetor.vetor[contador]).(QDE-1)).82. } } while(baixo <= alto). char nome[10] = "samuel". return(0).alto). int idade = 35.&peso). Ponteiros 13.contador.\n").ultimo).&altura). printf("\n"). Lembre-se que o valor da variável é uma coisa e o endereço de memória onde este valor está armazenado é outra. nome é %s e seu endereço é %x\n". . float altura = 1.1 Exibindo o endereço de memória de uma variável Para exibir o endereço de memória de uma variável use o operador & antes da variável.h> int main() { char letra = 's'. matriz[alto--] = temp. printf("Ordenando uma matriz utilizando o método quick sort.altura.nome.contador++) printf("%d ".&letra). altura é %1.baixo.contador < QDE. scanf("%d". O código abaixo esclarecerá melhor estes conceitos: /* exibindo o endereço de memória de variáveis */ #include <stdio.&idade). peso é %2. /* entrada de dados */ for(contador = 0.8.(contador+1)). letra é %c e seu endereço é %x\n".0.primeiro.nome).{ temp = matriz[baixo].letra. } int main() { int QDE = 10.idade. int vetor[QDE]. float peso = 87.1f e seu endereço é %x\n". for(contador = 0. } 13.

char nome[10] = "samuel". o compilador na verdade passa o endereço do primeiro elemento da matriz. Observe o exemplo abaixo: /* verificando como C trata as matrizes como ponteiros */ #include <stdio.82 e seu endereço é bffff8b0 Observe na codificação que a variável nome não precisou do operador de endereço & pois matrizes já são tratadas como ponteiros pela linguagem C.2 Definição de ponteiros Depois de entendida a diferença entre o valor de uma variável e seu endereço de memória fica fácil definir ponteiros.4 Atribuindo valor a uma variável ponteiro Como o ponteiro é uma variável que armazena um endereço de memória.8 e seu endereço é bffff8b4 altura é 1. printf("O endereço do primeiro elemento da matriz idade é %x\n".3 Declarando uma variável ponteiro A sintaxe para a declaração de uma variável ponteiro é: TIPO *NOME onde TIPO é um tipo de dados válido e NOME é o nome da variável. você deverá atribuir a uma variável ponteiro um endereço de memória.peso). assim quando seu programa passa uma matriz para uma função. float peso[5]. quando o programa passa uma matriz para uma função. return(0). Exemplo: . printf("O endereço do primeiro elemento da matriz nome é %x\n". 13.nome). o código acima deverá exibir algo parecido com: Exibindo o endereço de memória de variáveis O O O O O valor valor valor valor valor da da da da da variável variável variável variável variável letra é s e seu endereço é bffff8cb idade é 35 e seu endereço é bffff8c4 nome é samuel e seu endereço é bffff8b8 peso é 87.idade). o compilador passa o endereço inicial da matriz. Ponteiro é uma variável que armazena um endereço de memória. 13.} Ao ser executado.h> int main() { int idade[5]. } 13. Assim. OBSERVAÇÃO:Cabe aqui ressaltar que a linguagem C trata as matrizes como ponteiros. printf("O endereço do primeiro elemento da matriz peso é %x\n". Exemplo: int *idade.

h> int main() { int idade = 35. */ printf("O valor da variável idade é %d\n". Exemplo: /* desreferenciando um ponteiro */ #include <stdio. ptr_idade = &idade. Observe o uso do operador & que devolve o endereço de memória da variável idade.idade). return(0). /* foi atribuído o endereço da variável idade a variável ponteiro ptr_idade. Desreferenciar um ponteiro é acessar o valor armazenado neste endereço. int *ptr_idade.5 Desreferenciando um ponteiro Um ponteiro armazena um endereço de memória./* atribuindo valor a uma variável ponteiro */ #include <stdio. ptr_idade = &idade. printf("O endereço da variável idade é %x\n". */ printf("O valor da variável idade é %d\n". na linha acima. printf("O valor da variável ponteiro ptr_idade é %x\n".h> int main() { int numero = 35. printf("O valor apontado por ptr_idade é %d\n". } 13. */ return(0). int *ptr_idade.6 Alterando o valor armazenado no endereço apontado por um ponteiro /* Alterando o valor armazenado no endereço apontado * por um ponteiro */ #include <stdio.ptr_idade).&idade). printf("O valor da variável ponteiro ptr_idade é %x\n". exibir * o valor armazenado no endereço de memória apontado por ele. .&idade).*ptr_idade).ptr_idade). printf("O endereço da variável idade é %x\n". int *ptr. /* observe. que é o asterisco * . assim. Observe o uso do operador & que devolve o endereço de memória da variável idade.h> int main() { int idade = 35. o uso do operador de indireção ( * ) * para desreferenciar o ponteiro ptr_idade e. } 13.idade). /* foi atribuído o endereço da variável idade a variável ponteiro ptr_idade. Para isso você deve usar o operador de indireção.

ptr = &numero.8 Aritmética dos ponteiros Você pode somar e subtrair valores a ponteiros.*ptr).ptr. Observe que o ponteiro * deve ser desreferenciado.7 Ponteiros como parâmetros de função Quando queremos alterar o valor dos argumentos passados para uma função devemos definir os parâmetros da função como ponteiros. Não consegue alterar este */ printf("Valor de nr após a chamada da função valor = %d\n". /* alterando o valor do argumento passado */ } int main() { int nr = 26. /* função que recebe ponteiro. *ptr = 25. assim ao somar 1 a um ponteiro você estará indo para o próximo endereço de . ptr_nr = &nr.*/ printf("\nAgora o ponteiro ptr armazena o endereço %x que. /* atribuindo o endereço de numero a ptr */ printf("O ponteiro ptr armazena o endereço %x que. int *ptr_nr.\ armazena o valor %d\n". } 13.*ptr).h> /* a função que recebe como argumento o valor * da variável não consegue alterar o valor * deste */ int valor(int a) { a = 35. } 13. Os ponteiros são endereços de memória. return(0).\ armazena o valor %d\n".ptr. valor(nr).\npor sua vez. A isso denominamos chamada por referência. printf("O valor inicial de nr é %d\n".nr).\npor sua vez. Exemplo: /* ponteiros como parâmteros de função */ #include <stdio. /* alterando o valor armazenado no endereço * apontado por ptr. /* alterando o valor do argumento passado */ } /* a função que recebe como argumento um ponteiro * consegue alterar o valor apontado por este */ int ponteiro(int *a) { *a = 35.nr). ponteiro(ptr_nr). Consegue alterar valor * apontado */ printf("Valor de nr após a chamada da função ponteiro = %d\n". porém deve estar atento a um detalhe. return(0). /* função que recebe o valor.nr).

41}. printf("\nPonteiro para letra agora aponta para %c no endereço %x\n". Se você somar 2 a este ponteiro o resultado será um ponteiro apontando para o endereço 1002. i. digamos que um ponteiro do tipo char aponta para o endereço 1000.'e'. ptr_nr = nr. Para isso você pode usar o operador sizeof. printf("Ponteiro para nr aponta para %d no endereço %x\n". Se este ponteiro fosse do tipo int o resultado seria um ponteiro apontando para o endereço 1008.*ptr_nr. char *ptr_letra. printf("Ponteiro para nr agora aponta para %d no endereço %x\n". Analise o código abaixo para um melhor entendimento deste conceito: /* visualizando como funciona a aritmética de ponteiros */ #include <stdio.41\n"). printf("\nmatriz letra = a.9 Exibindo uma string usando um ponteiro Uma string é uma matriz de caracteres. sempre que for somar ou subtrair aos ponteiros você tem que trabalhar com o tamanho do tipo de dado utilizado. nr[5] = {30.sizeof(char)).h> int main() { char string[40] = "Exibindo uma string usando um ponteiro. ptr_nr + 2\n").".ptr_letra).13. Por exemplo. char *ptr_str. o. return(0).12.ptr_nr).*ptr_nr.12. ptr_letra += 3. printf("\nVerificando o tamanho dos tipos de dados\n"). e. printf("\nIncrementando os ponteiros\n").'i'.67.'o'. u\n"). pois o tipo char requer um byte de memória para armazenar seus dados. Então.13.'u'}. int *ptr_nr. int contador. Podemos usar um ponteiro para exibí-la assim: /* exibindo uma string usando um ponteiro */ #include <stdio.*ptr_letra. ptr_nr += 2. printf("matriz nr = 30. requer quatro bytes para armazenar seus dados. /* Apontando para a string */ . printf("Visualizando como funciona a aritmética de ponteiros\n"). printf("\nPonteiro para letra aponta para %c no endereço %x\n". printf("tamanho do tipo de dado char = %d\n". printf("ptr_letra + 3.memória do tipo de dado especificado.sizeof(int)). } 13. sob o linux.ptr_nr).ptr_letra). pois o tipo int.h> int main() { char letra[5] = {'a'. ptr_letra = letra.67. printf("tamanho do tipo de dado int = %d\n".*ptr_letra.

"Quinta"."Sábado"}. return(0).11 Matriz de ponteiros/strings A linguagem C lhe permite criar matrizes de ponteiros."Sexta". } 13. auxiliar++. printf("%s\n". string++. Abaixo segue um exemplo da declaração de uma matriz que armazena ponteiros para strings: char *dias(7) = {"Domingo". * Esta função retorna um ponteiro */ char *converte_maiuscula(char *string) { char *inicio_da_str. /* Exibindo toda a string usando o ponteiro */ while(*ptr_str) { putchar(*ptr_str). inicio_da_str = auxiliar = string."Quarta". } return(inicio_da_str). ptr_str++. 13. return(0). *auxiliar.h> /* Função que converte uma strig para maiúsculas. } int main() { char string[80] = "Usando uma função que retorna uma string. } printf("\n"). printf("%s\n".string).*ptr_str). você tem que fazer isso.10 Criando uma função que retorna um ponteiro #include <stdio.12 Percorrendo uma matriz de strings com um laço for /* percorrendo uma matriz de strings com um laço for */ #include <stdio.ptr_str = string.h> int main() .". O uso mais comum para este tipo de matriz é conter strings. } 13. while(*string) { *auxiliar = toupper(*string).h> #include <ctype. printf("Apontando para o inicio da string => ptr_str = %c\n\n".string)."Segunda". OBSERVAÇÃO:Em matrizes de ponteiros para strings a linguagem C não inclui um item NULL para indicar o final da matriz."Terça". converte_maiuscula(string).

Observe o uso disto no exemplo abaixo: /* exemplificando o uso de ponteiro para uma função */ #include <stdio."Segunda". for(contador = 0.contador < 7. } /* Quando você declara uma matriz de strings o compilador * não acrescenta um caractere NULL para indicar o final * da matriz como o faz com uma matriz de caracteres (strings). A declaração de um ponteiro para uma função segue a sintaxe: TIPO (*FUNÇÃO)()."Quinta".dias[contador])."Sábado".14 Ponteiro para função Você pode criar um ponteiro para uma função.contador+1. int contador."Sábado"}."Quarta"."Quinta". * * Foi isso que foi feito ao inserir 0 no final da matriz dia */ 13. } return(0). ptr_dia++. } /* função usa_maior()."Quarta". O uso mais comum deste recurso é para passar uma função como parâmetro para outra função. return(0). /* apontando ptr_dia para o início da matriz dia */ while(*ptr_dia) { printf("%s\n"."Segunda".*ptr_dia). char **ptr_dia."Sexta".contador++) printf("%do dia da semana = %s\n"."Sexta"."Terça". Recebe dois inteiros e um .h> int main() { char *dia[] = {"Domingo"."Terça".{ char *dias[7] = {"Domingo".int nr2) { return((nr1 > nr2) ? nr1 : nr2).13 Percorrendo uma matriz de strings com um ponteiro /* percorrendo uma matriz de strings com um ponteiro */ #include <stdio. * Por isso você mesmo tem que inserir o caractere NULL para * indicar o final da matriz. /* *dia é um ponteiro para uma string e * **ptr_dia é um ponteiro para um ponteiro para uma string */ ptr_dia = dia.h> /* função que identifica o maior entre dois inteiros */ int maior(int nr1. } 13.0}.

scanf("%d". . valor de venda.usa_maior(a. TIPO CAMPO2.. } int main() { int a....int y.... pois relacionados a cada produto teremos dados do tipo int(código.&a). } 14.quantidade). <>14... printf("Entre com o primeiro número: "). . scanf("%d".&maior)). Digamos que você precisa controlar os seguintes dados relacionados ao estoque de um pequeno estabelecimento comercial: · · · · · · · código nome do produto quantidade estocada valor de compra valor a ser vendido lucro observacões sobre o produto Este seria um caso para o uso de estruturas..b. char nome[50].. observações) e float(valor de compra.y)).. .. }.* ponteiro para a função maior() */ int usa_maior(int x. lucro).. Estruturas As estruturas são utilizadas para agrupar informações relacionadas de tipos de dados diferentes. Para o caso exemplificado no item anterior poderíamos ter algo como: struct produto { int codigo. TIPO CAMPOn. /* observe logo acima que usa_maior() recebe como argumentos * dois números inteiros e o endereço da função maior() * sendo... printf("O maior entre os dois é %d\n".1 Declarando uma estrutura A sintaxe para a declaração (ou criação) de uma estrutura é: struct NOME_DA_ESTRUTURA { TIPO CAMPO1...&b). coerente com sua declaração */ return(0). int quantidade.b. char(nome. assim.. float valor_compra. int (*maior)()) { return(maior(x. printf("Entre com o segundo número: ")..

float lucro.2 Declarando variáveis do tipo de uma estrutura criada Após a declaração da estrutura você pode declarar variáveis do tipo da estrutura com a sintaxe: struct NOME_DA_ESTRUTURA NOME_DA_VARIÁVEL.float valor_venda.CAMPO Observe o código abaixo para um melhor esclarecimento: /* acessando os campos de uma estrutura */ #include <stdio. A declaração da estrutura apenas cria um novo tipo de dado. float valor_compra.h> /* criando um novo tipo de dado "produto" */ struct produto { int codigo. char nome[50]. float valor_venda. Exemplo: struct produto item. sendo o TIPO da variável. float lucro. É importante observar que a declaração da estrutura não cria. }. char obs[200]. . a nova estrutura criada ( struct NOME_DA_ESTRUTURA ). int quantidade. char nome[50]. ainda. float valor_venda. float valor_compra. }. <>14.3 Acessando os campos de uma estrutura A sintaxe para acessar e manipular campos de estruturas é a seguinte: NOME_DA_ESTRUTURA. int quantidade. Você também pode declarar a variável logo após a declaração da estrutura com uma sintaxe do tipo: struct produto { int codigo. }item. Observe que esta sintaxe obecede a sintaxe normal para a declaração de variáveis: TIPO NOME_DA_VARIÁVEL. uma variável. char obs[200]. <>14. Após criar a estrutura você pode declarar variáveis do tipo de estrutura criado.

. printf("Item.nome..stdin).. int idade....&item..30. printf("Código.&item.item. printf("Valor de compra.... printf("Item...:%...2f\n".. altera_estrutura1(struct registro *ficha) { (*ficha).valor_compra).....50.. printf("\n").. /* declarando uma variável "item" do tipo "struct produto" */ printf("Preenchendo a variável \"item\"\n"). fgets(item.nome.idade -= 10. printf("Quantidade.int main() { struct produto item...item. ... printf("Quantidade..:")..item.. printf("Código.. printf("Valor de compra. } int main() { struct registro ficha.valor_venda).valor_compra).&item....:%s".CAMPO ou NOME_DA_ESTRUTURA->CAMPO Exemplo: /* acessando uma estrutura com ponteiros */ #include <stdio.stdin). printf("Valor de revenda:").2f\n".h> struct registro { char nome[30]...quantidade)..quantidade).&item..nome).item. scanf("%d".:"). } <>14...item. fgets(ficha. }.valor_venda)..codigo). scanf("%f".. scanf("%d". printf("Entre com seu nome:")..:%d\n".4 Acessando uma estrutura com ponteiros Para acessar uma estrutura usando ponteiros você pode usar duas sintaxes: (*NOME_DA_ESTRUTURA). } altera_estrutura2(struct registro *ficha) { ficha->idade += 20.....:%d\n". printf("Valor de revenda:%.. return(0)..:").. scanf("%f".:")... printf("Exibindo os dados\n").codigo).

altera_estrutura2(&ficha).CARACTER. printf("Idade: %d.BYTES) a função acima preenche BYTES da área de memória apontada por *STRING com CARACTER .idade).'s'. printf("Nome: %s". return(0). printf("Idade: %d.*ORIGEM. nome[10] = 0.\n". printf("\nExibindo os dados após a segunda alteração\n"). altera_estrutura1(&ficha).idade). printf("Nome: %s". /* inserindo o valor NULL para indicar o final da string */ printf("%s\n".10). Ela faz parte do arquivo de cabeçalho string.h> #include <string.h> int main() { char nome[10].\n".ficha. No gcc ela faz parte do arquivo de cabeçalho string. printf("Nome: %s".\n".ficha.ficha. printf("\nExibindo os dados após a primeira alteração\n").1 Preenchendo um intervalo de memória com uma constante byte Para preencher um intervalo de memória utilize a função memset() . scanf("%d".2 Copiando um intervalo de memória Para copiar um intervalo de memória use a função memcpy() .h e sua sintaxe é: *memset(*STRING.nome).nome). Exemplo: /* preechendo uma área de memória usando a função memset() */ #include <stdio. pelo menos no ambiente Linux usando o gcc.idade).nome). printf("Idade: %d.printf("Qual sua idade?"). Gerenciamento de memória <>15.nome). return(0). memset(nome.ficha. } 15. printf("\nExibindo os dados iniciais\n").ficha. Ao preencher strings com esta função. } <>15. assim tive que fazer isso eu mesmo.h e sua sintaxe é: *memcpy(*DESTINO. A função retorna um ponteiro para *STRING .&ficha.idade).BYTES) . a função não inseriu o caracter NULL para indicar o final da string.ficha.

4.contador < 5. printf("valores de nrs2 inicialmente\n").nrs[contador]).3.nrs1.nrs1[contador]). float *ptr_nrs. for(contador = 0.1.h> int main() { float nrs1[5] = {1. } <>15. for(contador = 0. float nrs2[5] = {5.1.1f ".3 Movendo um intervalo de memória Para mover uma área de memória use a função memmove() que está no arquivo de cabeçalho string. for(contador = 0.contador < 5.a função acima copia BYTES da área de meória *ORIGEM para a área de memória *DESTINO . printf("\n"). .1.3. return(0).BYTES) a função acima move BYTES da área de memória *ORIGEM para a área de memória *DESTINO .5}.4. A função retorna um ponteiro para *DESTINO .1.*ORIGEM.contador < 5.1.bytes.1.5.h> #include <string.sizeof(nrs1)).1f ". int contador.1.5}. Sua sintaxe é: *memmove(*DESTINO. printf("valores de nrs inicialmente\n"). for(contador = 0. int contador.5. Exemplo: /* movendo um intervalo de memória */ #include <stdio.contador++) printf("%. printf("\n"). A diferença entre esta função e a função memcpy() mostrada na seção anterior é que com esta as área de memória *DESTINO e *ORIGEM podem se sobrepor. /* observe o uso do operador "sizeof" para * determinar o tamanho da área de memória * a ser copiada */ printf("valores de nrs2 após a cópia\n").1f ".5}.1.1.nrs2[contador]).2. printf("\n"). Exemplo: /* copiando um intervalo de memória */ #include <stdio.contador++) printf("%.contador++) printf("%.5.h .1f ".h> #include <string.h> int main() { float nrs[5] = {1. printf("valores de nrs1\n"). A função retorna um ponteiro para *DESTINO . printf("\n").2.1.contador++) printf("%.contador < 5.nrs2[contador]). memcpy(nrs2.

contador < 5. Ela faz parte do arquivo de cabeçalho string.bytes).nrs[contador]). printf("valores de nrs após a movimentação\n").copia).CARACTER.*ORIGEM. if(ptr_copia) *ptr_copia = 0.h> #include <string.contador++) printf("%. } <>15. for(contador = 0.5 Comparando duas áreas de memória Você pode comparar duas áreas de memória usando a função memcmp() . printf("\n").BYTES) ...1f ". * será efetuada a cópia da área de memória até * este caracter e "ptr_copia" apontará para o * próximo byte após ". * Se o caracter ". char copia[80].frase.h e sua sintaxe é: memcpy(*AREA1. * Caso contrário. } <>15.h você pode copiar um intervalo de memória até encontrar um byte específico.estudem!!!". bytes = (sizeof(float) * 4)." em "copia. Exemplo: /* copiando um intervalo de memória até encontrar um * byte específico */ #include <stdio. return(0). return(0). ptr_nrs++. serão copiados 80 bytes e * "ptr_copia" receberá o valor NULL.4 Copiando até encontrar um byte específico Usando a função memccpy() . que está no arquivo de cabeçalho string. memmove(nrs. no máximo. BYTES de *ORIGEM para *DESTINO . */ ptr_copia = memccpy(copia. /* "ptr_copia" aponta para o resultado de memccpy(). printf("%s\n".h> int main() { char frase[80] = "E como dizia meu velho professor de física. char *ptr_copia.'. Ela retorna um ponteiro para o próximo byte após CARACTER em *DESTINO ou NULL se CARACTER não for encontrado nos primeiros BYTES de *ORIGEM .ptr_nrs.'." for encontrado em "frase".80). *memccpy(*DESTINO. parando se CARACTER for encontrado.ptr_nrs = nrs.*AREA2.BYTES) Ela copia. A sintaxe da função é.

Se *AREA1 for maior ela retorna um inteiro maior que zero. pares e ímpares. int resultado. */ é maior\n"). se *AREA2 for maior ela retorna um inteiro menor que zero e caso as duas áreas sejam iguais ela retorna zero.Ela compara os primeiros BYTES de *AREA1 e *AREA2 . printf("string2 = %s\n\n".string2. str_destino[30] = 0. Exemplo: /* trocando bytes adjacentes */ #include <stdio. <>15.BYTES) Ela copia BYTES de *ORIGEM para *DESTINO trocando os bytes adjacentes. use a função swab() .str_destino). printf("str_origem => %s\n".h> #include <string. .h> int main() { char string1[7] = "aeiou".*DESTINO. e string2 são iguais\n"). printf("string1 = %s\n". normalmente para trocar dados entre máquinas que possuem ordenamento de bytes alto/baixo diferentes. Exemplo: /* comparando duas áreas de memória */ #include <stdio. char str_destino[30].6 Trocando bytes adjacentes Quando você precisar trocar os bytes adjacentes. printf("str_destino => %s\n".str_origem).7). char string2[7] = "Aeiou".h> int main() { char str_origem[30] = "Trocando bytes adjacentes".'s'.h e sua sintaxe é: swab(*ORIGEM. resultado = memcmp(string1. memset(str_destino. < 0) é maior\n").string2).h> #include <string. if(resultado > 0) printf("string1 else if(resultado printf("string2 else printf("string1 return(0).string1). } /* Faça algumas substituições no código * trocando o "A" maiúsculo de "string2" * para "string1" e/ou substituindo-o * por um "a" e observe os vários * resultados do programa. Ela faz parte do arquivo de cabeçalho string.30).

Caso você * estivesse alocando memória para um ponteiro de * ponto flutuante esta instrução seria "(float *").7 Alocando memória dinamicamente Quando você declara uma matriz o compilador aloca memória para o armazenamento dos dados desta matriz. } <>15.h> int main() { int *matriz1. Para isso você pode usar as funções calloc() e malloc() . printf("str_origem => %s\n". Caso você queira alterar o tamanho da matriz terá que modificar o código e recompilar o programa.sizeof(int)). tendo cada um destes elementos TAMANHO bytes.contador + 1).h . swab(str_origem. o programa aloca a memória necessária durante a execução. scanf("%d".TAMANHO) Ela aloca memória para uma matriz com o número de elementos igual a QUANTIDADE_DE_ELEMENTOS .30). Exemplo do uso de calloc() : /* alocando memória dinamicamente com calloc() */ #include <stdio. printf("Entre com a quantidade de elementos da matriz de inteiros :"). int nr_elementos_matriz1. elas fazem parte do arquivo de cabeçalho stdlib.&matriz1[contador]).h> #include <stdlib. Esta função retorna um ponteiro para o ínicio do bloco de memória alocado ou NULL caso ocorra algum problema. } printf("\n"). A sintaxe de calloc() é: *calloc(QUANTIDADE_DE_ELEMENTOS. Para evitar isso você pode alocar memória dinamicamente.str_destino).contador++) { printf("Entre com o %do elemento :". */ if(matriz1) { for(contador = 0.&nr_elementos_matriz1).printf("chamando swab()\n"). usando o gcc.str_origem). . return(0). int contador. scanf("%d".contador < nr_elementos_matriz1. /* Observe acima a instrução "(int *)". matriz1 = (int *) calloc(nr_elementos_matriz1. printf("Alocando memória dinamicamente usando calloc()\n"). printf("str_destino => %s\n". Em ambiente linux. ou seja. Isto é usado * para converter o ponteiro retornado por calloc() * para um ponteiro do tipo desejado.str_destino.

\n"). return(0).contador + 1. printf("Entre com a quantidade de elementos da matriz de inteiros :").h> #include <stdlib.contador++) printf("Exibindo o %do elemento : %d\n". } printf("\n"). return(0). for(contador = 0. } else printf("Erro ao alocar memória. } A sintaxe de malloc() é: *malloc(BYTES) Esta função aloca BYTES e retorna um ponteiro para o início da memória alocada ou NULL caso ocorra algum problema.matriz1[contador]).contador + 1.&matriz1[contador]).contador < nr_elementos_matriz1. } else printf("Erro ao alocar memória.contador < nr_elementos_matriz1.&nr_elementos_matriz1). int contador. /* Observe acima a instrução "(int *)".contador + 1).contador < nr_elementos_matriz1. Isto é usado * para converter o ponteiro retornado por malloc() * para um ponteiro do tipo desejado.matriz1[contador]). int nr_elementos_matriz1. printf("Alocando memória dinamicamente usando malloc()\n").\n"). Exemplo do uso de malloc() : /* alocando memória dinamicamente com malloc() */ #include <stdio. scanf("%d".h> int main() { int *matriz1. } . Caso você * estivesse alocando memória para um ponteiro de * ponto flutuante esta instrução seria "(float *"). */ if(matriz1) { for(contador = 0.contador++) { printf("Entre com o %do elemento :". matriz1 = (int *) malloc(nr_elementos_matriz1 * sizeof(int)). scanf("%d".for(contador = 0.contador++) printf("Exibindo o %do elemento : %d\n".

free(matriz1). printf("Entre com a quantidade de elementos da matriz de inteiros :"). Se *PONTEIRO for NULL. se BYTES for igual a zero.contador + 1).9 Alterando o tamanho da memória alocada Para alterar o tamanho de um bloco de memória anteriormente alocado use a função realloc() .matriz1[contador]). calloc() ou realloc() . printf("e liberando a memória alocada com free()\n"). matriz1 = (int *) malloc(nr_elementos_matriz1 * sizeof(int)).&matriz1[contador]). scanf("%d".&nr_elementos_matriz1). return(0). a chamada será equivalente a free(*PONTEIRO) .BYTES) Ela altera o tamanho do bloco apontado por *PONTEIRO para BYTES . int nr_elementos_matriz1.contador++) printf("Exibindo o %do elemento : %d\n". a chamada será equivalente a malloc(BYTES) . Para isso você pode usar a função free() .h> int main() { int *matriz1.h e cuja sintaxe é: free(*PONTEIRO) Exemplo do uso de free() : /* liberando memória anteriormente alocada */ #include <stdio. for(contador = 0. A menos que *PONTEIRO seja NULL. que pertence ao arquivo de cabeçalho stdlib.contador < nr_elementos_matriz1. if(matriz1) { for(contador = 0. Ela faz parte do arquivo de cabeçalho stdlib. /* liberando a memória alocada */ } else printf("Erro ao alocar memória. } <>15. printf("Alocando memória dinamicamente usando malloc()\n"). int contador.h> #include <stdlib.contador < nr_elementos_matriz1.8 Liberando memória Quando seu programa não precisar mais da memória alocada com as funções malloc() e calloc() ele deve liberar a memória.h e sua sintaxe é: *realloc(*PONTEIRO. scanf("%d".<>15. A memória recém-alocada não será inicializada.contador++) { printf("Entre com o %do elemento :".contador + 1. .\n"). } printf("\n"). ele precisa ter sido retornado por uma chamada anterior para malloc() .

if(frase) printf("1000 bytes alocados com sucesso\n"). Para isso existem dois parâmetros da função main() . return(0). incluindo o nome do programa. Argumentos da linha de comando Seu programa C pode manipular os argumentos passados na linha de comando. return(0). } Compilei o código acima com o nome de args . Este é uma matriz de ponteiros para strings que armazena ponteiros que apontam para cada um dos argumentos passados.1000).contador++) printf("%do argumento => %s\n". incluindo o nome do programa. O segundo é argv . printf("\n"). realloc(frase. */ int main(int argc.Exemplo do uso de realloc() : /* alterando um bloco de memória anteriormente alocado */ #include <stdio. else printf("Erro ao alocar memória\n"). frase = (char *) malloc(10). printf("Foram passados %d argumentos na linha de comando.argc). * "argv" é uma matriz de ponteiros para strings e * armazena ponteiros que apontam para cada um * dos argumentos passados para a linha de comando.\n". for(contador = 0. } 16.h> /* "argc" armazena o número de argumentos passados * na linha de comando.contador. Para um melhor entendimento observe o código abaixo: /* entendendo os argumentos da linha de comando */ #include <stdio. else printf("Erro ao alocar memória\n"). char *argv[]) { int contador. Observe abaixo como ficou uma sessão de execução deste programa: [samu@pitanga c]$ .h> #include <stdlib. if(frase) printf("10 bytes alocados com sucesso\n"). Um é o parâmetro argc .argv[contador]).contador < argc. Ele recebe o número de argumentos passados na linha de comando./args argumento1 argumento2 .h> int main() { char *frase.

. env é uma matriz de ponteiros para strings que armazena ponteiros para cada uma das variáveis de ambiente. 0o argumento => .*argv). Manipulando o ambiente 17. printf("Foram passados %d argumentos na linha de comando. Para maiores detalhes sobre a conversão de strings para valores numéricos dê uma olhada na seção Convertendo strings em números. Observe: [samu@pitanga c]$ .char *env[]) { int contador. char **argv[]) { int contador = 0.h> int main(int argc. Abaixo segue um código que exibe as variáveis de ambiente do sistema: /* exibindo as variáveis de ambiente */ #include <stdio./args "este é o primeiro argumento" argumento2 argumento3 Foram passados 4 argumentos na linha de comando.\n". contador++. Para isso você deve declará-lo como um ponteiro para um ponteiro de strings. } return(0)./args 1o argumento => este é o primeiro argumento 2o argumento => argumento2 3o argumento => argumento3 [samu@pitanga c]$ Você pode ainda manipular argv como ponteiro em vez de tratá-lo como uma matriz de strings.Foram passados 3 argumentos na linha de comando. Exemplo: /* tratando "argv" como ponteiro */ #include <stdio. 17. Isto significa que os valores numéricos deverão ser convertidos. } Não que esqueça que argv é uma matriz de strings. while(*argv) { printf("%do argumento => %s\n".h> /* observe a declaração de "argv" como * um ponteiro para um ponteiro */ int main(int argc./args 1o argumento => argumento1 2o argumento => argumento2 [samu@pitanga c]$ Caso o argumento a ser passado seja uma frase você deve colocá-lo entre aspas.argc). então os dados passados na linha de comando são todos considerados caracteres ASCII.char *argv[].contador.1 Exibindo as variáveis de ambiente Além de argc e argv a função main possui o parâmetro env que lhe permite manipular as variáveis de ambiente. 0o argumento => . argv++.

Para isso você deve declará-lo como um ponteiro para um ponteiro de strings.env[contador] != NULL.\n").char **env[]) { int contador = 0. Exemplo: /* pesquisando uma variável de ambiente */ #include <stdio.3 Alterando o valor ou adicionando uma variável ao ambiente Para alterar o valor ou adicionar uma variável ao ambiente use a função putenv() . return(0). } 17.h> #include <stdlib.h e sua sintaxe é: putenv("VARIAVEL=novo_valor") .h e sua sintaxe é: getenv("NOME") Ela procura pela variável NOME na lista de variáveis de ambiente. Exemplo.h> int main(int argc.char *argv[]. Ela faz parte do arquivo de cabeçalho stdlib.env[contador]). return(0). printf("Exibindo as variáveis de ambiente\n").h> int main() { char *variavel.variavel). /* tratando "env" como ponteiro */ #include <stdio. } Você pode tratar env como um ponteiro em vez de tratá-lo como uma matriz de strings. } 17. return(0). for(contador = 0. while(*env) printf("env[%d] => %s\n". Ela faz parte do arquivo de cabeçalho stdlib.2 Pesquisando uma variável no ambiente Para pesquisar um item no ambiente use a função getenv() .contador. if(*variavel) printf("USER = %s\n". printf("=================================\n"). else printf("A variável de ambiente USER não está definida.contador++) printf("env[%d] => %s\n". Caso encontre ela retorna um ponteiro para a variável.contador++. caso contrário ela retorna NULL. printf("=================================\n").printf("Exibindo as variáveis de ambiente\n").*env++). variavel = getenv("USER").

printf("Entre com o valor do segundo número :"). printf("Entre com o valor do primeiro número :").1 return O comando return(VALOR) encerra uma função retornando VALOR para a função chamadora. */ printf("A soma dos dois é %d\n". /* "resultado" será passado a função chamadora * no caso "printf" */ return(resultado). O comando "return" * da função soma retornará "resultado" para * aqui.\n"). Caso a função chamadora seja main() . else { variavel = getenv("GURU"). scanf("%d". if(*variavel) printf("GURU = %s\n". } int main() { int nr1. Encerrando seu programa 18.h> int main(int argc.nr2)). caso contrário ela retorna -1. } 18. .h> #include <stdlib. scanf("%d".&nr2).h> int soma(int a. caso não exista esta é adicionada ao ambiente.soma(nr1. } return(0). /* Chamando a função soma.char *argv[]. else printf("A variável de ambiente GURU não está definida. if(putenv("GURU=samu")) printf("Erro ao adicionar a variável de ambiente GURU\n"). A função retorna zero caso tudo ocorra bem. int b) { int resultado.nr2. char *variavel. Exemplo: /* adicionando uma variável ao ambiente */ #include <stdio.valor. resultado = a + b.Caso VARIAVEL exista no ambiente seu valor é alterado para novo_valor .&nr1). Exemplo: /* verificando o funcionamento de "return" */ #include <stdio.variavel).char *env[]) { int contador. o programa será encerrado e o valor retornado passado para o sistema operacional.

&nr1). printf("Em ambiente Linux.printf("Entre com o valor a ser retornado para o sistema operacional :"). int b) { int resultado. printf("Em ambiente Linux.&valor).h> int soma(int a. */ printf("A soma dos dois é %d\n". printf("Para ver o valor retornado pelo programa\n").valor. scanf("%d". Exemplo: /* verificando o funcionamento de "exit" */ #include <stdio. } 18. scanf("%d". o comando exit(VALOR) encerra imediatamente o programa e retorna VALOR para o sistema operacional. printf("$ echo $?\n\n"). /* "valor" será retornado para o sistema operacional * pois este foi a função chamadora de "main" */ return(valor).soma(nr1. /* "valor" será retornado para o sistema operacional * pois este foi a função chamadora de "main" */ return(valor).nr2. printf("Entre com o valor do segundo número :"). } 18.&valor). /* Chamando a função soma. scanf("%d". printf("Entre com o valor do primeiro número :"). resultado = a + b. Exemplo: . } int main() { int nr1. digite o comando shell\n\n"). printf("Para ver o valor retornado pelo programa\n"). /* Nada abaixo disto será executado pois o comando "exit" * chamado na função "soma" acima encerrará imediatamente * o programa e retornará "resultado" para o sistema operacional */ printf("Entre com o valor a ser retornado para o sistema operacional :").nr2)).2 exit Ao ser chamado. printf("$ echo $?\n\n"). digite o comando shell\n\n"). scanf("%d".&nr2). /* "exit" encerra o programa imediatamente e retorna * "resultado" para o sistema operacional */ exit(resultado).3 abort Ao encontrar a função abort o programa é imediatamente encerrado e um valor de erro padrão do sistema é retornado para o sistema operacional. O comando "return" * da função soma retornará "resultado" para * aqui.

printf("Entre com o valor do primeiro número :"). digite o comando shell\n\n"). caso ela precise acessar dados estes devem ter sido declarados como variávesi globais. /* "valor" será retornado para o sistema operacional * pois este foi a função chamadora de "main" */ return(valor). /* Nada abaixo disto será executado pois o comando "exit" * chamado na função "soma" acima encerrará imediatamente * o programa e retornará "resultado" para o sistema operacional */ printf("Entre com o valor a ser retornado para o sistema operacional :"). FUNÇÃO não recebe argumentos. com uma chamada a exit() ou com uma chamada a return() a partir de main() ./* verificando o funcionamento de "abort" */ #include <stdio. /* Chamando a função soma.h> . caso contrário retorna -1. /* Ao encontrar "abort" o programa é imediatamente * encerrado sendo retornado para o sistema * operacional um dos valores de erro padrão * do sistema */ abort(). a última função declarada será a primeira a ser chamada. printf("Para ver o valor retornado pelo programa\n"). scanf("%d". Neste caso elas serão chamadas na ordem inversa da declaração.nr2)). scanf("%d".valor. scanf("%d".&nr1). Ela faz parte do arquivo de cabeçalho stdlib.nr2.&nr2). printf("$ echo $?\n\n").h> int soma(int a. int b) { int resultado.&valor).h> #include <stdlib. printf("Entre com o valor do segundo número :"). ou seja. assim. Observe abaixo um exemplo do uso de atexit : /* utilizando "atexit" */ #include <stdio.h e sua sintaxe é: atexit(FUNÇÃO) ela faz com que FUNÇÃO seja chamada quando o programa terminar normalmente. } int main() { int nr1. ou seja. exit(resultado). } 18. resultado = a + b. O comando "return" * da função soma retornará "resultado" para * aqui. Você pode ainda definir mais de uma função a ser chamada com atexit .4 Definindo funções a serem executadas no encerramento do programa Para definir funções a serem executadas no encerramento do programa use a função atexit() . */ printf("A soma dos dois é %d\n". printf("Em ambiente Linux.soma(nr1. Caso tudo ocorra bem atexit retorna zero.

char *argv[]){ int c. } return 0.h> void primeira() { printf("Primeira função chamada por atexit\n"). printf("%d argumentos passados.\n". pois o nome do programa é considerado o primeiro argumento. argc é um inteiro que indica quantos argumentos foram passados para main(). argv é um ponteiro para uma matriz de strings. Cada string desta matriz é um argumento passado na linha de comando. Exemplo: #include <stdio. argv[1] aponta para o primeiro argumento passado na linha de comando.com. argv[2] aponta para o segundo argumento. argv[0] aponta para o nome do programa. Execução: nerd@nerd:~$ . } int main() { printf("Chamando atexit\n\n").argv[c]). atexit(primeira).c < argc. argumento 1 => arg1 argumento 2 => arg2 argumento 3 => arg3 nerd@nerd:~$ ./args arg1 arg2 arg3 4 argumentos passados.c. c++){ printf("argumento %d => %s\n".h> int main(int argc. } void segunda() { printf("Segunda função chamada por atexit\n"). return(0). e assim por diante. atexit(segunda). } void terceira() { printf("Terceira função chamada por atexit\n"). Ele assume no mínimo o valor 1.br Os argumentos da linha de comando são referenciados através dos parâmetros argc e argv da função main().#include <stdlib.argc).sdiasneto@yahoo. atexit(terceira). for(c = 1. } Manipulando argumentos da linha de comando Samuel Dias Neto .

Após a chamada de va_end a variável ap é destruída. type). o último parâmetro o qual a função conheçe o tipo. O parâmetro last é o nome do último parâmetro antes da lista de argumentos variáveis. va_arg(va_list ap. Cada chamada a va_arg modifica ap de modo que a próxima chamada retorna o próximo argumento. isto é. Se ap é passado para uma função que usa va_arg(ap. ou se type não é compatível com o tipo do próximo argumento. va_arg e va_end. erros aleatórios ocorrerão. O arquivo de cabeçalho stdarg. Chamadas sucessivas retornam os valores dos outros argumentos. . ele não deve ser declarado como uma variável register.sdiasneto@yahoo. Descrição: Uma função pode ser chamada com um número variável de argumentos sendo estes argumentos de diversos tipos.br Sintaxe: #include <stdarg.h declara um tipo va_list e define três macros para manipular uma lista de argumentos cuja quantidade e tipos são desconhecidos pela função.h> void type void void va_start(va_list ap. Se não existe próximo argumento. last). va_list src). O primeiro uso da macro va_arg após a macro va_start retorna o argumento após last. Pode-se apontar para um objeto de um tipo específico simplesmente adicionando um * ao tipo. Várias chamadas com va_start e va_end aninhadas são possíveis. Porque o endereço deste parâmetro pode ser usado na macro va_start. ou como uma função ou como um array. va_end pode ser uma macro ou uma função. O parâmetro ap é aquele inicializado por va_start. va_end(va_list ap). A função deve declarar um objeto do tipo va_list o qual é usado pelas macros va_start.listas de argumentos variáveis Samuel Dias Neto . va_copy(va_list dest.type) então o valor de ap é destruído após o retorno da função. va_end Cada chamada de va_start deve ter uma chamada correspondente a va_end na mesma função. va_arg A macro va_arg expande para uma expressão que tem o tipo e valor do próximo argumento na chamada.com.stdarg . va_start A macro va_start inicializa ap para uso posterior por va_arg e va_end e deve ser chamada primeiro. O parâmetro type é um nome de tipo.

) { va_list ap.Exemplo: A função foo pega uma string de caracteres de formato e exibe o argumento associado com cada caracter de formato baseado no tipo. while (*fmt) switch(*fmt++) { case 's': /* string */ s = va_arg(ap.br O que é o utilitário make Arquivos make padrão O conceito de alvos Executando o Makefile Alvos frequentemente utilizados pela comunidade Dependências Utilizando macros Utilizando regras de inferência O que é o utilitário make O utilitário make é uma poderosa ferramenta usada para compilar grandes projetos. printf("char %c\n". *s. int d. . break. o make pode fazer isto para você com a vantagem de compilar somente o que for necessário. Em vez de você mesmo compilar e linkar todos os arquivos. int).h> void foo(char *fmt. assim não há necessidade de decorar as opções de comando que você utilizou para compilar um projeto.sdiasneto@yahoo. case 'd': /* int */ d = va_arg(ap. Você pode introduzir os comandos de compilação num arquivo make . va_start(ap. } Usando o utilitário make Samuel Dias Neto . case 'c': /* char */ /* need a cast here since va_arg only takes fully promoted types */ c = (char) va_arg(ap. printf("int %d\n". . int). Isto é muito útil no caso de pequenas modificações em um grande projeto.com. } va_end(ap).. char c.h>> #include <stdarg. s). fmt). printf("string %s\n". break. char *). d). #include <stdio. break. c).. *p.

GNUmakefile 2. Arquivos make padrão Ao ser invocado. fazer as alterações necessárias e executar pois makefile é escolhido primeiro pelo comando make. Nosso Makefile deve ter pelo menos um alvo. Se. Agora vamos editar o Makefile e introduzir alvos: # Estudando o comando make alvo1: @echo "Exibindo o alvo 1" alvo2: @echo "Exibindo o alvo 2" alvo3: @echo "Exibindo o alvo 3" As linhas iniciadas com # são linhas de comentários. Para aprofundar-se dê uma olhada na page do GNU. o comando make procura no diretório atual por um dos três arquivos abaixo na seguinte sequência: 1. Na seção de documentação você encontrará um manual completo do make .Veremos aqui a utilização básica do utilitário make . Quando usamos os recursos do comando make UNIX padrão devemos sempre usar o nome Makefile. teste]$ Observe que o comando foi encerrado dizendo que não haviam alvos. Stop. você quiser testar alguma modificação no Makefile sem mexer no original você pode copiálo com o nome de makefile . Alvos O comando make trabalha com o conceito de alvos. só que em inglês. Um nome de alvo deve sempre iniciar no começo da linha e ser seguido por dois pontos. makefile 3. Crie um Makefile vazio e execute o comando make e você terá uma sessão parecida com esta: [nerd@aranha Makefile [nerd@aranha make: *** No [nerd@aranha teste]$ ls teste]$ make targets. no futuro. Executando o Makefile . Makefile Ao construir seu arquivo make é recomendado o uso do nome Makefile porque: · · A própria documentação do GNU diz que deve-se evitar o uso do nome GNUmakefile pois este só deve ser empregado quando usamos os recursos suportados pelo comando make do GNU.

portanto. Observe: [nerd@aranha teste]$ make alvo2 Exibindo o alvo 2 [nerd@aranha teste]$ make alvo3 Exibindo o alvo 3 [nerd@aranha teste]$ make Exibindo o alvo 1 [nerd@aranha teste]$ Veja que quando foi invocado sem alvo.utilizado como o primeiro nome de alvo do arquivo e. Dependências O comando make também tem um conceito de dependência. Você pode também invocar vários alvos no mesmo comando: [nerd@aranha teste]$ make alvo2 alvo3 alvo1 Exibindo o alvo 2 Exibindo o alvo 3 Exibindo o alvo 1 [nerd@aranha teste]$ Alvos frequentemente utilizados pela comunidade Existem alguns nomes de alvo que são frequentemente utilizados por todos os programadores. o comando make assumiu o primeiro alvo do arquivo como o alvo padrão. Este alvo vai além do clobber pois remove também os arquivos de configuração. clobber . Abaixo segue alguns deles: · · · · · all . clean . A utilização deste alvo define o projeto inteiro. Você remove estes alvos para reconstruir o projeto do zero. distclean .Para excutar o Makefile invocando um alvo basta entrar com o comando make seguido do nome do alvo na linha de comando. Quando um alvo A depende de um alvo B. install -utilizado para instalar um projeto.usado para remover tudo.utilizado para remoção dos arquivo objeto e arquivos temporários criados no processo de instalação. Para o uso dos alvos frequentemente utilizados que estão descritos acima esteja ciente que: · · · install depende de all clobber depende de clean distclean depende de clobber Vamos introduzir dependências no nosso exemplo de estudo: # Estudando o comando make alvo1: @echo "Exibindo o alvo 1" alvo2: alvo1 alvo3 @echo "Exibindo o alvo 2" . exceto os arquivos originais que foram distribuídos pela internet.utilizado para remover os alvos que são construídos (normalmente executáveis e bibliotecas). o nome de alvo padrão. o alvo B será executado primeiro.

Observe a sessão abaixo: [nerd@aranha teste]$ make compilando teste.c compilando main.c #usando um nome de alvo frequentemente utilizado para #definir todo o projeto all: alvo1 alvo2 alvo3 alvo1: @echo "compilando "$(ARQUIVO) alvo2: @echo "linkando "$(ARQUIVO) alvo3: @echo "removendo "$(ARQUIVO) Nesta implementação do nosso arquivo de estudo introduzimos um nome de alvo normalmente utilizado ( all ) para definir todo o projeto. Observe como abaixo: # Estudando o comando make # definindo uma macro ARQUIVO = teste. Veja como seria a execução deste Makefile: [nerd@aranha teste]$ make compilando teste.c [nerd@aranha teste]$ make ARQUIVO=main. onde quisermos que o nome da macro seja substituído devemos colocar a expressão: $(NOME_DA_MACRO) Você ainda pode alterar o valor da macro quando invocando o Makefile.alvo3: alvo2 @echo "Exibindo o alvo 3" Agora vamos executar o Makefile invocando alvo2 e ver como funcionam as dependências: [nerd@aranha teste]$ make alvo2 Exibindo o alvo 1 Exibindo o alvo 3 Exibindo o alvo 2 [nerd@aranha teste]$ Vemos que as dependências devem vir após o nome do alvo e devem estar separadas por um espaço. Macros O arquivo make também pode utilizar-se de macros para aumentar sua funcionalidade.c linkando teste.c removendo teste.c removendo teste.c linkando teste.c . A primeira dependência também deve estar separada dos dois pontos por um espaço.c [nerd@aranha teste]$ Como mostrado no novo código do nosso Makefile de estudo.

4.c. ele deve excutar os comandos que seguem. As macros CC e STD já foram vistas acima. Para que o comando não seja exibido na saída padrão preceda-o com o caracter @ .c. $(CC) -c -Wall $(CFLAGS) -D$(STD) $< -o $@ O comando deve iniciar com um caractere de tabulação. como a opção -g para . o comando correto para a compilação do arquivo. existe um arquivo fonte ( .arquivo fonte em linguagem C .c removendo main.linkando main. O comando para o alvo . Veja que este comando usa amplamente macros.o: $(CC) -c -Wall $(CFLAGS) -D$(STD) $< -o $@ Vamos dissecar o trecho de código acima: 1.c.c . Ela pode ser usada para armazenar quaisquer outras opções de compilação não usadas constantemente.c ) de entrada e este é mais recente.arquivo fonte em linguagem C++ .o é um tipo de alvo especial que define a regra de inferência. O alvo . 3. Observe que estas macros serão substituídas na linha de ação do alvo . assim.o ). Regras de inferência As regras de inferência são outro grande recurso do comando make .arquivo objeto compilado Abaixo segue um exemplo da definição de uma regra de inferência: CC = gcc STD = _GNU_SOURCE .h .c ) seguido do sufixo do arquivo alvo ( .c [nerd@aranha teste]$ Veja que usamos o mesmo Makefile para processar outro arquivo através da definição de outro valor para a macro ARQUIVO na linha de comando. 5.o é: 6.c.o montando. Com esta declaração de alvo o comando make entende que se você tem um alvo que é um arquivo objeto ( .cc . As duas primeiras linhas 2.o . Para utilizá-las o make reconhece os seguintes tipos de arquivos dentre outros: · · · · . A macro CFLAGS normalmente é deixada em aberto para lhe dar flexibilidade.o ).arquivo de cabeçalho em linguagem C . Ele é composto do sufixo do arquivo inicial ( . CC = gcc STD = _GNU_SOURCE utilizam macros para definir o compilador e o padrão de compilação. É importante observar que numa definição de regra de inferência não deve haver dependência.

c com o código abaixo: #include <stdio. Juntamente com $* .c sam. $* 9.o [nerd@aranha teste]$ Observe os valores substituídos para as macros $< e $@ . } Agora crie o Makefile com o seguinte código: # Exemplo da utilização de regras de inferência CC = gcc .c [nerd@aranha teste]$ make gcc -c sam. Isto é feito pela passagem do valor correspondente a CFLAGS na própria linha de comando quando invocando make . o dependente será um arquivo fonte em linguagem C ( .o [nerd@aranha teste]$ ls Makefile sam. Utilizando as definições da regra de inferência o make procura o arquivo sam.c.h> int main() { printf("testando 1. return(0). 12.c -o sam. $< 13.2. o alvo será criado: [nerd@aranha teste]$ ls Makefile sam. lembrando que vimos apenas o "básico do básico" desta poderosa ferramenta.o: $(CC) -c $< -o $ $@ sam.o ). . provavelmente parecida com: [nerd@aranha teste]$ make make: Nothing to be done for `sam.c ) Para um melhor entendimento da utilização de regras de inferência vamos a um exemplo: Crie o arquivo fonte sam.3\n").o'. exibirá uma mensagem de erro.o . 7. $@ 11. Se não encontrar.c .o: Observe que o Makefile tem o alvo sam. As macros $< e $@ são macros pré-definidas pelo comando make . Aqui encerramos nossa pequena tour pelo comando make . estas são as macros pré-definidas mais utilizadas e significam: 8.depuração. o arquivo alvo sem o sufixo o arquivo alvo o arquivo dependente. como foi mostrado acima na seção macros. 10. [nerd@aranha teste]$ Caso encontre. No caso do alvo ser um arquivo objeto( .

Qualquer bizú a mais não esquece de me enviar. E como dizia o meu querido professor de física Guido, lá no CMR, toda vez que terminava a aula: " ..... estudem!" (aí jogava o giz na canaleta do quadro negro e saia da sala).

Processando opções da linha de comando
Samuel Dias Neto - sdiasneto@yahoo.com.br

Para implementar o processamento da linha de comando em seus programas você pode usar as funções getopt() e getopt_long().

getopt () A função getopt() faz parte do arquivo de cabeçalho unistd.h e sua sintaxe é:
#include <unistd.h> int getopt(int argc, char *argv[], char *opcoes) extern *optarg; extern optind; extern opterrr;

onde argc e argv são os conhecidos argumentos de main e opcoes é uma string que armazena os caracteres de opção suportados pelo programa. A definição de opcoes deve ser algo como:
static char opcoes[] = "ab:c";

Observe que a letra b vem seguida de dois pontos. Isto indica que esta opção pode receber argumentos, o que não ocorre com as opções a e c. A função getopt() ainda possui três variáveis externas que devem ser conhecidas pois serão utilizadas:
·

·

optarg é uma variável ponteiro que aponta para o argumento da opção, caso esta aceite. Assim, se getopt estiver processando uma opção do tipo -Wall ou -W all, a variável optarg apontará para all. optind é uma variável inteiro que inicia com o valor 1. Ela é usada por getopt para apontar para os argumentos passados na linha de comando. Como inicia com o valor 1, getopt processa a partir de argv[1]. No final do procesamento de getopt esta variável estará apontando para o primeiro argumento do programa. Por exemplo, se sua linha de comando é:
[nerd@aranha]$ cat -v teste

·

ao final do processamento desta linha, optind estará apontando para o argumento teste.
·

opterr é uma variável que exibe ou não mensagens de erro padrão quando uma opção não definida na string opcoes é passada. Ela é inicializada com o valor 1 indicando TRUE. Quando ela tem este valor e um caractere não definido em opcoes é passado, uma mensagem de erro padrão é exibida em

stderr,

que normalmente é o monitor. Quando opterr é configurada como 0 (zero) por seu programa, indicando FALSE, a mensagem de erro padrão não é exibida se um caractere não definido em opcoes for passado. Isto é feito quando seu programa fornecer a mensagem de erro ou quando a mensagem deve ir para outro lugar em vez de stderr.

getopt

funciona da seguinte maneira:

A linha de comando é analisada e a função retorna um valor inteiro. Cada chamada da função retorna um dos caracteres de opção passados. Ao retornar o caractere de opção, a variável optarg aponta para o argumento da opção, caso este exista. Ao final da análise, o valor -1 é retornado pela função. Neste ponto optind estará apontando para o primeiro argumento do programa. Por exemplo, digamos que a linha de comando a ser processada por getopt seja:
[nerd@aranha]$ gcc -Wall -g arquivo.c

a coisa funciona assim: 1. getopt é chamada, analisa a linha de comando e retorna W. Como esta opção aceita argumentos e um argumento foi passado, optarg aponta para all. 2. getopt é chamada novamente e agora retorna g. 3. o processamento das opções termina e getopt retorna -1. optind estará com o valor 3 indicando que o primeiro argumento do programa é argv[3].

Para um melhor entendimento vamos a um exemplo usando getopt:
/* Processando opções da linha de comando com getopt() */ #include <stdio.h> #include <unistd.h> int main(int argc,char *argv[]) { int opcao; static char opcoes[] = "ab:c"; opterr = 0; while((opcao = getopt(argc,argv,opcoes)) != -1) switch(opcao) { case 'a': { printf("opção -a escolhida.\n"); break; } case 'b': { printf("opção -b escolhida.\n"); printf("esta opção recebeu o argumento %s.\n",optarg); break; } case 'c': { printf("opção -c escolhida.\n"); break; } default: printf("opção inválida!\n");

} for(;optind < argc;optind++) printf("argv[%d] = %s\n",optind,argv[optind]); return(0); }

Executando nosso programa de exemplo:
nerd@aranha:~/C$ ./opcoes -a opção -a escolhida. nerd@aranha:~/C$ ./opcoes -b teste opção -b escolhida. esta opção recebeu o argumento teste. nerd@aranha:~/C$ ./opcoes -c opção -c escolhida. nerd@aranha:~/C$ ./opcoes -d opção inválida!

getopt_long() Com getopt_long você pode processar opções longas tipo -- version. Esta função faz parte do arquivo de cabeçalho getopt.h e sua sintaxe é:
#include <getopt.h> int getopt_long(int argc, char *argv[], char *opcoes, option *opcoes_longas, int *indice_opcoes_longas)

onde argc, argv e opcoes já são conhecidos. opcoes é uma string do tipo daquela mostrada no uso de getopt() acima. O argumento opcoes_longas é um ponteiro para uma matriz de estruturas do tipo option. Esta estrutura é pré-definida em getopt.h e sua composição é:
struct option { const char *name;/* int has_arg; /* int *flag; /* int val; /* }

Nome da opção longa */ Diferente de zero se opção aceita argumento */ NULL(zero) ou um ponteiro para um valor int */ Valor de retorno */

Abaixo segue um exemplo de como deve ser a declaração da matriz de estruturas do tipo option a ser usada com getopt_long:
static struct option opcoes_longas[]= { {"help",0,0,'h'}, /* name,has_arg,flag,val */ {"version",0,0,'v'}, /* name,has_arg,flag,val */ {0,0,0,0} };

O último elemento da matriz deve ter valor zero em todos os componentes da estrutura option.

h> int main(int argc. {0.1}.e val trabalham em conjunto.\n").0.0.\n"). break.&chave. {"version".0} }. porém se a opção passada for "version". } case 'g': { printf("opção -g escolhida.'h'}.name.h> #include <getopt. opterr = 0. opcoes. static int chave = 0. while((opcao = getopt_long(argc.0. o valor 1 será armazenado na variável "chave" O argumento indice_opcoes_longas é usado da seguinte maneira: um índice interno da função getopt_long inicia em zero e é usado para comparar a opção passada na linha de comando com o elemento opcoes_longas[índice].0. flag Quando quiser usar flag você deve fazer assim: static int chave = 0. . static char opcoes[] = "hg:c". static struct option opcoes_longas[]= { {"help". &indice_opcoes_longas)) != -1) switch(opcao) { case 0: break. flag com o valor de zero e val com a letra a ser retornada. use como mostrado acima. {"version".1}.optarg).char *argv[]) { int opcao. {0.0. Neste caso.&chave. Quando você quiser que getopt_long retorne uma letra que abrevia a opção longa.'h'}.0} }. Se a opção passada for igual a opcoes_longas[índice].0.0.argv.name. simulando assim a passagem de uma opção curta.0. se a opção passada na linha de comando for "help" a função getopt_long retornará "h". Caso contrário o índice é incrementado e nova comparação é feita até o final da matriz de estruturas. opcoes_longas. printf("esta opção recebeu o argumento %s. o índice é armazenado em indice_opcoes_longas para ser usado no processamento dos outros elementos da estrutura. int indice_opcoes_longas = 0. ou seja. break.\n". Vamos a um exemplo: /* Processando opções da linha de comando com getopt_long() */ #include <stdio. case 'h': { printf("Exibindo ajuda. /* iniciando a flag */ static struct option opcoes_longas[]= { {"help".0.0.

break./opcoes_longas -b opção inválida! nerd@aranha:~/C$ .br Toda a programação em linguagem C é baseada em funções (até mesmo main() é uma função). Normalmente se usa o valor zero ou valores positivos para indicar o sucesso.0 nerd@aranha:~/C$ . } if(chave != 0) printf("Versão 1. Qualquer ponteiro não nulo indica sucesso. nerd@aranha:~/C$ . a falha é indicada pelo retorno de um ponteiro NULL. Se a função retorna um ponteiro./opcoes_longas -g teste opção -g escolhida./opcoes_longas -h Exibindo ajuda. nerd@aranha:~/C$ . nerd@aranha:~/C$ ./opcoes_longas --version Versão 1.com. funções que retornam um valor inteiro indicam erro quando retornam -1. Qualquer outro valor retornado indica sucesso. Por convenção. Como as funções que retornam valores inteiros normalmente usam o valor -1 para indicar que houve alguma falha.0\n"). } Executando o programa: nerd@aranha:~/C$ . O valor de retorno de uma função indica se esta foi executada com sucesso ou não.sdiasneto@yahoo. } default: printf("opção inválida!\n"). você pode usar o seguinte código para identificar se ocorreu algum erro numa chamada a uma função que retorna um valor inteiro: if((VARIÁVEL = FUNÇÃO) < 0) /* um erro ocorreu */ { COMANDOS PARA TRATAMENTO DO ERRO } .\n"). esta opção recebeu o argumento teste.} case 'c': { printf("opção -c escolhida./opcoes_longas --debug opção inválida! Tratamento de erro Samuel Dias Neto ./opcoes_longas -c opção -c escolhida. return(0).

quando uma função falhava.h e você já pode usar errno. Atualmente você não precisa declarar errno como uma variável externa. o erro era indicado através de uma variável externa especial chamada errno.errno).h> int main() { extern int errno.Se a função retorna um ponteiro. Exemplo: #include <stdio. ou NULL (no caso de ponteiros) e armazenava o código do tipo de erro em errno. normalmente o erro é indicado por um ponteiro nulo e você pode usar o código: if((VARIÁVEL = FUNÇÃO) == 0) /* um erro ocorreu */ { COMANDOS PARA TRATAMENTO DO ERRO } Antigamente."r")) == NULL) { printf("errno = %d\n". /* exibindo o código de erro */ exit(errno). } return(0). Além disso foram definidas várias macros que referenciam os erros codificados por errno. } O programa acima compilado e executado deve gerar uma saída assim: $ ./erro1 errno = 2 $ echo $? 2 Observe que o arquivo "arquivoX" não deve existir para este exemplo funcionar. basta incluir o arquivo de cabeçalho errno. if((arquivo = fopen("arquivoX". FILE *arquivo. Abaixo podemos ver uma lista com algumas delas: MACRO E2BIG EACCESS EFBIG EINVAL EIO DESCRIÇÃO DO ERRO Lista de argumentos muito longa Permissão negada Arquivo muito grande Argumento inválido Erro de entrada/saída .h> #include <stdlib. A função retornava -1 (no caso de valores inteiros).

.h."r")) == NULL){ printf("%s. Esta é a nova definição de errno. exit(errno). Veja um exemplo do uso de strerror(): #include #include #include #include <stdio. Observe também que o valor de errno é diferente do primeiro exemplo.strerror(errno)). Você também pode usar a função strerror() para exibir uma mensagem ao usuário indicando o erro. if((arquivo = fopen(argv[1].h> <stdlib. Esta função faz parte do arquivo de cabeçalho string."r")) == NULL){ if(errno == ENOENT){ printf("Erro: O arquivo %s não existe.\n". } fclose(arquivo). porém normalmente estas mensagens retornam em inglês. Por exemplo: #include <stdio.h> #include <stdlib. if((arquivo = fopen(argv[1]. } } fclose(arquivo). char *argv[]){ FILE *arquivo. return(0).h> /* usando strerror() */ int main(int argc.h> /* usando macros para personalizar suas mensagens de erro */ int main(int argc. } Rodando o exemplo: $ .ENOENT Arquivo ou diretório inexistente Para ver a lista completa dê uma olhada na manpage do errno: man errno A utilização destas macros permite que você personalize sua mensagem de erro. char *argv[]){ FILE *arquivo.h> <string.h> <errno./erro2 arquivoX Erro: O arquivo arquivoX não existe.\n".h> #include <errno. exit(errno).argv[1]). $ echo $? 84 Observe que "arquivoX" não existe e o programa emite a mensagem de erro personalizada.

com.return(0)..h> int main(){ char nome[21].. printf("Nome: %s. printf("Entre com seu nome :"). É importante lembrar que a string retornada por strerror() só é válida até que esta função seja chamada novamente.nome).. return(0)./errno3 arquivoX No such file or directory./scanf0 Entre com seu nome :Samuel Dias Neto Nome: Samuel. . Mas tem um bizú. digamos que o usuário resolve digitar o nome completo: $ . printf("Entre com seu nome :"). } Execução: $ . Entrada de strings Samuel Dias Neto .sdiasneto@yahoo.nome). scanf("%s".. Agora. Exemplo: /* scanf0. É . Para que scanf() leia tudo que for digitado até encontrar um caracter de nova linha faça assim: /* scanf1. } Execução: $ .c */ #include <stdio.\n". parece que não funcionou corretamente.br Para capturar a entrada de cadeias de caracteres em C podemos usar a função scanf() com o especificador de formato %s.h> int main(){ char nome[21].c */ #include <stdio./scanf0 Entre com seu nome :Samuel Nome: Samuel.

return(0). Mais um bizú: para limitar a quantidade de caracteres da entrada basta colocar o número após o caracter % no especificador: .. return(0)./scanf2 Entre com seu nome : Nome: Samuel Dias Neto./scanf2 Entre com seu nome :Um Dois Três de Oliveira Quatro Raimundo da Silva Nome: Um Dois Três de Oliveira Quatro Raimundo da Silva.h> int main(){ char nome[21]. Samuel Dias Neto Agora ficou melhor.. Houve problema. se o usuário desligado digitar uns espaços antes do nome: $ .scanf("%[^\n]". Agora funcionou legal. } Execução: $ ./scanf1 Entre com seu nome : Samuel Dias Neto Nome: Samuel Dias Neto. } Execução: . Basta inserir um espaço antes do caracter % no especificador: /* scanf2. A especificação "%[^\n]" diz para aceitar a entrada até que o caracter \n (nova linha) seja encontrado. printf("Nome: %s.nome). printf("Nome: %s.\n"./scanf1 Entre com seu nome :Samuel Dias Neto Nome: Samuel Dias Neto.nome). né ??? E se o nome do cara for muito grande ??? $ ..nome).nome). printf("Entre com seu nome :"). E. falha de segmentação. scanf(" %[^\n]".c */ #include <stdio. Falha de segmentação Ops ..\n".

\n".nome). pois em C as strings são consideradas arrays de caracteres. Observe também que não precisamos do operador "endereço de" ( & ) ao indicar a variável nome na função scanf() ( scanf(" %20[^\n]". . Agora não houve falha de segmentação. return(0).h> int main(){ char nome[21]./* scanf3. } Execução: $ .nome). printf("Nome: %s./scanf3 Entre com seu nome :Um Dois Três de Oliveira Quatro Raimundo da Silva Nome: Um Dois Três de Oliv. Observe que ao declarar a variável para armazenar o nome ( char nome[21]) sempre colocamos um caracter a mais para armazenar o caracter nulo que encerra uma string. printf("Entre com seu nome :").c */ #include <stdio. E ao passar um array na verdade estamos passando o endereço do primeiro elemento do array.nome) ). scanf(" %20[^\n]".

Sign up to vote on this title
UsefulNot useful