____ _ _ _ _
| _ \ | | | | | | (_)
| |_) | ___ | |_ ___ ___ ___ | | | |_ __ ___ __
| _ < / _ \| __/ _ \/ __/ _ \| | | | '_ \| \ \/ /
| |_) | (_) | || __/ (_| (_) | |__| | | | | |> <
|____/ \___/ \__\___|\___\___/ \____/|_| |_|_/_/\_\
...:::Ajudando povo Unix Like desde 2006:::...
www.bugsec.com.br
ATENÇÂO ESTE PAPER é BETA, ainda está em escrita
-------------------------------------------------------------------------------------------
INICIANDO em
____ __ _________
| | |__| ____ ____ __ _______ ____ ____ _____ \_ ___ \
| | | |/ \ / ___\| | \__ \ / ___\ / __ \ / \ / \ \/
| |___| | | \/ /_/ | | // __ \_/ /_/ X ___/| Y Y \ \ \____
|_______ \__|___| /\___ /|____/(____ /\___ / \___ |__|_| / \______ /
\/ \//_____/ \//_____/ \/ \/ \/
|##|
) (
( )
_) (_
| | , ,
|------| / GNU \
| GCC | ((__-^^-,-^^-__)) Autor: Antonio "Cooler_"
|~~~~~| |VODKA | `-_---' `---_-' Contato: c00f3r@gmail.com
`--,--' |------| `--|o` 'o|--' -----------+
| | | \ ` / \-\\
__|__ |______| ): :( \ / / \ \\
:o_o: / \ / | \\
"-" \ ------\ / /
|/ \| |/ \|
14/11/10 | | | |
() () () ()
Indice
==========
x00-Introdução a linguagem C
x01-Separando o material
x02-O que é um Compilador
x03-Iníciando em C
x04-int - interger - inteiro
x05-float - real
x06-Char - caracter - alfanumérico
x07-Ponteiro "Pointer"
x08-Casting
x09-Condições
x10-Estilos de programação até Aqui
x11-Loops em C laços com goto,while,do e for
x12-Arrays "Vetores,matrizes"
x13-Funções
x14-Usando Switch,break e continue
x15-Melhorando a Peformance
x16-Bibliografia
x17-Agradecimentos
aperte ctrl+f "x15" por exemplo caso queira ir direto ao capítulo 15
------------------------------------------------------
x00-Introdução a linguagem C
--------------------------
"Senta aí que lá vem história!!" - Ra Tim Bum - 1992
Linguagem C foi inventada em 1970 por Dennis Ritche, teve grande influência
do seu amigo Ken Thompson que criou a linguagem "B",ambos trabalharam na AT&T
Bell Labs,está foi uma época bem interessante Dennis Ritche e Ken thompson
fizeram um Unix em C,já tinham um Unix com assembly e tal porem não era portável,
se não me engano foi o "sistem V" o primeiro Unix a usar C,em fim nesta época
erá duro fazer um programa portável com Assembly.Em 1978, Brian Kernighan(que é
um dos criadores da linguagem AWK) e Dennis Ritchie publicaram a primeira edição
do livro The C Programming Language.Esse livro, conhecido pelos programadores
de C, como "K&R", serviu durante muitos anos como uma especificação informal da
linguagem. A versão da linguagem C que ele descreve é usualmente referida como
"K&R C".
Curiosidades:
*Em 1983, Dennis Ritche e Ken Thompson receberam o prémio Turing "pelo seu desenvol-
vimento de teoria de sistemas operativos genéricos e especialmente pela sua
implementação do sistema operativo UNIX."
A denominação do prêmio é homenagem a Alan Mathison Turing, um matemático britânico
considerado um dos pais da ciência da computação moderna. O prêmio é conhecido como
o "Prêmio Nobel da computação". É patrocinado pela Intel Corporation e acompanhado
atualmente por um prêmio monetário no valor de 250.000,00 USD (duzentos e cinquenta
mil dolares americanos).
*Também receberam premio nacional de tecnologia pelas mãos do presidente Bill Cliton
*Dennis Ritche Nascido em Bronxville, Nova Iorque, Ritchie formou-se em física e
matemática aplicada pela Universidade de Harvard.
*Ken thompson criou a codificação de caracteres UTF-8,construiu programas para jogar
xadrez contra o campeão do ramo Kasparov.
*Tanto Ken Thompson como Dennis Ritche tem um projeto com Rob Pike de sistema
Operacional chamado Plan9 e um sistema operacional hospedeiro chamado inferno
ambos são livres
*Em 1980, Bjarne Stroustrup do mesmo laboratório Bell Labs criou o C++ que seria
um "C + smalltalk" ou seja linguagem C com classes,C orientado a objetos,fui meio
infeliz nesta comparação que fiz, mesmo por que C++ é diferente de C ansi em vários
aspectos não vou discutilos aqui...
algumas refêrencias rápidas:
http://plan9.bell-labs.com/who/dmr/
http://plan9.bell-labs.com/who/ken/
http://c-faq.com/ansi/index.html
http://groups.google.com/group/comp.lang.c/
x01-Separando o material
--------------------------
O paper teve início com história da linguagem pois isso é muito importante
dá um mundo para o que vamos estudar,o que adianta estudar algo sem saber
de onde veio as cegas ? durante muito tempo eu aprendi as cegas na faculdade,
não desejo isso para nimguém...
em fim para continuar a ler este paper você deverá separar o seu "Tool Box"
para trabalhar com linguagem C,primeira coisa é usar um bom editor como VIM,
EMACS,gedit caso não queira nenhum desses tem o jedit entre outros,segundo
item seria ter um compilador eu pessoalmente uso o GCC sugiro o mesmo.
exemplo de instalação do compilador,editor de texto,desbuger em um Linux
baseado em GNU Debian...
apt-get install gcc g++ make gdb vim
exemplo em Linux baseado em Redhat
yum install gcc g++ make gdb vim
e assim vai gentoo use merge,arch pacman,slack installpkg etc...
caso use algum *BSD,MacOS ou OpenSolaris procure nos Ports dos mesmos
http://www.macports.org/
http://www.freebsd.org/ports/
http://gcc.gnu.org/
Maioriados Unix Like vem com GCC como default,a não ser que seja
minimalista de mais...
Caso você use windows gcc tem uma versão para Windows que se chama MinGW.
É a mesma instalada pelo ambiente Dev-C++ ou pelo CodeBlocks.
http://www.mingw.org/
http://www.codeblocks.org/
Quanto ao editor tendo um highlights(letras coloridas quando você
está editando o código) já da para quebrar o galho eu mesmo prefiro
o "VIM". terceiro ferramenta um desbugador,depurador o GDB já resolvi
isso,lembrando que o CodeBlocks já tem editor e debuger se não me engano...
instalado o GCC caso use Unix Like como Linux,BSD etc,de o comando
man gcc
assim você vai ver o manual do GCC caso use windows não fique triste
veja nos link
http://gcc.gnu.org/onlinedocs/gcc-4.5.0/gcc/
http://gcc.gnu.org/onlinedocs/gcc-4.5.0/gcc.pdf
não é para ler tudo de cara, mas deixe numa gaveta como referencia futura...
se você poder ter o livro do K&R ajuda também,outro bom livro como "C primer plus"
até mesmo "practical C". Estudar códigos de outros programadores ajuda seu
conhecimento na linguagem a subir exponencialmente.
x02-O que é um Compilador
-------------------------
Sendo curto e direto ao Ponto,Compilador ele pega o código escrito de alto nível
por um editor qualquer,compila através de automatos,geradores léxicos,condições
para execuções de certas funções para gerar o código de máquina...
se o scaner léxico acusar algo fora do padrão da linguagem então é retornada
uma saída de erro "syntax error before x bla bla..."
por exemplo uma linguagem X de programação, usa função "escreva()" para mostrar
uma saída,e todo fim de uma função nesta nossa linguagem tem que ter "string"
de ";"(ponto e virgula),exemplo prático:
escreva(ola mundo)
compilador vai ler letra por letra
[e][s][c][r][e][v][a][(][*][)][][][]...--> campos com espaços nulos
\ | | | | | / |
se for (escreva) verifica se tem ";"
mostre o que se não tiver retorna com erro
tem entre parentes
ao ver que o ultimo campo não tem ";" para finalizar vai retornar erro de
sintaxe, e irá parar tudo,caso a sintaxe esteja OK o compilador vai continuar
com sua tarefa,em outras palavras veja o desenho:
_______ ________
| | |01010101|
|code | |01010101|
| |------->> Compilador compila então --->> |10101010| <<---- Executa
| Ola! | |01010101| retorna saida
+-------+ +--------+ "Ola!"
Compilador pega código de alto nível e passa para baixo nível,ou seja nível
de máquina,tem muitas paradigmas das quais poderia falar aqui mas não é meu
objetivo explicar o grande paradoxo que tem dentro dos compiladores.
Se o programa faz referência a funcoes que estejam definidas em outros
arquivos objetos (como as bibliotecas padroes libc e glibc) entao o linka-
dor une tudo fazendo um executavel! Nosso programa está pronto.
caso queira saber mais os internals sugiro ler o "Dragon Book"
"Compilers: Principles, Techniques and Tools", 1986
tem este apelido por ter um dragão na capa, eu tenho este livro e acredite
eu li todo, infelizmente como não pratiquei todo o conteudo não fixou no meu
cérebro,eu estudei mais para ficar bom em parsers...
http://dragonbook.stanford.edu/
se você não saber resolver algoritmos de árvores,grafos nem perde seu tempo
lendo hehehe.Bom quem Domina ASSEMBLY e leu isso deve ter achado bobo mas
é apenas uma explicação para iniciantes...
x03-Iníciando em C
------------------------------------
Bom Primeira paradigma que devemos ter é que os códigos não vem do além,cada
função em linguagem C vem de uma "header","API" ou popularmente "biblioteca".
Primeira "Header" que vamos usar é a <stdio.h> que tem conformidade com ANSI
X3.159-1989 (‘‘ANSI C’’),siglas da "header" seria standard input/output library
traduzindo ai "biblioteca padrão de entrada e saida".Isso em um sistema Unix Like
você resolveria com comando "man stdio",caso não use um sistema Unix like ai
está alguns manuais.
http://www.manpagez.com/man/3/stdio/ man em EN
http://man.gnusquad.org/stdio/section-3/pt/ man em PT
Com esta "header" que vamos pegar entrada do usuário com nossos programas usando
função "scanf",saída vamos usar a função "printf".
vamos a um "hello world" parece que todo paper de programação tem isso he he
---------------------------code
main() {
puts("ola");
}
---------------------------EOF
por que "main() { code }" ?
"main()" nada mais é que uma função,no caso é a primeira função que C lê
como padrão...
escreva o código num paper txt, e renomeio para extensão ".c"
veja seguencia de comando que mandei no terminal
vim programa.c <---usei o vim para escrever o código no arquivo "programa.c"
gcc programa.c -o programa <--- compilei com GCC e usei argumento "-o" para apontar a saida
./programa
teve como saida a palavra "ola"
a função "puts()" não vem de uma "header" repare que não apontamos para nenhuma
ou seja não usamos <stdio.h>.caso use windows use uma "IDE" como dev C++ ou codeblocks
nos menus dele tem opção de compilar e executar,"\n" dentro dos parenteses seria
comando "new line" par apular uma linha depois da "string".
Nosso exemplo foi muito minimalista,vamos trabalhar com saídas só que usando
a função "printf()" e proveitando para explicar variáveis,expressões aritméticas e
funções.Bom agora sim vamos usar <stdio.h> para apontar para ela vamos usar
#include "stdio.h"
ou
#include <stdio.h>
vamos a um exemplo
---------------------------code
#include <stdio.h>
/* isso é um comentario */
int main() {
//outra forma de comentar
// veja função "printf"
printf("ola\n");
return 0;
}
---------------------------EOF
veja a função "main()" agora é um "int" ou seja inteiro
precisa retornar algo no fim da função então justifica no final "return 0;"
O pre-processador remove comentários do programa que seria iniciados com "//" ou
"/* conteudo */",interpreta diretivas especiais do pre-processador. Estas
diretivas sao iniciadas por # que pode ser um apontador para header ou macros
exemplo de macro
diretiva #define que eh assim:
#define MAX_SIZE 100
Faz uma substituicao completa por todo arquivo trocando MAX por 100.
---------------------------code
#include <stdio.h>
#define MAX 100
int main() {
printf("numero %d \n", MAX);
return 0;
}
---------------------------EOF
Explanação de o que ocorreu dentro da função "printf()"
pula
linha número inteiro
| /
printf("string %d \n", 21);
| |
texto \
qualquer argumento que define
tipo de variável
no caso número inteiro
integer "int"
então usamos "%d"
d = decimal
Só pro curiosidade algumas sequencias de escape:
\a (alert) -> Produz um alerta visivel ou audivel.
\b (backspace) -> Muda a posicao atual 1 caractere antes.
\f (form feed) -> Move a posicao atual para o inicio da proxima pagina.
\n (new line) -> Move a posicao atual p/ posicao inicial da proxima linha.
\r (carriage return) -> Move a posicao atual p/ a posicao inicial da linha.
\t (horizontal tab) -> Move a posicao atual p/ a proxima posicao de tabulacao definida na linha.
\v (vertical tab) -> Move a posicao atual p/ a proxima posicao de tabulacao vertical definida.
x04-int - interger - inteiro
---------------------------
variavel inteira é aquela que assume valores inteiros.
O tipo basico para um inteiro é "int", ou seja, declaramos um inteiro
assim:
int x;
ou
long int x;
O valor de um inteiro assim declarado é um inteiro de 32bits ou seja,
pode ir de -2147483648 a 2147483647. Inteiros de 16 bits ainda podem ser
declarados, bastando anexar a palavra short antes de int:
short int x;
ou
short x;
Isso faz com que x varie de -32768 a 32767. Um inteiro pode ser
declarado para ser positivo apenas, bastando colocar a palavra
unsigned (sem sinal), então temos:
unsigned shor int x;
seria uma declaracao no qual os valores de x podem ir de 0 a 65535 (2^16-1)..
unsigned long int z;
seria uma declaracao no qual os valores de z podem ir de 0 a 4294967297 (2^32 - 1).
Segue aqui uma tabela com os principais tipos de declaradores para inteiros:
+---------------------+--------------------+
| 16 bit | 32 bits |
|---------------------|--------------------|
| short | long |
| short int | long int |
| unsigned short int | unsigned long int |
| signed short int | signed long int |
| | unsigned int |
| | signed int |
+---------------------+--------------------+
veja por si
---------------- Code
#include <stdio.h>
int main() {
printf("The 'int' data type is\t\t %d bytes\n", sizeof(int));
printf("The 'unsigned int' data type is\t %d bytes\n", sizeof(unsigned int));
printf("The 'short int' data type is\t %d bytes\n", sizeof(short int));
printf("The 'long int' data type is\t %d bytes\n", sizeof(long int));
printf("The 'long long int' data type is %d bytes\n", sizeof(long long int));
printf("The 'float' data type is\t %d bytes\n", sizeof(float));
printf("The 'char' data type is\t\t %d bytes\n", sizeof(char));
return 0;
}
---------------- EOF
Os operadores aritmeticos servem para realizar operacoes aritmeticas, ou
seja, aquelas que envolvem as operacoes basicas que aprendemos logo nos
primeiros anos da escola: soma, subtracao, multiplicacao e divisao. As
expressoes sao do tipo (membro1 operador membro2) e o valor retornado pela
expressao eh exatamente o resultado da operacao.vamos a um exemplo usando
expressões aritméticas conforme a tabela.
+---------------------------------------------------------------------------+
| Adição | Subtração | Multiplicacao | Divisão | Resto de Divisão |
|--------------------------------------------------------|------------------|
| (a + b) | (a - b) | (a * b) | (a / b) | ( A % B ) |
+--------------------------------------------'-----------'------------------+
exemplo apenas atribuição de valores em variáveis
---------------------------code
#include <stdio.h>
int main() {
//declaramos variáveis
int x,y,z;
//setamos valor nas váriaveis
x=2,y=3,z=5;
printf("escolhidos %d %d %d \n", x, ,y ,z);
return 0;
}
---------------------------EOF
repare que usamos "," virgula para separar a atribuição das variáveis
podiamos usar também;
x=2;
y=3;
z=5;
vamos exemplo com atribuição e uso de operadores aritméticos
---------------------------code
#include <stdio.h>
int main() {
//declaramos variáveis
int x,y,z;
//setamos valor nas váriaveis
x=2+2;
y=3-2;
z=5*2/2;
printf("resultado de x,y e z é %d %d %d \n", x, y, z);
return 0;
}
---------------------------EOF
Podemos atribuir uma váriavel dentro da outra desde que seja do mesmo tipo
exemplo
---------------------------code
#include <stdio.h>
int main() {
//declaramos variáveis
int x,y,z;
//setamos valor nas váriaveis
x=2;
y=3;
z=x+y;
printf("resultado de z é %d \n", z);
return 0;
}
---------------------------EOF
podemos usar notação pósfixa para atribuir um valor exemplo invés de
fazer
x=x+1;
podemos fazer
x+=1;
ou x++
para atribuição de valor "1" podemos fazer até x++;
vou dar um exemplo prático e pesado para estudo, tente entender o que
cada linha faz...
---------------------------code
#include <stdio.h>
int main() {
//declaramos variáveis
int x,y,z;
//setamos valor nas váriaveis
x=2;
y=3;
z=5;
z+=(x+y); // isso vale como z=z+(x+y)
printf("resultado 1 de z é %d \n", z);
z++; // equivale a z=z+1
z++;
printf("resultado 2 de z é %d \n", z);
z*=2; // z=z*z
printf("resultado 3 de z é %d \n", z);
z%=12;
printf("resultado 4 do resto da divisao de 24 por 12 de z é %d \n", z);
z=13;
z+=x++ + ++y; // ou seja z=z+(x+1)+(y-1)
printf("resultado 5 de z é %d \n", z);
z-=1; // valia 19 agora vale 18
z-=12 + x++; // ou seja z=z-(12+(x+1))
printf("resultado 6 de z é %d \n", z);
z=20; //agora z vale 20
z+=y-- + --x; // z=z+(y-1)+(-x)
printf("resultado 7 de z é %d \n", z);
z=20; //z agora vale 20
z+=(((20/5)+(1-1))*3)/x; // isso vale z=z+( (((20/5)+(1-1))*3) /x )
printf("resultado 7 de z é %d \n", z);
return 0;
}
---------------------------EOF
acho que com este ultimo exemplo deu para explanar operadores aritméticos
com variáveis inteiras,agora mudando de assunto porem dentro do tópico "int"
Em resumo os tipos de declarações de "int"
* int, pode possuir 16 bits, 32 bits ou 64 bits
* short int, deve possuir tamanho de no mínimo 16 bits e não pode ser maior que int
* long int, deve possuir tamanho mínimo de 32 bits
* long long int, deve possuir tamanho mínimo de 64 bits
Todos estes tipos de inteiros podem ainda ser declarados precedidos da cláusula unsigned,
o que faz com que só suporte números positivos. Isto faz com que, com o mesmo tamanho, uma
variável suporte mais números positivos do que um signed (todos os inteiros são signed por
omissão).
como eu sei quantidade de Bits de uma variável ?
usamos função "sizeof()" para determinar o tamanho de uma variavel, tipo ou
constante. O valor retornado é em bytes.
---------------------------code
#include <stdio.h>
int main() {
int x;
x = sizeof(int);
printf("bytes de x é %d , tem total de %d bits\n", x, x*8);
return 0;
}
---------------------------EOF
Acima, o valor de x será 4, ou 4 bytes, que dah 32bits, ou seja, x é um
inteiro de 32 bits.
antes de partir para float só mais um exemplo,desta ves um programa
que mostra alguns dos argumentos na função "printf()" são eles "%d"
que já usamos que seria para decimal,"%o" para octal, "%x" hexadecimal
---------------------------code
#include <stdio.h>
int main(void)
{
int x = 100;
printf("dec = %d; octal = %o; hex = %x\n", x, x, x);
return 0;
}
---------------------------EOF
rode o programa e tente entender...
x05-float
------------
Uma variavel racional,real(ponto flutuante) é aquela que assume valores
racionais.
Podemos declarar assim:
float x;
ou
double y2;
Na primeira declaracao, temos x um ponto flutuante de precisao simples,
e xy um ponto flutuante de precisao dupla, ou seja, x pode ter
mais casas decimais do que y. Voce tambem pode usar unsigned, long e
short para float:
unsigned float z;
+----------------+-----------------+
| float | double |
| short float | short double |
| long float | long double |
| unsigned float | unsigned double |
| signed float | signed double |
+----------------+-----------------+
vamos a um exemplo de uso em um probleminha de porcentagem
Um produto, cujo valor original era de R$ 250,00, teve um desconto de 10%.
Qual foi seu valor final da compra?
---------------------------code
#include <stdio.h>
int main() {
float valor,percentual,total;
valor = 250.00;
percentual = 10.0 / 100.0;
total = valor - (percentual * valor);
printf("O valor final é %.2f \n", total);
return 0;
}
---------------------------EOF
Só uma explicação rápida do que ocorreu na função "printf()"
printf("O valor final é %.2f \n", total);
| |
string |_usamos argumento "%f" para float
qualquer ".2" seria para indentificar
quantos zeros antes do "ponto"
se você usar "%.3f" então vai
ter "225.000" invés de "225.00"
Mistério Descobrido !
Scooby Scooby Doooooo AhUHAuHAHAU !
x06-Char - caracter - alfanumérico
---------------------------------
O tipo char ocupa 1 byte, e serve para armazenar caracteres ou inteiros.
Isso significa que o programa reserva um espaço de 8 bits na memória RAM
ou em registradores do processador para armazenar um valor (char de tamanho
maior que 8 bits é permitido pela linguagem, mas os casos são raros). Com
vetores do tipo char é possível criar cadeias de caracteres (strings).
Um caractere em ASCII - American Standart Code for Information
Interchange, tem um valor que varia de 0 a 255. Ou seja, quando voce declara
um caractere, voce estah na verdade declarando um inteiro de 0 a 255.
char letra;
É importante voce saber boa parte da tabela ASCII, principalmente se voce
quer lidar com baixo nivel. O seguinte programa em C exibe a tabela
para voce:
---------------------------Code
#include <stdio.h>
int main() {
unsigned char i;
for (i=0;i<255;++i)
// %c argumento para definir apenas um char
printf("%d -> %c\n",i,i);
return 0;
}
---------------------------EOF
Por exemplo, a letra A (maiusculo) tem o valor 65. Assim, apos
declarado a variavel
unsigned char c;
voce poderia ter feito..
c = 'A';
ou
c = 65;
pois o resultado seria o mesmo.
Strings ficam interessantes mesmo com vetores "arrays",não é legal eu
falar disso agora,Mas vou tentar,um "Array" nada mais é que uma lista
em linguagem C podemos definir por "[]" e dentro vai o número da quantidades
de elementos do "Array",por exemplo "[4]" então é um "array" de 5 elementos
[0][1][2][3][4] isso por que contamos apartir do ZERO
vamos um exemplo prático
---------------------------Code
#include <stdio.h>
#define frase "olhe que legal estou vivo!"
int main() {
char name[10];
printf("qual seu nome?\n");
scanf("%s", name);
// s = string
printf("Ola, %s. %s\n", name, frase);
return 0;
}
---------------------------EOF
%s = seria o argumento para definir um conjunto de caracteres
usamos uma função nova até aqui o "scanf()" que serve para pegar
entradas "stdin" ou seja entradas do teclado.programa mostra como
saida "qual seu nome?" então o cliente vai digita o nome,então
o programa retorna a saída "ola Fulano , olhe que legal"...
só para discutir aqui, está forma de pegar string de entrada não
é a melhor forma, memso pro que alguns compiladores podem retornar
algum BUG,veja o por que
array name[15]
[c][h][u][c][k][][n][o][r][r][i][s][\0][][]
| |-> null caracter
|-usuário digita nome dele chuck norris
o problema é que alguns compiladores faz
array name[15]
[c][h][u][c][k][][n][o][r][r][i][s][\0][\n][] e "\n" na próxima entrada
| |-> null caracter
|-usuário digita nome dele chuck norris
isso acaba bugando seu programa então tem que fazer uma gambiarra
usando "getchar()"
scanf("%s", ola); getchar();
assim pegando \0\n que tem a mais...
só uma curiosidade se você quiser mostrar somente uma letra da palavra
pasta mostrar sua posição exemplo,"chuck norris" se pegarmos o terceiro
caracter "u", então teriamos
[c][h][u][c][k]....
0 1 2 3 4 <--- número da posição dos elementos do "array"
então
printf("%c", var[2]);
isso não é nada elegante,então baseada na idéia de um amigo o "m0nad" fiz
uma macro para resolver o problema, na versão do m0nad seria uma função chamada
"chomp" com influências na linguagem interpretada Perl.
---------------------------Code
#include <stdio.h>
#include <string.h>
#define ReadString(a) fgets(a,sizeof(a),stdin),a[strlen(a)-1] = '\0';
int main() {
char teste[10];
printf("seu nome\n");
ReadString(teste);
printf("voce escreveu %s\n",teste);
return 0;
}
---------------------------EOF
vamos lapidar a nossa macro "ReadString"
fgets(var,sizeof(var),stdin); <-- usamos para ler a entrada stdin
var[strlen(var)-1] = '\0'; <-- usamos para deletar "\0" e assim não bugar
a função "strlen()" esta inclusa na header <string.h> isso justifica o uso
da header,lembrando que nesta header tem muitas funções legais de strings
como exemplo você deseja concatenar strings. usamos função "strcat"
---------------------------Code
#include <stdio.h>
#include <string.h>
#define ReadString(a) fgets(a,sizeof(a),stdin),a[strlen(a)-1] = '\0';
int main() {
char animal[10], animal2[10], soma[30];
printf("nome de um animal \n");
ReadString(animal);
printf("nome de um animal \n");
ReadString(animal2);
strcat(soma,animal); //soma+=animal...
strcat(soma," e o animal ");
strcat(soma,animal2);
printf("string concatenada %s \n", soma);
return 0;
}
---------------------------EOF
caso use um "unix like" de o comando num terminal "man string" para ver o manual
da <string.h> caso não visite
http://www.manpagez.com/man/3/string/
x07-Ponteiro "Pointer"
--------------------
É uma variável que aponta para uma determinada area da memória,seu valor é o
endereço da memória que geralmente é um inteiro hexadecimal,Chamamos de apontador
porque podemos utilizar o operador unario "*" para acessar ao valor da memoria
que o nosso ponteiro armazena.Interessante saber que para um inteiro, o valor nulo
é 0, para um float, é 0.0, para um char, é '\0', mas e para um ponteiro? Nesse caso é
NULL. exemplo;
---------------------------Code
#include <stdio.h>
int main() {
int x ,*y;
printf("digite um número\n");
scanf("%d", &x);
/*
"&" seria um operador unario utilizado junto a variáveis para
determinar o endereço de memoria onde estao armazenadas
*/
y=&x;
printf("y vale %d \n", *y);
printf(" endereço da memória de y é %x \n", y);
return 0;
}
---------------------------EOF
x08-Casting
--------------------
Seria converter uma variável de um tipo para outro tipo
exemplo:
---------------------------Code
//1
int index = 1;
float var = 0.0;
index = (int)var;
//2
char c = ’A’;
int x = (int)c;
//3
int x;
//printando de "A" até "Z"
for(x=97; x<=122; x++)
printf(" %c ", (char)x);
//4
int x=7, y=5;
float z;
z = (float)x/(float)y;
//5
int x = 13;
printf("x/2 is %f", (float)x / 2);
---------------------------EOF
x09-Condições
-------------------
IF-ELSE
if-else é um controlador do fluxo com o qual podemos fazer com que
um bloco de comandos seja executado se uma dada condicao for correta, e
tambem pode fazer com que um bloco de comandos alternativo seja executado
caso a condicao seja não correta.
A sintaxe é:
if (expressao)
comando1
else
comando2
exemplo
---------------------------Code
#include <stdio.h>
int main() {
int x ,y;
printf("digite um número para x\n");
scanf("%d", &x);
printf("digite um número para y\n");
scanf("%d", &y);
if(xy);
printf("%d",z);
return 0;
}
---------------------------EOF
podemos usar agrupar um conjunto de comandos com "{ }" chaves
exemplo:
dado o problema que é necessario pegar duas entradas do usuário
inteiras,verificar se são iguais,se forem iguais então a primeira
entrada deverá receber adição de 1,caso a segunda entrada seja
menor ou igual a primeira então a segunda entrada recebera o produto
de 2.
---------------------------Code
#include <stdio.h>
int main() {
int x ,y;
printf("digite um número para x\n");
scanf("%d", &x);
printf("digite um número para y\n");
scanf("%d", &y);
if(x==y)
{
printf("x é igual a y \n");
printf("x vai receber adição de um numero \n");
x++;
}
if(y<=x)
{
printf("y é menor ou igual a x\n");
y*=2;
}
/* Por fim mostramos o valor das duas entradas */
printf("x = %d , y = %d\n", x,y);
return 0;
}
---------------------------EOF
até aqui está fácil de mais, vamos usar agora operadores "&&" and,"||" or
Operadores Logicos AND e OR (E e OU)
,---,---,--------,
| a | b | a && b |
|---|---|--------|
| 0 | 0 | 0 |
| 0 | 1 | 0 |
| 1 | 0 | 0 |
| 1 | 1 | 1 |
'---'---'--------'
Assim, a expressão (x < y) && (z >= x) sera 1 se e somente se x for menor
que y e, simultaneamente, z for maior ou igual a x. Ou seja, se ambas as
expressões forem verdadeiras.
O operador OU eh caracterizado pela seguinte tabela verdade:
,---,---,--------,
| a | b | a || b |
|---|---|--------|
| 0 | 0 | 0 |
| 0 | 1 | 1 |
| 1 | 0 | 1 |
| 1 | 1 | 1 |
'---'---'--------'
Assim, a expressao (x < y) || (x < z) serah 1 se e somente se pelo menos uma
das expressoes for verdadeira. Sera 0 se e somente se ambas forem falsas.
temos também operador "XOR" representado pro "^"
,---,---,--------,
| a | b | a ^ b |
|---|---|--------|
| 0 | 0 | 0 |
| 0 | 1 | 1 |
| 1 | 0 | 1 |
| 1 | 1 | 0 |
'---'---'--------'
Muito usado para fazer SWAP
A B C
| | | | | |
|~~~~~| |~~~~~| | |
| | | | | |
| | | | | |
+-----+ +-----+ +-----+
Na lógica imaginamos como se fosse 3 copos sendo dois cheios e um vazio
para fazer a troca entre A e B,nada impossível com terceiro copo "c=b; b=a; a=c;"
E se só tive-se copo "A" e "B" ?
Tem uma forma diferente usando XOR "^", para usar swap
mas desta vez descarto esta forma, que em elementos comuns com INT seria
int a = 10;
int b = 20;
a = a ^ b:
b = a ^ b;
a = a ^ b;
Temos também operador "!" negação seria NOT ou seja
if(x==0)
x+=2;
podemos fazer
if(!x)
x+=2;
seria equivalente
pode-se fazer um xor usando NOT
!a != !b;
vamos a um problema
pegue 3 entradas de um usuário qualquer,sabendo que as 3 entradas
são números inteiros,então avise se as 3 entradas forem iguais e
primeira entrada devera receber como adição ao seu valor a segunda entrada e a
terceira entrada, se a primeira entrada for Igual ou maior que a terceira
"ou" se terceira entrada for igual ou maior que a primeira então
mostre o produto dos dois com subtração de "2",caso a primeira,segunda
entrada e a terceira não seja teclada avise para o usuário para teclar
um número inteiro e que o mesmo não pode ser zero.
---------------------------Code
#include <stdio.h>
int main() {
int x ,y ,z;
printf("digite um número para x\n");
scanf("%d", &x);
printf("digite um número para y\n");
scanf("%d", &y);
printf("digite um número para z\n");
scanf("%d", &z);
if( (x==y) && (x==z) )
printf("3 entradas iguais\n adição delas é %d\n", x+=y+z);
if( (x>=z) || (z>=x) )
printf("produto de x com z com subtração de 2 é %d \n", ((x*z)-2) );
if( (!x) && (!y) && (!z) )
printf("tecle um número inteiro ,não pode ser zero\n");
return 0;
}
---------------------------EOF
bom isso foi uma forma simples e direta de resolver o nosso problema
tem outra forma mudando o estilo de programar veja só
---------------------------Code
#include <stdio.h>
int main() {
int x ,y ,z,var;
printf("digite um número para x\n");
scanf("%d", &x);
printf("digite um número para y\n");
scanf("%d", &y);
printf("digite um número para z\n");
scanf("%d", &z);
if( (x==y) && (x==z) )
{
x+=y+z;
printf("3 entradas iguais\n adição delas é %d\n", x);
}
if( (x>=z) || (z>=x) ) {
var=((x*z)-2);
printf("produto de x com z com subtração de 2 é %d \n", var );
}
if( (!x) && (!y) && (!z) )
printf("tecle um número inteiro ,não pode ser zero\n");
return 0;
}
---------------------------EOF
último exemplo,faça um programa que pegue duas entradas e veja se as
mesmas são impar ou par, caso seja par mostre seu valor, caso seja impar
mostre com adição de "1"
---------------------------Code
#include <stdio.h>
int main() {
int x ,y;
printf("digite um número para x\n");
scanf("%d", &x);
printf("digite um número para y\n");
scanf("%d", &y);
if(!(2%x))
printf("x é par seu valor é %d \n", x);
else
printf("x é impar seu valor é %d, adição é %d\n", x, x++);
if(!(2%y))
printf("y é par seu valor é %d \n", y);
else
printf("y é impar seu valor é %d, adição é %d\n", y, y++);
return 0;
}
---------------------------EOF
hehehe não foi visualmente claro ?
isso
if(!(2%x))
printf("x é par seu valor é %d \n", x);
else
printf("x é impar seu valor é %d, adição é %d\n", x, x++);
equivalente a isso
if((2%x)==0)
printf...
else
printf...
dentro da condição você pode resolver problemas aritméticos
sim e é divertido :)
invés de ler (2%x) o interpretador resolve o que esta entre parenteses
por exemplo se x vale 6 então resto da divisão seria 0 então (0==0)
em fim você pode fazer N soluções com isso...
não tem só if e else no C também temos "else if"
podemos usar como exemplo, se uma condição não for verdadeira e for de acordo com expressão dentro
do parenteses então faça...
if(exp)
{
codes
}
else if(exp)
{
code
}
também temos condições ternárias usando "?" e ":" ou seja
isso
if(x==2)
x=0;
else
x++;
podemos passar para expressão ternária e ficando
x=(x==2)?0:++x;
ou seja
var=(expressão de condição)? se for exp : se não for exp ;
teria o resultado equivalente ao usar o "if" e "else"
podemos no "printf" e em outras funções como exemplo
---------------------------Code
#include <stdio.h>
int main() {
int x,y;
printf("digite um número para x\n");
scanf("%d", &x);
printf("digite um número para y\n");
scanf("%d", &y);
printf("maior das duas entradas é %d \n", (x>y)?x:y );
return 0;
}
---------------------------EOF
tem um pessoal que abusa de expressão ternária, fazendo o código
ser chato para ser lido e interpretado por um outro programador
isso seria uma prática ruim de ser feita,veja só que bizarro
---------------------------Code
#include <stdio.h>
int main() {
int x,y;
printf("digite um número para x\n");
scanf("%d", &x);
printf("digite um número para y\n");
scanf("%d", &y);
printf("maior das duas entradas %d \n", (x>y)?(x>10)?(x+5)/3:++x:(!((y-2)/2))?0:666 );
return 0;
}
---------------------------EOF
Achou o código muito espartano?
vou explicar a expressão ternária aqui passada
(x>y)?(x>10)?(x+5)/3:++x:(!((y-2)/2))?0:666
equivale ao código:
if(x>y)
{
if(x>10)
return ((x+5)/3)
else
return ++x
}
else if( ((y-2)/2) == 0 )
{
return 0;
}
else
{
return 666;
}
x10-Estilos de programação até Aqui
----------------------------------
alguns programadores em C do IRC no servidor da freenode fazem competição
para ver quem resolve um algoritmo em menas linhas usando,expressão ternária
e outras funções da linguagem, só não vale usar shellcode rsrs...
Tem um pessoal "Noob" de programação de alto nível,que se racha de dar risada
quando escuta falando que linguagem C tem um estilo,em C você tem N formas de
se fazer a mesma coisa,claro que algumas formas vão ser mais rápidas que outras
e algumas vão ser visualmente ruim de se ler o código mas em fim veja só os
exemplos,todos tem a função igual
-----------------------------------------
método ousado de usar "," para evitar chaves "{}"
eu já vi muitos códigos "l33t" do povo underground assim
pessoalmente não gosto de ver isso
if(x>y,++x,y+=3*2)
printf("result %d \n", x);
else
x=0,y=0;
-----------------------------------------
método evitando "{}" chaves e usando ","
if(x>y)
++x,y+=3*2,printf("result %d \n", x);
else
x=0,y=0;
-----------------------------------------
método GNU, o mais popular e correto no meio acadêmico
e profissional,também tem outras possíbilidades...
if(x>y)
{
++x;
y+=3*2;
printf("result %d \n", x);
} else {
x=0;
y=0;
}
-----------------------------------------
usando exp ternária
x=(x>y)?++x:0;
x=(x>y)?y+=3*2:0;
ou forma bizzara :D
x=(x>y)?++x:0,x=(x>y)?y+=3*2:0;
ou usando "and" invés de ","
x=(x>y)?++x:0&x=(x>y)?y+=3*2:0;
-----------------------------------------
provavelmente se outro programador em linguagem C ver estes exemplos
que segue a mesma forma de se fazer a mesma coisa,teria uma forma diferente
de resolver o mesmo. que como falei cada um segue uma paradigma definida para
sí próprio, por exemplo se você quer participar de um projeto de software livre
exemplo o "Firefox",para garantir uma certa aprovação da equipe você teria
que ter que mostrar ser útil e seguir o mesmo estilo da programação do projeto
,firefox se não me engano usa padrão GNU...
se o projeto foi feito de forma porca sem um paradigma definida,você vai ouvir
coisas do tipo,"faz o seu ai,se funcionar beleza!",ou seja tanto faz o estilo
usado se está tudo sem documentação, se o código está tudo numa linha etc...
x11-Loops em C laços com goto,while,do e for
-----------------------------------------------
Em ASSEMBLY quando precisamos fazer alguma repetição,seja uma sequencia temos que usar
"JUMP", instrução "JMP", com uma certa condição em linguagem C poderiamos usar GOTO
para realizar o feito vejamos
goto.c
---------------------------- code
main()
{
int x=0;
// esta word "jump" poderia ser qualquer coisa como ex INICIO:
JUMP:
x++;
puts("olha só");
if(x<=9) goto JUMP;
}
---------------------------- EOF
este programa é simples ele imprime 10 vezes "olha só"
entendendo o ASSEMBLY em conjunto com GDB
"Espada Justiceira, dê-me a visão além do alcance!" - Thundercats
-usamos argumento "-g" para poder usarmos o GDB depois
cooler@malloc:~/c$ gcc -g -o goto goto.c
cooler@malloc:~/c$ gdb goto
GNU gdb 6.8-debian
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "i486-linux-gnu"...
(gdb) disass main
Dump of assembler code for function main:
0x080483a4 <main+0>: lea 0x4(%esp),%ecx
0x080483a8 <main+4>: and $0xfffffff0,%esp
0x080483ab <main+7>: pushl -0x4(%ecx)
0x080483ae <main+10>: push %ebp
0x080483af <main+11>: mov %esp,%ebp
0x080483b1 <main+13>: push %ecx
0x080483b2 <main+14>: sub $0x24,%esp
0x080483b5 <main+17>: movl $0x0,-0x8(%ebp)
0x080483bc <main+24>: addl $0x1,-0x8(%ebp) nossa var X recebe +1
0x080483c0 <main+28>: movl $0x80484a0,(%esp)
0x080483c7 <main+35>: call 0x80482d4 chamando função puts na libc
0x080483cc <main+40>: cmpl $0x9,-0x8(%ebp)
0x080483d0 <main+44>: jle 0x80483bc <main+24>jump main 24 if x less or equal 9
0x080483d2 <main+46>: add $0x24,%esp
0x080483d5 <main+49>: pop %ecx
0x080483d6 <main+50>: pop %ebp
0x080483d7 <main+51>: lea -0x4(%ecx),%esp
0x080483da <main+54>: ret
este exemplo foi bem direto
agora que você entendeu GOTO,vou explicar o "while"
bom o "while" é muito mais fácil que o GOTO, porem quando você disassembla
vê que acaba gerando mais código portanto GOTO é mais leve, porém código
cheio de GOTO é considerado má prática.vamos exemplo do "while","do while"
e "for".
exemplo é simples vamos mostrar na tela 10 vezes "ola cara"
de várias formas diferentes
---------------------------- code
// usando while
main()
{
int x=0;
while(x<9) puts("ola cara"),x++;
}
//veja que você também pode usar chaves {}
main()
{
int x=0;
while(x<9)
{
puts("ola cara")
x++;
}
}
// usando DO WHILE
main() {
int x=0;
do
puts("ola cara"),x++;
while(x<=9);
}
main() {
int x=0;
do
{
puts("ola cara");
x++;
}while(x<=9);
}
// dois exemplos usando for
main() {
int x;
for(x=0; x<=9; x++) puts("ola cara");
}
main() {
int x;
for(x=0; x<=9; x++)
{
puts("ola cara");
}
}
---------------------------- EOF
você pode ver que dentro do while(), tem uma exp de condição
quando aquela condição for verdadeira termina o loop,no caso do "for()"
fica no meio exemplo "for(x=0; x>3; x--)" bom chega de exemplos
fáceis vamos botar sua cabeça no fogo...
Melhor lugar para treinar lógica de programação é o project Euler seria
um site onde se encontra vários desafios matemáticos que podem ser resolvidos
e devem usando programação.no proóprio site tem um forum com algumas respostas
nas mais diversas linguagens de programação a la Lisp,haskel,python...
http://projecteuler.net
exemplo de desafio e solução para o mesmo
problema número 1
Add all the natural numbers below one thousand that are multiples of 3 or 5.
tradução rápida ;
mostre toda a soma dos numeros naturais até 1000 dos números multiplos de 3 e 5.
vou dar duas respostas diferentes porem chega na mesma lógica
---------------------------- Code
#include <stdio.h>
main()
{
int x,y;
for(x=1,y=0; x<1000; x++,y+=((!(x%3))||(!(x%5)))?x:NULL);
printf("%d\n",y);
}
//melhorando o código, outro exemplo
#include <stdio.h>
main()
{
int x=0,y=0;
for(X=1; X<1000; X++)
{
// para saber se um número é multiplo dividimos
// vemos o resto se for zero é multiplo
// usamos NOT "!" para ficar equivalente a ((x%3)==0)
if( (!(x%3)) || (!(x%5)) )
// var y recebe ela mesma mais o numero multiplo por 3 ou 5
y+=x;
}
printf("%d\n",y);
}
---------------------------- EOF
já penso em fazer isso com o lapiz hehehe
bom primeiro desafio da lista sempre é o mais fácil apartir do oitavo
desafio, ai sim você vai queimar a cabeça vai ter até que fazer buscas no
"google".
x12-Arrays "Vetores,matrizes"
------------------------------
vetor é uma lista de números ou caracteres,endereços etc...
vou dar um exemplo
---------------------------- Code
#include
main()
{
int x;
int y[4];
y[0]=2;
y[1]=4;
y[2]=6;
y[3]=8;
y[4]=10;
for(x=0; x<=4; x++)
printf("%d\n",y[x]);
puts("mais um exemplo");
int z[]={1,2,3,4,5};
for(x=0; x<=4; x++)
printf("%d\n",z[x]);
puts("teste com ponteiro");
char *lambda[3];
lambda[0]="12";
lambda[1]="21";
lambda[2]="32";
lambda[3]="41";
for(x=0; x<=3; x++)
printf("%s\n",lambda[x]);
}
---------------------------- EOF
da mesma forma pode-se trabalhar com matrizes bidimensionais
int var[4][3]; // 4 linhas (0 a 3) e 3 colunas (0 a 2)
tridimensionais
var[][][]
4D
var[][][][]...
x13-Funções
---------------------
lembra que aqui no paper foi falado que "main()" é função assim como "scanf()"
,printf(),praticamente tudo em C que tem parenteses é função rsrsrs
mas afinal como fazer uma função ?
Pode criar uma função com qualquer nome como se fosse uma var mesmo exemplo
---------------------------- Code
#include <stdio.h>
// aqui uma função mais útil
int num(int x,int y)
{
printf("%d\n",x+y);
return 0;
}
//uma função que retorna nada usando void
void Boteco()
{
puts("como vai?");
}
main()
{
// chamamos a função desta forma
Boteco();
if(!num(2,3))
puts("retorno zero");
}
---------------------------- EOF
também podemos botar as funções no final do código
porem devemos botar seu rotulo no inicio
---------------------------- Code
void Boteco();
main()
{
Boteco();
}
void Boteco()
{
puts("como vai?");
}
---------------------------- EOF
já que você entendeu vamos um exemplo espartano com função recursiva ou seja
ela própria se chama...
a méta do programa nosso é converter número decimal para romano
ou seja se é "5" converter para "V",9 para "IX"...
---------------------------- Code
#include
// repare que estas vars são globais
int value[] = {1000,900,500,400,100,90,50,40,10,9,5,4,1};
char Roman[][3] = {"M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"};
int
troca(int n)
{
int i;
if(!n)
return 0;
for(i = 12; i>=0; i--)
if(value[i] >= n)
break;
if(i < 0) i++;
if(value[i] > n) i++;
printf("%s",Roman[i]);
troca(n-value[i]);
}
main()
{
int n;
while(scanf("%d",&n) == 1)
troca(n),printf("\n");
}
---------------------------- EOF
se você parar para pensar as "headers" ou "bibliotecas" estão cheias de funções
irei mostrar agora um programa,assim ilustrar um poco o que já vimos,leia os
comentários.
---------------------------- Code
/*
Exemplo de programa em Linguagem C que usa recursividade
Autor: Antonio "Cooler_"
contato: c00f3r@gmail.com
tony.unix@yahoo.com.br
site: BotecoUnix.com.br
Explicação:Programa tem que calcular fração do tipo Soma
ou subtração como no exemplo a seguir
2 1 4+7 11
---- + ---- = ----- = ----
21 6 42 42
sabendo que
MMC = mínimo múltiplo comum entre dois números é representado
pelo menor valor comum pertencente aos múltiplos dos números.
Observe o MMC entre os números 20 e 30:
M(20) = 0, 20, 40, 60, 80, 100, 120, ....
M(30) = 0, 30, 60, 90, 120, 150, 180, ...
O MMC entre 20 e 30 é equivalente a 60.
Outra forma de determinar o MMC entre 20 e 30 é através da fatoração,
em que devemos escolher os fatores comuns de maior expoente e os termos
não comuns. Observe:
20 = 2 * 2 * 5 = 2² * 5
30 = 2 * 3 * 5 = 2 * 3 * 5
MMC (20; 30) = 2² * 3 * 5 = 60
O MDC de dois números inteiros é o maior número inteiro que divide
ambos sem deixar resto, O algoritmo de Euclides é baseado no princípio
de que o MDC não muda se o menor número for subtraído ao maior. Por
exemplo, 21 é o MDC de 252 e 105 (252 = 21 × 12; 105 = 21 × 5); já
que 252 − 105 = 147, o MDC de 147 e 105 é também 21. Como o maior dos
dois números é reduzido, a repetição deste processo irá gerar sucessi-
vamente números menores, até convergir em zero. Nesse momento, o MDC é
o outro número inteiro, maior que zero. Ao reverter os passos do algoritmo
de Euclides, o MDC pode ser expresso como soma dos dois números originais,
cada um multiplicado por um número inteiro positivo ou negativo, por
exemplo, 21 = 5 × 105 + (−2) × 252. Esta importante propriedade é denominada
identidade de Bézout.
^`. o
^_ \ \ o o
\ \ { \ o
{ \ / `~~~--__
{ \___----~~' `~~-_ ______ _____
\ /// a `~._(_||___)________/___
/ /~~~~-, ,__. , /// __,,,,) o ______/ \
\/ \/ `~~~; ,---~~-_`~= \ \------o-' \
/ / / /
'._.' _/_/
';|\
*/
#include <stdio.h>
int mdc(int a,int b)
{
if(!b) return a;
else return mdc(b,a%b);
}
int mmc(int a,int b)
{
int formula;
if(!b) return a;
else formula = (a*b)/(mdc(a,b));
return (formula);
}
main()
{
int a,b,c,d;
char line[30],choice=0,operator=0;
double resposta;
while(choice!='s') {
printf("Informe 4 numeros seguindo de espaço e por fim operador aritmético \n");
printf("Exemplo: 2 21 1 6 \n ");
fgets(line, sizeof(line), stdin);
sscanf(line, "%d %d %d %d ", &a, &b, &c, &d);
printf("digite um operador + ,- ,/ ou * \n");
scanf("%c", &operator);
printf("%d %d %d %d %c \n", a,b,c,d,operator);
if(operator == '+') a += c,d=mmc(b,d);
if(operator == '/') a /= c,d/=b;
if(operator == '-') a -= c,d=mmc(b,d);
if(operator == '*') a *= c,d*=b;
printf("resultado => %d/%d = %f\n", a,d, resposta=(a>d)?a/d:d/a);
printf("\nDeseja continuar o programa tecle um caracter menos 's' ");
scanf("%s",&choice);
}
}
---------------------------- EOF
x14-Usando Switch,break e continue
-------------------------------------
Bom e se eu pedir para você fazer 4 funções num programa,por exemplo
se o usuario teclar 1 faz x,teclar 2 faz y,teclar 3 faz z.exemplo
anterior você viu
if(operator == '+') a += c,d=mmc(b,d);
if(operator == '/') a /= c,d/=b;
if(operator == '-') a -= c,d=mmc(b,d);
if(operator == '*') a *= c,d*=b;
para executar operação desejada pelo usuário
porem podemos fazer de outra forma usando "switch" veja só
---------------------------- Code
#include <stdio.h>
main()
{
int x;
puts("digite algo");
scanf("%d",&x); getchar();
switch(x)
{
case 1:
puts("escolha 1");
puts("legal");
// "break" faz pular do primeiro código que esta com chaves {}
break;
case 2:
puts("case 1");
break;
// repare ao teclar 3 como não tem break vai executar o case default também
case 3:
puts("case 3");
default:
puts("saindo");
break;
}
}
---------------------------- EOF
este foi um exemplo simples, vamos mostrar agora algo mais funcional
uma calculadora,onde o usuário tecla por exemplo
+ 2
+ 2
resultado: 4
/ 2
resultado: 2
* 2
resultado: 4
e se teclar qualquer outra coisa e teclar enter fecha
---------------------------- Code
/*
*Function this programm
this program is a simple calculator,work with operator and number
i make this program for my friend d3lf0 study "ansi C"
Author: Antonio "Cooler_x86"
contact: tony.unix@yahoo.com.br
license: BSD
greetz
Thanks _mlk_ , m0nad,IAK,Fox,D3lf0,nibbles and Chris Torek.
K&R for book ansi C
.--..--..--..--..--..--.
.' \ (`._ (_) _ \
.' | '._) (_) |
\ _.')\ .----..---. /
|(_.' | / .-\-. \ |
\ 0| | ( O| O) | o|
| _ | .--.____.'._.-. |
\ (_) | o -` .-` |
| \ |`-._ _ _ _ _\ /
\ | | `. |_||_| | Solution!
| o | \_ \ | -. .-.
|.-. \ `--..-' O | `.`-' .'
_.' .' | `-.-' /-.__ ' .-'
.' `-.` '.|='=.='=.='=.='=|._/_ `-'.'
`-._ `. |________/\_____| `-.'
.' ).| '=' '='\/ '=' |
`._.` '---------------'
//___\ //___\
|| ||
||_.-. ||_.-.
(_.--__) (_.--__)
*/
// biblioteca de padrão de entrada e saida, standart input and output
#include <stdio.h>
//declaração das variaveis
char line[100],operator;
int result,value;
// Banner
char opcao_menu()
{
int i;
// array bidimensional com ponteiro para guardar o banner
char *banner[] = {
"Operator Calc",
"coded by Cooler_ visit http://botecounix.com.br",
"exemplo",
"operatores:+,-,*,/ ",
"qualquer outro char pra sair",
"-> ",
};
for(i=0; i<=5; i++)
printf(" %s \n",banner[i]);
}
main()
{
opcao_menu(); result = 0;
// Loop soh termina se retorna 1
while (1)
{
printf("Resultado: %d\n", result );
printf("Digite Operador e o numero : ");
// pega as duas entradas ex: + 2
fgets(line, sizeof(line), stdin);
sscanf(line, "%c %d", &operator, &value);
/*
aqui poderiamos ter usado comando "continue;" para identificar
algo que não queremos por exemplo:
if ((value<0)||(!value)) continue;
Opcao invalida: volta ao inicio do loop
*/
switch(operator)
{
case '+':
result += value;
break;
case '-':
result -= value;
break;
case '*':
result *= value;
break;
case '/':
result /= value;
break;
default:
puts("Saindo do programa");
return 1;
}
}
}
---------------------------- EOF
x15-Melhorando a Peformance
===================================
como dizia o mestre dos magos em "Caverna do dragão" ano 1990
"Nem tudo o que dá certo é certo."
Embora o código compile não quer dizer que está com boas práticas,ou mesmo
com uma boa performance,no livro "the Practice of Programming" do K&P
"Brain kernighan e Rob Pike",tem um capítulo somente falando disso isso se o
livro inteiro já não tiver esta meta,milhares de paradigmas para seguir
você não pode inventar algo e simplesmente abstrair,um bom código é aquele
que outros programadores entendem. mas em fim performance, vou mostrar algumas
práticas para ser trocadas.
troque isso:
for(i=0; i< n=z[c] ; i++) {
por isso:
n = z[c] ;
for(i=0; i < n; i++) {
evite loops desnecessários "loop unrolling"
como:
for(i=0; i<3; i++)
a[i]=b[i]+c[i];
faça:
a[0]=b[0]+c[0];
a[1]=b[1]+c[1];
a[2]=b[2]+c[2];
como:
int i, sum = 0;
for (i = 1; i <= 8; i++)
sum += i;
printf ("sum: %d\n", sum);
faça
int sum = (8 * (8+1)) / 2;
printf ("sum: %d\n", sum);
substituir um Operador caro por um mais barato.
-Produto por adição
-Divisão e resto são muito mais lentos do que a multiplicação
invés:
for(i=0;i<10;i++)
printf("%d\n",i*10);
faça:
for(i=0;i<100;i+=10)
printf("%d\n",i);
variaveis do tipo int são mais leves que char
invés:
char x;
int y;
y = x;
faça:
int x, y;
y = x;
//voce pode fazer malabarismo depois com casting
Declarar funções locais como "static"
informa o compilador que a função não precisa ser tão gerais quanto
ao serviço de chamadas arbitrária geral a partir de módulos independentes
Se o endereço da função nunca é tomada, o compilador pode tentar
simplificar e reorganizar o uso do mesmo dentro de outras funções.
invés:
void swap(int *x, int *y) {
int t;
t = *y;
*y = *x;
*x = t;
}
faça:
static void swap(int *x, int *y) {
int t;
t = *y;
*y = *x;
*x = t;
}
"variáveis globais são mais rápidas do que estaticas".
em questão de loops "do while" é mais rápido que o "for"
invés:
for(i=0;i<100;i++) {
map[i].visited = 0;
}
faça:
i=99;
do {
map[i].visited = 0;
i--;
} while(i>=0);
Inline ASM pode ser uma grande opção quando já fez o possível
----------------------- Code
#include <stdio.h>
float A=10,B=15;
main()
{
// adição
__asm__ __volatile__("addl %%ebx,%%eax":"=a"(A):"a"(A), "b"(B));
printf("A+B=%d\n", A);
// subtração
A=20,B=12;
__asm__ __volatile__("subl %%ebx,%%eax":"=a"(A):"a"(A), "b"(B));
printf("20-12=%d\n", A);
// produto
A=2,B=8;
__asm__ __volatile__("imull %%ebx,%%eax":"=a"(A):"a"(A), "b"(B));
printf("2x8=%d\n", A);
// divisão
A=2,B=20;
__asm__ __volatile__("idivl %%ebx,%%eax":"=a"(A):"a"(A), "b"(B));
printf("2/20=%d\n", A);
}
----------------------- EOF
porem é bem espartano e pode comer seu tempo para problemas simples
como um simples loop,tratar uma string...
outro inline porem este não fui eu que escrevi,este é para raiz quadrada
----------------------- Code
/* Copyright (C) 1997 by Vesa Karvonen. All rights reserved.
**
** Use freely as long as my copyright is retained.
*/
double __stdcall Inv_Sqrt(double x) {
__asm {
; I'm assuming that the argument is aligned to a 64-bit boundary.
mov eax,0BFCDD6A1h ; 1u Constant from James Van Buskirk
mov edx,[esp+8] ; 1v Potential pms.
sub eax,edx ; 2u
push 03FC00000h ; 2v Constant 1.5, aligns stack
shr eax,1 ; 3u
sub edx,000100000h ; 3v =.5*x, biased exponent must > 1
mov [esp+12],edx ; 4u
push eax ; 4v
; The lower 32-bits of the estimate come from uninitialized stack.
fld QWORD PTR [esp-4] ; 5 Potential pms
fmul st,st ; 6-8
fld QWORD PTR [esp-4] ; 7
fxch st(1) ; 7x
fmul QWORD PTR [esp+12] ; 9-11 Potential pms
fld DWORD PTR [esp+4] ; 10
add esp,4 ; 12 Faster on Pro/PII
fsub st,st(1) ; 12-14
fmul st(1),st ; 15-17
fmul st(1),st ; 18-20
fld DWORD PTR [esp] ; 19
fxch st(1) ; 19
fmulp st(2),st ; 20-22
fsub st,st(1) ; 21-23
fmul st(1),st ; 24-26
fmul st(1),st ; 27-29
fld DWORD PTR [esp] ; 28
fxch st(1) ; 28
fmulp st(2),st ; 29-31
fsub st,st(1) ; 30-32
fmul st(1),st ; 33-35
pop eax ; 34
fmul st(1),st ; 36-38
fld DWORD PTR [esp] ; 37
fxch st(1) ; 37
fmulp st(2),st ; 38-40
fsubrp st(1),st ; 39-41
fmulp st(1),st ; 42-44
}
}
----------------------- EOF
relax é mais para ilustrar uso de assembly para melhorar desempenho dos códigos
mesma função só que sem ser em Assembly,seguindo uma outra lógica porem
com mesmo objetivo.
----------------------- Code
/* by Jim Ulery */
static unsigned julery_isqrt(unsigned long val) {
unsigned long temp, g=0, b = 0x8000, bshft = 15;
do {
if (val >= (temp = (((g << 1) + b)<>= 1);
return g;
}
----------------------- EOF
Melhor forma de um programador evoluir é vendo códigos de outros programadores
a última forma que conheço de melhorar a performance é paralelismo usar programas
com "pthread.h" ou fork(),mas isso vou deixar para outro paper quem sabe...
bom galera, fico por aqui ;)
não ache que mostrei tudo de linguagem C pois isso que tem no paper não é
nem 50% do que tem por ai,estude o GCC e seus argumentos,GDB para te ajudar
ler um bom livro... nunca parar de estudar :)
x16-Bibliografia
===================
C: a Linguagem de Programação Padrão Ansi - BRIAN W. KERNIGHAN & DENNIS M. RITCHIE
C Primer Plus, Third Edition - Stephen Prata
Practical C Programming, Third Edition - Steve Oualline
x17-agradecimentos
---------------------------
----> Pessoal do "BugSec" grupo que faço parte!
,, ,,
((((( )))))
(((((( ))))))
(((((( Overflow ))))))
(((((,e@@@@@@@@@@e,)))))
(((@@@@@@@@@@@@@@@@)))
\@@/,:::,\/,:::,\@@/
/@@@|:::::||:::::|@@@\
/ @@@\':::'/\':::'/@@@ \
/ /@@@@@@@//\\@@@@@@@\ \
( / '@@@@@@@@@@@@@@' \ )
\( / \ )/
\ ( ) / ('-.)' [Ruby](`'.) '
\ / ('-.)' (`'.)[ASM] '('-.)'
. ' . ('-.)' (`'.) '('-.)' (`'.) '
' .( '.) '[Flex+bison]('-.)' (`'.) '('-.)' (`'.) '
_ ('-.)' (`'.) '('-.)' (`'.) '('-.)'[Emacs] (`'.) (`'.) ''
|0|=======- -(. ')`[VIM]( .-`)(`'.) ',(-')'('-.)' (`'.) (`'.) '
.--`+'--. . (' -,).(') .('-.)' (`'.) '('-.)' (`'.)(`'.) [Python]' '
|`-----'| (' .) - ('. )[Perl]('-.)' (`'.) '('-.)' (`'.) '(`'.) '
| | . ('[PHP] `. )('-.)' (`'.)[REGEX] '('-.)' (`'.) '
| === | ` . `('-.)'[C/C++] (`'.) ('-.)' (`'.) ''
|BugSec | ('-.)' (`'.) '('-.)[AWK]' (`'.) '
| --- |
| | Art by Cooler_
| GDB |
| |
`-.___.-'
Brothers do BugSec _Mlk_,I4K e m0nad. por tudo e por serem meus amigos!
sem eles não estava escrevendo isso hoje, agradecimento especial para
meus Pais :), a min mesmo Cooler_ UHAuHAhUAh
----> Diversos
voidpointer ,syn_ack, edenc ,Ephexis, ecl , isis, Cs0, muzgo , zepplin , nibbles,
nash coracaodeleao,6_Bl4ck9_f0x6 , d3lf0 ,f0kerDebug,Joey, Otacon_x86 , BackBone
e deadside.
pessoal do BotecoUnix.com.br,BugSec.com.br e compania
pessoal dos canais #c4ll,#c-br,#openbsd-br,#php-br,#asm,#gentoo-br da freenode