Escolar Documentos
Profissional Documentos
Cultura Documentos
#include <stdio.h>
int main()
{
printf("Hello, world\n");
}
O que este programa faz é basicamente escrever na saída padrão o string "Hello, world".
Alguns detalhes deve ser explicados:
Outro exemplo:
Variáveis, constantes, expressões e atribuição
O exemplo a seguir ilustra alguns conceitos importantes em C:
#include <stdio.h>
int main()
{
int a,b,c,soma;
a = 1; b = 2; c = 3;
soma = a + b + c;
printf("soma = %d\n",soma);
}
1
int a, b, c, soma;
declara a, b, c e soma como variáveis do tipo inteiro. Uma variável do tipo inteiro pode
receber qualquer valor inteiro permitido na máquina. Os comandos
a = 1; a = 2; c = 3;
são comandos de atribuição. Um comando de atribuição indica que uma variável assume
passa a assumir o valor de uma expressão. Nos comandos acima, as expressões são
definidas pelas constantes inteiras 1, 2 e 3. Esses comandos são executados na ordem
em que aparecem. Ao atribuir um valor a uma variável, o valor anterior da mesma é
simplesmente perdido (uma variável sempre tem um único valor. Considere-se por
exemplo a sequência de comandos abaixo:
a = 1; a = 2; a = 3;
Após a execução dessa sequência de comandos, o valor de a será igual a 3 (a cada
atribuição, o "valor anterior" da variável a é destruído). O valor de uma variável pode ser
utilizado numa expressão ( soma=a+b+c ). Isso vale também para a variável à esquerda
do sinal de atribuição ("=").
Exemplo:
a = 1;
a = a + 2;
a = a + 3;
Em C, todo comando encerra com um " ; ". A separação de linhas tem a mesma função
que um espaço em branco. A sequência de comandos acima é equivalente a
a = 1; a = a + 2; a = a + 3;
O comando printf
O comando printf é utilizado para escrever dados em forma de texto na saída padrão ou
num arquivo. Por enquanto, estamos utilizando a forma mais simples desse comando:
#include <stdio.h>
int main()
{
int a,b,c;
a = 1; b = 2; c = 3;
printf("valor de a:%d valor de b: %d valor de c:%d \n ",a,b,c);
}
Neste exemplo, a primeira ocorrência de "%d" se refere à primeira variável da lista (a), a
segunda à segunda variável (b) e assim sucessivamente. O par "\n" está sendo utilizado
2
para representar o caracter new line que causa a mudança de linha na saída padrão. O
resultado da execução desse programa deverá ser:
#include
int main()
{
int a,b,c;
scanf("%d %d %d", &a,&b,&c);
printf("a:%d b:%d c:%d \n",a,b,c);
}
Os 'comandos' scanf e printf na verdade são funções definidas na biblioteca stdio que
internamente chamam funções da biblioteca padrão que por sua vez se utilizam dos
serviços oferecidos pelo sistema operacional para realizar as operações de leitura e
escrita.
As funções scanf e printf trabalham basicamente com sequências de caracteres. Elas
têm a capacidade de converter caracteres para outros tipos de dados e vice-versa. Essa
conversão é indicada na sequência de caracteres através de "especificadores de
formato", sempre precedidos de '%'. Nos exemplos apresentados até aqui, utilizamos
apenas "%d" para indicar a conversão de caracteres para inteiros (no caso de scanf) ou
de inteiros para caracteres (no caso de printf).
O caractere '&' antes do nome de cada variável a ser lida indica referência ou endereço
da variável. É através dessa referência ou endereço que o valor da mesma será
atualizado após a leitura do dado correspondente.
Parentesis podem ser utilizados para forçar o cálculo de uma expressão numa
determinada ordem. Exemplos:
a + (b / 2)
(a * 2) + 1
((((a*2) + 1)*2)+1)*2+1)
3
Uma expressão como a + b * c será calculada como a + ( b * c ) porque o cálculo da
mesma leva em conta a precedência entre os operadores. Em C essa precedência é
definida da seguinte forma (para os operadores aritméticos):
+, - menor precedência
*, /,% maior precedência
Os "operadores combinados"
Em programação, são frequentes comandos como:
a = a + b;
x = x - y;
p = p * 2;
Nesses comandos, o valor a ser atribuído à variável à esquerda é o resultado de uma
operação na qual o valor dessa mesma variável é utilizado. Em C é possível escrever
esse comando de forma mais compacta através da "combinação" da operação\ com a
atribuição (+=, -=, *=, etc.). Os comandos mostrados acima, por exemplo, poderiam ser
reescritos como:
a += b;
x -= y;
p *= 2;
Os operadores ++ e --
Outro tipo de comando comum em programação é aquele no qual apenas se incrementa
ou decrementa o valor de uma variável de 1. Em C é possível escrever esse tipo de
comando através dos operadores "++" e "--". Exemplos:
++i; equivalente a i = i + 1;
++i; equivalente a i = i - 1;
Esses operadores podem ser utilizados de duas formas: antes ou depois do operando (p.
ex. ++i ou i++). No primeiro a operação é feita antes do uso do valor do operando. No
segundo caso, a operação é feita depois do uso do valor. Exemplos:
Comentários
Um comentário em C tem a seguinte forma:
/* texto qualquer */
Comentários podem aparecer em qualquer lugar do programa onde caberia um
espaço (' '). Seu significado é exatamente o mesmo de um espaço em branco.
Comentários delimitados por "/*" e "*/" podem ocupar várias linhas.
4
#include <stdio.h>
/*
Determina o "peso ideal" de uma pessoa a partir da sua altura.
Trata-se apenas de um exemplo de programação - não segue nenhuma
orientação médica.
*/
int main()
{
int a; /* altura */
int p; /* peso */
p = (a-119)*5/8+45;
printf("Peso ideal: %d \n",p);
}
O Comando Condicional
O comando condicional permite alterar a sequência de execução dos comandos com
base numa condição. O comando condicional em C tem duas formas básicas:
5
Exemplos:
...
a < (h+5)
...
a <= h
...
x == 10
...
if ( a > 200) printf("altura acima do limite\n");
...
if ( a < 40) printf("altura abaixo do limite\n");
...
Esses operadores têm todos a mesma precedência, que é menor que a precedência dos
operadores aritméticos. O resultado de uma comparação será um valor igual a zero de a
condição testada resultar em falso ou um valor diferente de zero se a condição testada
resultar em verdadeiro. O valor diferente de zero indicando verdadeiro não é especificado
na definição da linguagem.
Mais exemplos
...
if(a != b) a = a-b; else b = b - a;
...
if(a != b) a -= b; else b -= a;
...
if(x == 10) y = 1;
else if (x == 11) y = 2;
else y = 0;
...
Comando Composto
Em algumas situações é necessário tratar uma sequência de comandos como um único
comando. Isso é possível através de '{' e '}', que delimitam um comando composto.
Exemplo:
...
if(a < b) { t = a; a = b; b = t; }
else i = i+1;
...
O Comando while
O comando while tem a forma
e indica que comando deve ser executado repetidamente enquanto condição tiver tiver
um valor diferente de zero (verdadeiro). A condição é calculada antes da execução de
comando e recalculada antes de cada repetição.
6
Exemplo
#include <stdio.h>
int main()
{
int s,i;
s = 0; i = 1;
while(i <= 10) { s = s + i; i = i+1; }
int main()
{
int A,B, a,b;
O comando for
O comando for é outro tipo de comando repetitivo, com uma estrutura um pouco mais
elaborada. Sua forma geral é a seguinte:
7
onde
• expressão1 é calculada uma vez antes do início da execução
• expressão2 indica a condição de repetição
• expressão3 é executada a cada passo, depois de comando
O comando for, como mostrado acima é equivalente a um comando while da forma:
expressão1;
while( expressão2 )
{
comando
expressão3;
}
O termo expressão1 está sendo utilizado acima em lugar de comando. A rigor um
comando em C é uma expressão, que devolve um valor. Essa característica ainda não
está sendo utilizada neste texto.
Exemplo
#include <stdio.h>
int main()
{
int s,i;
s = 0;
for(i=1; i <= 10; ++i) s+=i;
#include <stdio.h>
# define N 10
int main()
{
int s,i;
s = 0;
for(i=1; i <= N; ++i) s+=i;
8
printf("A soma dos inteiros de 1 a %d é %d\n",N,s);
}
Vetores
Um vetor é um sequência de valores de um mesmo tipo que podem ser acessados a
partir da sua posição. Exemplo: declaração de um vetor de inteiros, com 10 elementos:
...
int v[10];
...
Os elementos de um vetor podem ser acessados a partir da sua posição, ou índice, e
usados no programa como qualquer outra variável. Os índices de um vetor de N
elementos variam de 0 a N-1 (0 corresponde ao primeiro elemento e N-1 corresponde ao
último).
Exemplos
...
v[0] = 1;
v[1] = 2;
v[2] = v[0] + v[1];
...
O índice para acesso ao elemento de um vetor pode ser uma variável ou uma expressão
inteira. Exemplos:
...
for(i=0; i < N; i++) v[i] = 0;
...
v[n-k+1] = v[n-k+i];
...
Outro Exemplo
/*
leitura de uma sequência de 10 valores e determinação do maior e menor elemento
*/
#include <stdio.h>
int main()
{
int t[10];
int i, max, min;
9
Valor Inicial de um Vetor
Ao declarar uma variável é possível definir um valor inicial para a mesma. Exemplo:
int k = 21;
Isso é possível também no caso de um vetor e nesse caso, a sequência de valores
aparece entre '{' e '}', separados por vírgula. Exemplo:
/* criação da tabela */
for(i = 0; i < 5; i++)
for(j = 0; j < 10; j++) tab[i][j] = k++;
/* escrita da tabela */
for(i = 0; i < 5; i++)
{
for(j = 0; j < 10; j++) printf(" %d ",tab[i][j]);
printf("\n");
}
}
Exemplos
#include <stdio.h>
int main()
{
float valor = 100.0;
float taxa = 0.005;
int n = 12;
int i;
10
printf("valor inicial: %7.2f \n",valor);
for(i=0; i < n; i++) valor += valor*taxa;
printf("valor final: %7.2f \n",valor);
}
Neste exemplo, no comando printf, o especificador de formato "%7.2f" está sendo usado
para formatar um valor do tipo float, ocupando um campo de 7 caracteres, com duas
casas após o ponto decimal.
#include <stdio.h>
int main()
{
char x;
for(x = 'a'; x <= 'z'; x++) printf("%c",x);
printf("\n");
}
Neste exemplo, o operando ++ está sendo aplicado a uma variável do tipo char. O
resultado dessa operação é o "caracter seguinte" na sequência de caracteres da
máquina.
Ainda neste exemplo, a sequência o especificador de formato "%c" está sendo usado
para indicar que a variável correspondente será escrita como um caracter.
Funções
Funções em C permitem agrupar uma sequência de operações sob um nome através do qual é
possível executar essa sequência. Exemplo:
...
int max(int i, int j)
{
if (i > j) return i;
else return j;
}
...
O exemplo acima mostra a definição da função max, que ao ser executada retorna um
valor do tipo int. Os comandos entre '{' e '}' correspondem ao corpo da função, que é
executado toda vez que a função for ativada (ou chamada).
As variáveis i e j, declaradas entre parentesis, são os parâmetros da função. Estes são
utilizados pelo programa que usa a função para "passar" os valores a serem usados pela
função ao realizar os seus cálculos.
Para chamar uma função num programa, usa-se o nome da mesma, seguido dos valores
que devem ser associados aos parâmetros, entre parêntesis. Exemplos:
...
int main()
{
int x,y,z, m;
scanf(" %d %d %d",x,y,z);
m = max(x,y);
m = max(m,z);
printf("m: %d\n",m);
}
Neste exemplo, os comando "m = max(x,y);" é usado para chamar a função max,
passando como valores para i e j o valor das variáveis x e y. O valor passado como
11
parâmetros nesse caso poderia ser qualquer valor, definido por uma constante, uma
variável, ou uma expressão. Uma chamada válida poderia ser "max(10,x+y);" (se isso fizer
sentido no programa sendo escrito).
A chamada à função "max" retorna um valor do tipo inteiro, que pode ser utilizado no
programa em qualquer situação onde um valor inteiro é válido. Por exemplo, a sequência
de comandos
m = max(x,y);
m = max(m,z);
poderia ser substituída por
m = max(max(x,y),z);
O programa do exemplo acima poderia ser reescrito de forma mais compacta como:
int main()
{
int x,y,z, m;
scanf(" %d %d %d",x,y,z);
printf("m: %d\n",max(max(x,y),z));
}
A partir da definição de uma função num programa, ela passa a estar disponível como se
fosse uma nova facilidade da linguagem, como se a mesma pudesse ser "extendida" em
função das necessidades de uma aplicação. Esse é um recurso poderoso e que aparece
em praticamente todas as linguagens de programação.
É possível também utilizar funções definidas em módulos externos, combináveis com o
programa. É exatamente isso que acontece com as funções utilizadas até agora para
fazer entrada e saída, printf e scanf: essas funções estão definidas na biblioteca de
funções stdio.h.
Outro exemplo
A função abaixo calcula o máximo divisor comum entre dois inteiros positivos:
12
As funções getchar e putchar
As funções getchar e putchar, definidas na biblioteca stdio são orientadas à leitura e
escrita de caracteres. Na sua forma mais simples, elas leem e escrevem caracteres pela
entrada e saída padrão. O exemplo a seguir mostra o seu uso:
c = getchar(); /* le um caracter */
Outro exemplo
O programa abaixo conta o número de linhas do texto lido a partir da entrada padrão:
13
int main() ?
Nos exemplos mostrados até aqui, o programa principal, é declarado sempre como
...
int main() { ... }
...
Essa declaração segue o mesmo padrão usado na declaração de uma função. Na
verdade, trata-se realmente de uma função. O UNIX inicia a execução do programa a
partir da função cujo nome é main.
Essa é uma convenção adotada pelo UNIX e usada por outros sistemas operacionais
(uma exceção é o Windows no qual a execução do programa se inicia a partir de uma
função chamada WinMain()).
A função main pode ou não retornar um valor. Sua declaração poderia ser da forma
int main()
{
int x,y,z, m;
scanf(" %d %d %d",x,y,z);
m = max(x,y);
m = max(m,z);
printf("m: %d\n",m);
}
Se duas funções declaram variáveis com nomes iguais, como cada declaração é local a
cada uma das funções, essas variáveis são na verdade duas variáveis independentes,
que por acaso têm o mesmo nome. Exemplo:
#include <stdio.h>
int f(int n)
{
int i,s;
s = 0;
for(i=1; i<=n; i++) s += i;
return s;
}
int g(int n)
{
int i,p;
p = 1;
for(i=1; i <=n; i++) p *= i;
return p;
}
14
int main()
{
...
int i,p,s;
...
}
Assim como as variáveis locais, os parâmetros de uma função são locais à mesma.
Uma variável global é uma variável declarada "fora" de uma função e pode ser utilizada
por qualquer função do programa. Um exemplo:
#include <stdio.h>
#define NMAX 10
int insert(int v)
{
if(tSize >= NMAX-1) return -1;
tab[++tSize] = v;
return tSize;
}
int sort()
{
int i,j,t;
for(i=0; i < tSize-1; i++)
for(j = i+1; j < tSize; j++)
if(tab[i] > tab[j])
{
t = tab[i]; tab[i] = tab[j]; tab[j] = t;
}
}
void printTab()
{
int i;
printf("tab: ");
for(i=0; i < tSize; i++) printf("%d ",tab[i]);
printf("\n");
}
int main()
{
init();
insert(5); insert(8); insert(2); insert(12);
sort();
15
printTab();
}
Passagem de Parâmetros
Os exemplos de funções mostrados até agora, definem um conjunto de parâmetros que
têm um dos tipos primitivos da linguagem (int, char, float, double ). Um exemplo:
...
float max(float a, float b)
{
if(a > b) return a; else return b;
}
...
Ao se chamar essa função, os valores de cada um dos parâmetros efetivos serão
associados aos parâmetros formais a e b. Exemplos:
...
x = max(10.0, z-4.3);
p = max(r,s);
w = max(10.0,max(x,p));
...
No primeiro exemplo, o valor 10.0 é associado ao parâmetro formal a e o valor da
expressão "z-4.3" é associado ao parâmtro b. Esse tipo de passagem de parâmetros é
chamado de passagem por valor, e é a forma básica de passagem de parâmetros em C.
A passagem de parâmetros por valor é aplicável à maioria das situações de programação.
No entanto existem casos em que é necessário extende-la. Suponhamos por exemplo
que um programa necessite com frequência trocar o valor de duas variáveis e que que a
mesma deverá ser aplicada a diferentes pares de variáveis ao longo do programa. Se
implementarmos essa função da forma como mostrada abaixo, ela não apresentará a
funcionalidade desejada:
int *p;
Essa declaração define a variável p como uma referência a um inteiro (que pode ser uma
outra variável). Se quisermos, por exemplo atribuir um valor à variável referenciada por p,
podemos fazer o seguinte:
*p = 10;
ou ainda, para usar o valor da variável referenciada por p numa expressão
x = *p + 10;
O operador de referência &
Para que variáveis do tipo referência como p usada nos exemplos acima tenham alguma
utilidade, é necessário que a linguagem permita que se indique que "p referencia uma
16
certa variável". O operador '&' serve justamente para esse propósito: se x é uma variável
qualquer, &x é a referência a essa variável. Um exemplo:
...
int x = 1;
int *p;
...
p = &x; /* o valor de p e uma referência a x */
*p = 10;
printf("valor de x: %d\n",x);
..
Neste exemplo, a o comando "p = &x;" faz com que p passe a "referenciar" ou "apontar" para a variável x.
Isso significa que "*p" (ou seja, "a variável referenciada por p" passa a ser x. Qualquer alteração em *p é
equivalente a uma alteração em x (e vice-versa, obviamente). O valor escrito pelo comando "printf" será
portanto "10".
Uso de referências em parâmetros
O tipo referência pode ser usado nos parâmetros de uma função. Por exemplo, a função
"troca" pode ter o efeito desejado se utilizarmos os parâmetros de forma adequada:
17
k = 0;
for(i=0; i < n-1; i++)
if(v[i] > v[i+1])
{
troca(&v[i],&v[i+1]); k++);
}
} while(k!=0);
}
No exemplo acima, "v[]" denota um vetor, cujo tamanho não é fixado na função, já que o
mesmo depende do parâmetro efetivo. O segundo parâmetro, "n" indica o tamanho do
parâmetro efetivo e deve ser preenchido ao se chamar a função. O exemplo abaixo
mostra alguns usos da função "ordena".
...
int a[10], m[12][31];
...
ordena(a,10);
ordena(m[5],31);
...
gcc prog.c
Esse comando, causa a tradução do programa fonte em C contido no arquivo "prog.c"
para a linguagem de máquina. O programa executável gerado, neste caso, vai estar num
arquivo chamado "a.out". Esse é o nome padrão para a saída do compilador.
Caso o programa fonte contenha erros de compilação, estes serão indicados na saída
padrão (de forma nem sempre amigável). Para a correção dos erros, usa-se novamente o
editor de textos.
O nome "a.out" nem sempre é o mais conveniente para um programa executável. Além
disso, pelo fato de ser sempre o mesmo, o conteúdo anterior desse arquivo é destruído a
cada compilação. Uma saída é renomear o arquivo após cada compilação (p. ex. "mv
a.out prog"). Outra possibilidade mais interessante é usar uma opção de compilação
indicando o nome desejado para o progrma executável. Isso é feito através da opção "-o
nome". Exemplo
18
gcc -o prog prog.c
Ativação do programa
A ativação do programa a partir da shell é feita da mesma forma que a ativação dos
comandos padrão do UNIX (estes, na verdade, são programas executáveis como
qualquer outro).
Strings
Quando escrevemos uma cadeia de caracteres ("string") num programa, a mesma é
compatível com os tipos "char *" e "char[]". Exemplo:
#include <stdio.h>
int main()
{
char * texto = "Um título";
char nome[] = "João da Silva";
char *dias[7] = {
"segunda","terça", "quarta",
"quinta", "sexta", "sábado",
"domingo"
};
int i;
printf("%s\n",texto);
printf("%s\n",nome);
for(i=0; i < 7; i++) printf(" %s ",dias[i]); printf("\n");
}
No exemplo acima,
• texto é uma referência a um string, que aponta para o string "Um título"
• nome é um vetor de caracteres, cujo tamanho é determinado a partir do valor
atribuído a ele ("João da Silva");
• dias é um vetor de 7 apontadores para caracteres.
Em qualquer um dos casos, os strings são representados como uma sequência de
caracteres delimitada pelo caracter "null", que é o caracter cuja representação interna é
igual a zero. A função abaixo usa essa propriedade de um string para determinar o seu
tamanho.
int tamanho(char s[])
{
int i;
for(i=0; s[i] != 0; i++);
return i;
}
Strings constituem um recurso importante em programação e as bibliotecas padrão de C
oferecem um extenso conjunto de funções para sua manipulação. Algumas dessas
funções:
• int strlen(char * str) - devolve o tamanho de um string
• char *strcpy(char *dest, char *origem) - copia um string
• char *strcat(char *dest, char *origem) - concatena 2 strings
• char *strcmp(char *str1, char *str2) - compara 2 strings
19