Ir para conteúdo

JonatasLucasf

Conde
  • Total de itens

    780
  • Registro em

  • Última visita

  • Dias Ganhos

    1

Histórico de Reputação

  1. Upvote
    JonatasLucasf deu reputação a Furabio em Ponteiros C/C++   
    Estou estudando C/C++, e esse tutorial sobre ponteiros me tirou várias dúvidas e pensei em compartilhar ele com vocês.
    Todo os créditos ficam a C0d3r__.

    Audiência

    Você tem dificuldades entendendo ponteiros? Tem problemas no uso de ponteiros? Até mesmo não tem menor idéia do que é um ponteiro? Se a resposta for SIM para uma das perguntas anteriores, então esse tutorial é para você, também se vc tiver uma idéia legal sobre ponteiros, quem sabe esse tutorial não pode aumentar o seu nàvel de conhecimento, então continue a lêr.

    Requerimentos

    Interesse em aprender, e um pouco de conhecimento sobre C ou C++ desenvolvido ou não. É necessario lêr as sessões do comeco ao fim sem pular nenhuma sessão pq o conhecimento no assunto de ponteiros sera construido sequencialmente, quero dizer uma sessão irí lhe dar o alicerce para a proxima sessão.

    O que são ponteiros

    Ponteiros são variaveis, isso mesmo um ponteiro é uma variavel, mas vc pode se perguntar: "oq é uma variavel?", a resposta seria, uma variavel é um tipo de dados que é armazenado na memoria do computador em um determinado endereço. Onde tipos de dados são como os inteiros, caracteres, números fracionarios, e o endereço é um número que representa a posiçao na memoria onde se encontra a variavel.

    exemplo:

    int MeuInt;

    Como vc pode observar acima na declaracao de uma variavel em C, o int é o tipo da variavel que é inteiros, e o MeuInt é chamado de label, ou nome da variavel, onde internamente é associado ao nome da variavel o seu determinado endereço na memoria, "mas oq eu faco com o endereço e como obtenho?" com o endereco vc consegue referenciar a uma variavel, e pra se obter o endereco na programacao em C existe o operador &, que retorna o endereço na memoria de uma variavel. "Operador, que isso?" "Quem vai operar quem?" um operador da linguaguem C ou C++ é uma palavra-chave, que faz uma operacao então a operacao que o operador & faz é simplesmente retornar o endereço de uma variavel, vejamos:

    #include <stdio> #include <stdlib> int main(void) { int MeuInteiro = 0; /* Declara um inteiro */ /* Usa o %p ou specificador de formato p para mostrar o endereço em hexadecimal da variavel que estara na lista de argumento de printf() onde temos &MeuInteiro */ printf("%#p", &MeuInteiro); /* Pausa */ system("pause"); return 0; }
    Compilando o codigo acima em um compilador de C ou C++ vc vera que o programa irí mostrar na tela o endereço da variavel MeuInteiro, onde o operador & foi usado para se obter o endereço.

    também se vc não sabe, números hexadecimais são números de base 16, a base 16 são 16 possiveis números e letras para um digito, os números são: de 0 a 9, e de A a F as letras. Se vc contar da 16, então o valor 0xABCD e um número hexadecimal, veja que cada digito, 4 digitos "ABCD" tem uma letra. também no exemplo acima foi usado o modificador de formato # antes de p que e para dizer a printf() que coloque o prefixo 0x defrente do número hexadecimal, pq 0x representa números hexadecimais.

    Então logo depois que revisamos oq é uma variavel, e aprendemos que todas variaveis tem um endereco que e geralmente representado em hexadecimal, posso lhe dizer que um ponteiro é uma variavel que contém o endereço de uma outra variavel na memoria.

    Da mesma forma que variaveis normais contem um valor, digamos:

    int Inteiro = 10;

    E dado a variavel Inteiro o valor 10.

    Ponteiros também tem um valor, que e um endereço na memoria de outra variavel.

    Também como toda variavel tem um endereço, o ponteiro também tem um endereço de localizacao na memoria.

    #include <stdio> #include <stdlib> int main(void) { int MeuInteiro = 0; /* Declara um inteiro */ int *MeuPonteiro = &MeuInteiro; /* Declara um ponteiro para um inteiro que esta recebendo o endereço de um inteiro */ /* Acessando o conteudo de um ponteiro, ou seja 5 e copiado para MeuInteiro */ *MeuPonteiro = 5; /* Mostra o valor de MeuInteiro */ printf("MeuInteiro = %d\n", MeuInteiro); /* pausa */ system("pause"); return 0; } Como vc pode observar acima e usado o operador * para se acessar oq o ponteiro esta apontando, ou seja: na variavel que MeuPonteiro aponta copie o valor 5, então e mostrado o valor da variavel MeuInteiro que foi acessada apartir de MeuPonteiro.

    Pra vc ver que ponteiros também possuem seu endereço na memoria compile o codigo fonte abaixo:

    #include <stdio> #include <stdlib> int main(void) { int MeuInteiro = 0; /* Declara um inteiro */ int *MeuPonteiro = &MeuInteiro; /* Declara um ponteiro para um inteiro que esta recebendo o endereço de um inteiro */ /* Acessando o conteudo de um ponteiro, ou seja 5 e copiado para MeuInteiro */ *MeuPonteiro = 5; /* Mostra o endereço do ponteiro */ printf("endereço do ponteiro = %#p\n", &MeuPonteiro); /* O que o ponteiro tem (Um endereço pra um inteiro) */ printf("MeuPonteiro = %#p\n", MeuPonteiro); /* Mostre MeuInteiro atravez do ponteiro */ printf("MeuInteiro = %d\n", *MeuPonteiro); /* pausa */ system("pause"); return 0; } Como vc pode observar com o operador * acessamos oq o ponteiro esta apontando, no caso acima acessamos a variavel MeuInteiro, onde usando o operador de copia = e copiado um valor atravez do ponteiro para a variavel, e também usando o *MeuPonteiro como na linha:

    printf("MeuInteiro = %d\n", *MeuPonteiro);

    e mostrado oq MeuInteiro possui atravez de MeuPonteiro.

    Vale apena salientar que se o operador * não e usado em um ponteiro o valor do ponteiro e acessado que e obvio um endereço, vejamos:

    printf("MeuPonteiro = %#p\n", MeuPonteiro);

    E mostrado o endereço de MeuInteiro que esta dentro da variavel MeuPonteiro.

    também aplicando o operador & ao ponteiro pegamos o seu endereço de localizacao na memoria, vejamos:

    printf("endereço do ponteiro = %#p\n", &MeuPonteiro);

    você Sabia: desde que ponteiros tem enderecos, e possivel se criar um ponteiro para um ponteiro, ou uma variavel que possui o endereço de outro ponteiro.

    Para que servem os ponteiros

    Os ponteiros servem para adicionar flexibilidade na programacao, onde apartir de um ponteiro e possivel se acessar variaveis pra lêr oq as mesmas contem ou pra se modificar oq as mesmas contem.

    ? Ponteiros são usados com memoria dinamica, com arrays, com variaveis, ou com estruturas. Onde um ponteiro pode conter um determinado endereço de um valor dentro de um grupo de memoria, apartir dai usando aritimetica de ponteiros, e possivel se andar por absolutamente todos os bytes de um grupo de memoria, indepedente do tipo de dados. Funcoes de manipulacao de string abusam do uso de parametros que são ponteiros, simplesmente pq e impossivel fazer uma manipulacao de uma variavel de dentro de uma funcao e modificar a variavel se ela foi passada como parametro sem que um ponteiro pra variavel seja usado; Veremos mais detalhes sobre isso na sessão de funcoes.

    ? Ponteiros são usados com funcoes de varias formas: funcoes que tem parametros que são ponteiros, funcoes que retornam um ponteiro, ponteiro para funcoes.


    Todas essas formas de ponteiros seram analizadas nas sessões a seguir.


    Ponteiros e memoria dinamica

    Memoria dinamica e toda memoria alocada dinamicamente ou seja na hora de execucao do programa de acordo com algum evento que satisfaca a necessidade de variacao, exemplo:

    Em um programa de redes, cliente/servidor, um cliente pode requisitar(pedir) informacoes ao servidor usando bytes, o mesmo que dados, que são chamados de cabecalhos, então imagine a seguinte situacao: um cliente envia um cabecalho que define o tamanho da requisicao de dados que irí seguir ou seja o tamanho dos dados, o tamanho que e enviado inicialmente pelo cliente seria uma variavel inteiro, que ira dizer ao servidor a quantidade de bytes o servidor deve alocar para se guardar o requisito de informacao, onde essa quantidade de bytes varia. O servidor quando recebe esse tamanho que pode ser variado, aloca memoria no lado do servidor de acordo com esse tamanho de uma forma dinamica ao invez de constante como seria no caso de uma declaracao de uma variavel.

    Onde o ponteiro entra em acao? O ponteiro e utilizado pra apontar para o inicio da memoria recem alocada; Funcoes como malloc(), calloc(), realloc(), são funcoes da livraria padrao da linguaguem C que retornam ponteiros.
    também os operadores new e delete em C++ são exemplos que alocam memoria e retornam um ponteiro.

    Vejamos um exemplo em C:

    #include <stdio> #include <stdlib> int main(void) { /* Declara um ponteiro pra um inteiro */ int *p = NULL; /* Usa malloc pra alocar memoria */ p = malloc(sizeof(int)); /* Abaixo se p == NULL memoria não foi alocada */ /* Pq 0 se torna 1 com o ! entao o bloco do if e executado */ if (!p) { fputs("Erro: sem memoria disponivel!", stderr); return 1; } /* Acesse memoria dinamica */ *p = 1234; /* Mostre memoria dinamica */ printf("%i\n", *p); system("pause"); return 0; } Compile o codigo acima, e vera como e facil alocar memoria dinamica e usar o ponteiro pra essa memoria.
    Observe que no codigo acima p e inicializado para NULL, onde NULL e um define dentro de stdlib.h que esta dessa forma:

    #define NULL (void *)0

    O NULL e o mesmo que 0 internamente, o casting (void *) siguinifica que 0 pode ser copiado para qualquer tipo de ponteiro usando o operador de atribuicao =.

    E importante SEMPRE inicializar os nossos ponteiros para NULL e depois checar depois da rotina de alocacao de memoria se o ponteiro aponta pra algo diferente de NULL, senao problemas graves em projetos podem ocorrer onde o programa apenas e encerrado pelo sistema operacional pq o mesmo tentou manipular memoria protegida, lembra dos Read access violation, Write access violation, isso, esses 2 erros podem ser evitados inicializando os ponteiros para NULL, e sempre que vc for manipular os ponteiros verifique antes, se o mesmo realmente aponta pra memoria valida, memoria diferente de NULL e liberada para leitura/escrita pelo sistema.


    Ponteiros e arrays

    O que e uma array? Uma array e um grupo de variaveis em sequencia, exemplo:

    char MinhaArray[50];

    A declaracao acima aloca uma array chamada MinhaArray de tamanho 50, em outras palavras um grupo de 50 chars e alocado.

    Existe um relacionamento entre ponteiros e arrays, pelo simples fato, sabemos que um ponteiro e uma variavel que aponta pra outra variavel, ja uma array e um grupo de variaveis no qual o NOME da array "MinhaArray" aponta pro primeiro item ou elemento da array. vejamos:

    #include <stdio> #include <stdlib> int main(void) { /* Grupo de 50 chars */ char MinhaArray[50]; /* Desde que MinhaArray aponta pro primeiro elemento podemos usar o operador * e acessar o primeiro elemento */ *MinhaArray = 10; /* Agora conferimos */ printf("Primeiro elemento = %i\n", *MinhaArray); /* Comprovamos */ printf("MinhaArray aponta pra = %#X\n", MinhaArray); system("pause"); return 0; } não confunda! apesar de existir um relacionamento com ponteiros o nome da array não e um ponteiro, porem por ser associado o nome ao endereço do primeiro elemento, onde o nome e simplesmente um label linhas como:

    *MinhaArray = 10;

    Se tornam possivel, por que * funciona da mesma forma com nomes de array como com nomes de ponteiros.
    No entanto linhas como:

    *MinhaArray++;

    ou

    *++MinhaArray;

    não são permitidos, por que MinhaArray não possui um espaco unico na memoria, então:

    MinhaArray += sizeof(TIPO_DE_OBJETO);

    ou

    MinhaArray = MinhaArray + sizeof(TIPO_DE_OBJETO);

    Onde tipo de objeto pode ser qualquer tipo suportado, não são permitidos; Observe que desde que MinhaArray não possui o seu espaco na memoria não e possivel assinar a mesma valores.


    O operador ++ faz a operacao de incrementacao por 1, então:

    x++;

    e o mesmo que:

    x = x + 1;

    e

    ++x;

    também e:

    x = x +1;

    Logo desde que não podemos salvar a posiçao de um determinado elemento dentro do nome da array, usamos ponteiros, logo observe:

    char MinhaArray[50];
    char *MeuPonteiro;

    MeuPonteiro = MinhaArray;

    E dado ao MeuPonteiro o endereço do primeiro elemento da array MinhaArray. Declarando um ponteiro temos um espaco na memoria, onde podemos manter o endereço de um determinado byte, no caso de um char, dentro da array, dessa forma podemos andar ou pecorrer os items da array; Vejamos:

    #include <stdio> #include <stdlib> int main(void) { /* O grupo de bytes */ char MinhaArray[50]; /* Coloca o endereço do primeiro elemento da array dentro de MeuPonteiro */ char *MeuPonteiro = MinhaArray; /* Mantem a posiçao atual e evita que ultrapassemos o tamanho da array que e 50. */ int Count = 0; /* Esse loop irí pecorrer a array de chars de 0 a 49 que são 50 elementos e irí copiar o valor atual de Count + 1 dentro de um determinado elemento usando ponteiro. */ while (Count < 50) { *(MeuPonteiro + Count) = Count + 1; Count++; } /* Reseta Count */ Count = 0; /* O loop abaixo irí pecorrer a array usando o ponteiro e irí mostrar na tela oq a array contem. */ while (Count < 50) { printf("%d ", *(MeuPonteiro + Count)); Count++; } system("pause"); return 0; } A linha abaixo faz o seguinte:

    *(MeuPonteiro + Count) = Count + 1;

    O valor de MeuPonteiro que e um endereço e obtido depois e somado com Count, e depois o operador * irí permitir que acessemos esse endereço, onde e copiado usando o operador =, Count + 1.

    A linha acima poderia ser substituida por:

    *MeuPonteiro++ = Count + 1;

    E o ponteiro seria resetado assim:

    MeuPonteiro = MeuPonteiro - 50;

    Onde MeuPonteiro++ e o mesmo que: MeuPonteiro = MeuPonteiro + 1; dessa forma pecorremos os bytes da array incremetando o endereço do primeiro byte que faz com que o ponteiro aponte pro segundo byte mas note que MeuPonteiro depois da expressao irí apontar para o endereço + 1, por que MeuPonteiro++ e o mesmo que MeuPonteiro = MeuPonteiro + 1, observe o operador =, por isso e necessario resetar o ponteiro, se vc deseja passar pelos bytes iniciais, porque em outras palavras o operador ++ modifica o seu operando; Um exemplo mais simples segue:

    #include <stdio> #include <stdlib> int main(void) { /* Grupo de bytes inicializado, e terminado por 0 */ char MinhaString[] = "Ola mundo!"; /* Coloca o endereço do primeiro elemento da array em MeuPonteiro */ char *MeuPonteiro = MinhaString; /* Enquanto o byte apontado por MeuPonteiro não e 0 */ while (*MeuPonteiro != '\0') { /* Mostre o determinado byte */ putchar(*MeuPonteiro); /* Depois que mostrou o byte aponte pro proximo */ MeuPonteiro++; } /* Nova linha */ putchar('\n'); system("pause"); return 0; } Compile o exemplo acima e vera que uma string e mostrada na tela usando ponteiros.
    Se vc não esta lembrado uma string e uma array de characteres terminada por um 0. Quando vc cria uma string:
    char MinhaString[] = "Ola mundo!"; o 0 e colocado depois do sinal de !. Observe também que na linha:

    MeuPonteiro++

    Acontece:

    MuPonteiro = MeuPonteiro + sizeof(TIPO_DE_OBJETO);

    Dessa forma apontamos pro proximo byte da string.

    Vale apena salientar que MeuPonteiro++ pode variar de acordo com o tipo de ponteiro, se for um ponteiro para character então e somado sizeof(char) ao endereço, se for um ponteiro pra um inteiro e somado o tamanho do inteiro, sizeof(int), se for um ponteiro para um float e somado sizeof(float), e ser for um ponteiro para um double e somado sizeof(double).

    Utilizando operadores aritimeticos como +, -, com ponteiros e chamado de aritimetica com ponteiros que de acordo com o tipo de ponteiro tem um efeito diferente, observe o exemplo abaixo:

    #include <stdio> #include <stdlib> int main(void) { /* Declaracao de uma array de inteiros Smile */ int MinhaArrayDeInteiros[50]; /* Nosso ponteiro apontando pro inicio da array */ int *MeuPonteiroPraInteiros = MinhaArrayDeInteiros; /* Mostra oq o ponteiro contem */ printf("endereço que ponteiro contem = %#X\n", MeuPonteiroPraInteiros); /* Aqui incremente o endereço de MeuPonteiroPraInteiros por sizeof(int) ou seja o endereço do ponteiro inicial e somando por sizeof(int), e não por 1, pq não estamos lidando com 1 byte; Assim apontamos pro proximo inteiro, e acessamos o mesmo colocando 10 nele. */ *++MeuPonteiroPraInteiros = 10; /* Mostra oq o ponteiro no momento contem */ printf("Agora endereço que ponteiro contem = %#X\n", MeuPonteiroPraInteiros); /* Mostra a diferenca do endereço final em relacao ao endereço inicial */ printf("Diferenca = %d\n", (int)MeuPonteiroPraInteiros - (int)MinhaArrayDeInteiros); /* Usa indexacao [] para se acessa minha array que foi modificada apartir do ponteiro*/ printf("%d\n", MinhaArrayDeInteiros[1]); system("pause"); return 0; } sizeof() se vc estiver esquecido retorna o tamanho de um tipo de dado.

    E possivel tambem se ter arrays de ponteiros ou seja uma array onde todos os seus elementos sao ponteiros, vejamos:

    char *MinhaArraydePonteiros[10];

    Na declaracao acima uma array de 10 ponteiros pra characteres e criada, ou seja uma array de 10 elementos que sao enderecos de memoria.

    O uso de uma array de ponteiro e bem eficaz e dinamico, muitas vezes precisamos de mais de 1 ponteiro em nossos programas para apontar para variaveis que muitas vezes nao sabemos oq seram ou quantas seram, observemos o caso de um suposto programa editor de texto; Sabemos que a cada caractere que o usuario tecla esse caractere deve ser gravado em um buffer ou em uma alocacao de memoria, entao digamos que implementamos uma funcao que se obtenha uma sequencia de caracteres, quando o usuario pressiona enter sabemos que temos uma linha, em um programa de texto haveram varias linhas, entao entra-se em questao, onde guardar essas linhas, e como se ter controle de todas essas linhas, se a cada chamada de uma suposta funcao EntreLinha() 1 buffer seria preenchido, onde estaria esse buffer? voce poderia fazer uma array multidimensional porem memoria seria altamente disperdicada se o usuario precisa-se somente de umas 10 linhas e voce aloca-se espaco para 1000, por isso e usado uma array de ponteiros para charactere, lembra da sessao de memoria dinamica e ponteiros, o dinamismo do ponteiro resolve o problema, EntreLinha() retornaria um ponteiro para uma linha que foi alocada na memoria dinamicamente e esse ponteiro seria copiado para a array de ponteiros e um inteiro de posicao da array seria incrementado, nesse caso por simplicidade e tambem pq como tudo e limitado a array de ponteiros teria de ter um tamanho predeterminado e limitado digamos 1000 linhas, entao imagine que em um determinado momento o usuario do programa precisa procurar por uma string dentro das linhas, simplesmente seria pecorrida a array de ponteiros acessando-se a memoria em que os ponteiros aponta; Se nao fosse com uma array de ponteiros como ordenaria-mos as linhas sequencialmente, assim?

    #define TAMANHO_DA_LINHA 200

    buf1[TAMANHO_DA_LINHA]
    buf2[TAMANHO_DA_LINHA]
    buf3[TAMANHO_DA_LINHA]
    ...
    ...
    ...

    Com certeza nao!

    Talvez assim?

    #define MAXIMO_DE_LINHAS 1000

    buf[MAXIMO_DE_LINHAS][TAMANHO_DA_LINHA]

    Com certeza nao!

    Voce ver no procedimento acima array multidimensional, seria alocado MAXIMO_DE_LINHAS(1000) * TAMANHO_DA_LINHA(200) que no caso seria 200,000 bytes que e disperdicio desde que vc nao sabe se o usuario somente precisa de 10 linhas ou seja 10 * 200 que e igual a 2,000 bytes.

    Entao a solucao e:

    char *MinhaArraydePonteiros[MAXIMO_DE_LINHAS];

    Pq ai memoria e alocada de acordo com a necessidade de linhas, onde custariamos espaco inicialmente somente para os ponteiros ou sizeof(char *) * 1,000 que e igual a 4,000 bytes, e quando 10 linhas fossem tecladas, 10 * 200 teriamos 2,000, ao todo estariamos tomando 4,000 + 2,000 que e 6,000 bytes que comparado com a array multidimensional 200,000 bytes e absurdamente mais flexivel.

    Observe um exemplo:

    Leia o exemplo abaixo atenciosamente, e compile.

    #include <stdio> /* Para IO*/ #include <stdlib> /* Para rotinas em geral */ #include <time> /* Calendario */ /* Definicao do limite de linhas */ #define NUMERO_DE_LINHAS 1000 /* Definicao do tamanho de uma linha */ #define TAMANHO_DA_LINHA 200 /* Definicao de uma string de error */ #define ERR_SEM_MEMORIA "Erro: sem memoria suficiente." /* A definicao de uma Array de Ponteiros para characteres observe a sintaxe */ char *Linhas[NUMERO_DE_LINHAS] = {NULL}; /* Inicializada pra NULL */ /* Index de linha, representa a linha atual dentro de Linhas.*/ int NumLinhas = 0; /* Mostra sugestoes sobre um texto que voce possa escrever */ void MostreUmaSugestao(void); /* Entrada de uma linha pelo teclado */ char *EntreLinha(void); /* Mostra todas as linhas em LinhasParam na quantidade exata */ void MostreLinhas(char *LinhasParam[], int QuantasLinhas); /* Limpa todas as linhas em LinhasParam na quantidade exata */ void LimpeLinhas(char *LinhasParam[], int QuantasLinhas); /* Funcao inicial */ int main(void) { /* Mostra um titulo de programa amigavel */ puts("Usuario(a), bem vindo ao editor de texto," " para terminar digite '.' ponto, no comeco de uma" " linha e pressione [ENTER]."); puts(""); /* Mostra uma sugestao, veja declaracao da funcao logo abaixo */ MostreUmaSugestao(); /* Enquanto nao passamos do limite de linhas */ while (NumLinhas < NUMERO_DE_LINHAS) { /* EntreLinha() retorna um ponteiro para uma linha para dentro de Linhas */ Linhas[NumLinhas] = EntreLinha(); /* Se o primeiro charactere de Linhas em uma determinada linha for . saia */ if (Linhas[NumLinhas][0] == '.') break; /* Proxima linha */ NumLinhas++; } puts(""); printf("Voce escreveu %d linha(as).\n", NumLinhas); puts("Mostrando toda(as) a(as) linha(as)..."); puts(""); /* Declaracao abaixo */ MostreLinhas(Linhas, NumLinhas); /* Declaracao abaixo */ LimpeLinhas(Linhas, NumLinhas); puts("O fim."); puts(""); system("PAUSE"); return 0; } /* Mostra uma sugestao declaracao */ void MostreUmaSugestao() { /* Todas as sugestoes */ /* Observe que Sugestoes, abaixo e uma array multidimensional de 2 dimensoes, inicializada com todas as possiveis sugestoes, saiba tambem que e alocado em bytes 10 * 60 = 600 bytes. */ char Sugestoes[10][60] = { "Historia da sua vida", "Melhor dia da sua vida", "Sua primeira vez", "Pior dia da sua vida", "Um fato traumatico", "Um objetivo a ser alcancado para o futuro", "Relacionamento familiar", "Melhores amigos(as)", "Ponteiros", "Arrays de ponteiros" }; /* Numero que representa a data e hora do sistema */ time_t t; puts("Escreva sobre: "); /* Inicializa a funcao rand() para pegar uma sugestao aleatoriamente */ srand(time(&t)); /* Pega uma sugestao aleatoriamente */ printf("%s.\n\n", Sugestoes[rand() % 10]); } /* Entra uma linha pelo teclado */ char *EntreLinha(void) { /* Esse buf e temporario ira segura a linha por um momento */ char Buf[TAMANHO_DA_LINHA]; /* Esse e um ponteiro para a linha que sera alocada */ char *Linha = NULL; /* Abaixo Pega uma linha para dentro de buf, note fgets() coloca '\n' que representa uma nova linha, dentro de buf. */ fgets(Buf, TAMANHO_DA_LINHA, stdin); /* Abaixo e alocado memoria para Linha de acordo com o tamanho de "caracteres" em Buf. strlen(Buf) + 1 + 1 e necessario para se reservar espaco para o NULL. */ Linha = (char *)malloc((strlen(Buf) + 1) * sizeof(char)); /* Alocou memoria ok? senao mostre erro, e saia. */ if (!Linha) { puts(ERR_SEM_MEMORIA); exit(EXIT_FAILURE); } /* Copie Buf para dentro da Memoria alocada apontada por Linha */ strcpy(Linha, Buf); /* Retorne um ponteiro para a memoria alocada para a linha que e copiado para dentro da array de ponteiro de caracteres depois. */ return Linha; } /* Mostre linhas no console */ void MostreLinhas(char *LinhasParam[], int QuantasLinhas) { int i; /* Observe que LinhasParam[x] retorna um endereco para uma linha */ for (i = 0; i < QuantasLinhas; i++) if (LinhasParam[i]) /* Nao pode ser NULL */ printf(LinhasParam[i]); /* E diferente de NULL acesse endereco */ } /* Libera memoria alocada para as linhas */ void LimpeLinhas(char *LinhasParam[], int QuantasLinhas) { int i; /* Observe que LinhasParam[x] retorna um endereco para uma linha */ for (i = 0; i <QuantasLinhas> ou operador seta, vejamos: PonteiroPraMinhaStruct = &InstanciaMinhaStruct; PonteiroPraMinhaStruct -> Campo1 = 10; printf("%i\n", PonteiroPraMinhaStruct -> Campo1); Observe como o operador -> e usado para acessar os campos de uma estrutura, também e possivel utilizar a seguinte sintaxe:

    (*PonteiroPraMinhaStruct).Campo1;

    Onde os parenteses são necessarios para com oq a estrutura seja acessada apartir do ponteiro primeiro, depois o operador . e aplicado e Campo1 pode ser acessado dentro da estrutura apontada por PonteiroPraMinhaStruct.

    Vejamos um exemplo:

    #include <stdio> #include <stdlib> int main(void) { /* Declara uma struct dentro de main */ struct MinhaStruct { int Campo1; int Campo2; }; /* Inicializa a struct na memoria */ struct MinhaStruct InstanciaMinhaStruct; /* Declara um ponteiro para uma estrutura */ struct MinhaStruct *PonteiroPraMinhaStruct; /* Ponteiro pra estrutura aponta pra instancia na memoria */ PonteiroPraMinhaStruct = &InstanciaMinhaStruct; /* Acesse o campo1 usando -> */ PonteiroPraMinhaStruct -> Campo1 = 10; /* Acesse o campo1 pra mostrar na tela */ printf("%i\n", PonteiroPraMinhaStruct -> Campo1); /* Acesse o campo2 usando sintaxe normal de ponteiros */ /* Note a necessidade dos parenteses por causa que ponto tem precedencia maior */ (*PonteiroPraMinhaStruct).Campo2 = 20; /* Acesse o campo2 pra mostrar na tela */ printf("%i\n", (*PonteiroPraMinhaStruct).Campo2); system("pause"); return 0; } não e facil usar ponteiros com estruturas? Smile não tem segredo.


    Ponteiros e parametros de funcoes

    Muitas vezes em nossos programas precisamos passar parametros para uma funcao, se vc não sabe oq e uma funcao ou não esta tao confiante aqui vai uma revisao:

    Tipo-de-retorno Nome-da-funcao(Tipo-de-parametro Nome-do-parametro, ...);

    Acima o formato de uma funcao em C/C++ o Tipo-de-retorno e oq a funcao retorna podendo ser qualquer dos tipos suportados na linguaguem C/C++, o Nome-da-funcao vc escolhe, e o Tipo-de-parametro Nome-do-parametro, e a declaracao de um parametro para uso dentro da funcao, exemplo:

    void Tabuada(int De, int Ate);

    Seria uma funcao que retorna nada(void) chamada Tabuada e que pega 2 parametros o inteiro De, e o inteiro Ate, onde qualquer linha de codigo chamando a funcao passara os parametros por valor, ou seja valores seram passados nos dois parametros ou variaveis que contenham um valor que seja do mesmo tipo excluindo ponteiros.

    então oq acontece se eu fizer:

    Tabuada(1, 10);

    Estaria passando os valores que programaticamente e chamado: Parametros passados por valor.

    ou

    int x = 1;
    int y = 10;
    Tabuada(x, y);

    Seria a mesma coisa: Parametros passados por valor.

    Quando um parametro e passado por valor, e feita uma copia do mesmo na stack, a stack e um lugar onde as variaveis do seu programa em C/C++ que não são globais, ficam armazenadas. então essa copia do valor fica na stack e não tem nenhum relacionamento com as variaveis x, e y fora da funcao, exemplo:

    #include <stdio> #include <stdlib> /* A funcao exemplo pega 2 parametros inteiros. E depois pras respectivas copias de a e b que foram passadas pra funcao que estao na stack e escrito 10 e 90, então se 10 e 90 e escrito para as copias as variaveis que foram passadas por valor não são afetadas, somente as copias. */ void Exemplo(int a, int { a = 10; b = 90; } int main(void) { int x = 1, y = 2; /* Chama a funcao Exemplo() no qual e feita uma copia de x e y na stack. */ Exemplo(x, y); /* x continua 1 e y continua 2 */ printf("X = %d, Y = %d\n", x, y); system("pause"); return 0; } Então aqui e onde ponteiros entram em acao, e utilizado ponteiros para se modificar o valor de variaveis de dentro de uma funcao!!!

    Ou seja, desde que, quando chamamos uma funcao passando parametros por valor, copias dos valores são feitas exclusivas para a funcao na stack, então se vc modifica o parametro da funcao vc não afeta as variaveis que foram usadas para se passar pra funcao, mas sim as copias que foram feitas automaticamente que estao na stack, então as variaveis que foram usadas pra se passar pra funcao ficam intocaveis, a solucao para esse problema: variaveis intocaveis, e o uso de ponteiros.

    Vejamos:

    #include <stdio> #include <stdlib> /* A funcao exemplo pega 2 ponteiros pra inteiros. E depois atravez dos ponteiros e acessado as respectivas variaveis que são passadas por referencia, ou seja os enderecos das variaveis são passados, então os valores 10 e 90 são escritos diretamente. */ void Exemplo(int *a, int * { *a = 10; *b = 90; } int main(void) { int x = 1, y = 2; /* Chama a funcao Exemplo() no qual e feita uma copia dos enderecos x e y na stack. */ Exemplo(&x, &y); /* X foi modificado e Y também */ printf("X = %d, Y = %d\n", x, y); system("pause"); return 0; } Se vc compilar o exemplo acima vera que x e y, variaveis dentro de main() são modificadas pela funcao Exemplo() que recebe o endereço das variaveis, que e chamado de: Parametros passados por referencia.

    Lembra de:

    scanf("%c", &MeuChar);

    Isso mesmo e necessario uma chamada por referencia para com que a variavel MeuChar possa ser acessada por scanf; Onde o endereço da variavel e passado pra funcao e a mesma modifica a variavel, se voce nao passar o endereco, scanf() pegara o valor de MeuChar pensando que o mesmo e um endereco, no qual nao e, e scanf() tentara copiar um caractere para um espaco de memoria que possa estar protegido, e o sistema abortara o programa com erro de write access violation.

    Isso vale para qualquer variavel que vc deseja modificar de dentro de uma funcao, arrays, estruturas, etc.

    Observe o exemplo abaixo:

    #include <stdio> #include <stdlib> /* Essa funcao troca o valor em x pelo de y */ void Troca(int x, int y) { int temp; temp = x; /* Guarda x*/ x = y; /* Troca por y */ y = temp; /* Troca por x */ printf("copia de x = %d e copia de y = %d\n", x, y); } int main(void) { int x, y; x = 10; y = 20; puts("x e y inicial: "); printf("x = %d e y = %d\n", x, y); /* Parametros passados por valor */ Troca(x, y); /* Continua o mesmo */ puts("Dentro de main:"); printf("x = %d e y = %d\n", x, y); system("pause"); return 0; } Analizando a chamada da funcao Troca(x, y), parametros sao passados por valor, oq siguinifica que de dentro da funcao nao ha como se referenciar as variaveis que foram declaradas dentro de main, entao siguinifica que apesar de Troca() trocar os valores, esses valores seram trocados usando as copias de x e y que foram feitas que estao na stack, por tanto quando a funcao retorna, x e y dentro de main continuam a mesma coisa.

    Observe o exemplo abaixo:

    #include <stdio> #include <stdlib> /* Essa funcao troca o valor em x pelo de y */ void Troca(int *x, int *y) { int temp; /* Observe o uso do operador * para acessar as variaveis */ temp = *x; /* Guarda x */ *x = *y; /* Troca por y */ *y = temp; /* Troca por x */ } int main(void) { int x, y; x = 10; y = 20; puts("x e y inicial: "); printf("x = %d e y = %d\n", x, y); /* Parametros passados por referencia */ Troca(&x, &y); /* Troca() modifica */ puts("Dentro de main:"); printf("x = %d e y = %d\n", x, y); system("pause"); return 0; } Chamando Troca() com parametros passados por referencia, e dado a funcao os enderecos das variaveis aonde se encontram os dados dessa forma de dentro da funcao e possivel se acessar esses dados, entao as variaveis de dentro de main() sao modificadas.

    Funcoes que retornam um ponteiro

    Funcoes que retornam um ponteiro são funcoes que retornam o endereço em memoria de uma variavel dessa forma e possivel manipular a variavel apartir do ponteiro, vejamos o exemplo:

    #include <stdio> #include <stdlib> #include <string> /* Para usar strupr() */ /* A funcao abaixo pega 1 ponteiro pra um char então a funcao strupr() e chamada passando o parametro Str de StrMaiuscula(), e o retorno e um ponteiro pra um caractere em letra maiuscula que e retornado da strupr(). */ char *StrMaiuscula(char *Str) { return strupr(Str); } int main(void) { char String[] = "minha string Smile"; /* Chama a funcao StrMaiuscula() passando a string String como parametro depois printf() e chamado, desde que StrMaiuscula retorna o endereço de String o uso direto como abaixo e possivel. */ printf("%s\n", StrMaiuscula(String)); system("pause"); return 0; } Como vc pode observar strupr() retorna um ponteiro pra um char por isso:

    return strupr(Str);

    E aceitavel. Pq estamos retornando oq strupr() retornou um ponteiro para um caractere.

    também e necessario lembrar que String, o nome da array e um label que associa o nome String a um endereço, e esse endereço e o endereço do primeiro caractere na memoria, por isso vc não ve o operador & antes de String nas chamadas de funcao, simplesmente pq String ja representa o endereço do primeiro elemento da array, no entanto &String[0] também e possivel.

    Ponteiro pra funcoes

    Se vc não sabe e possivel se declarar um ponteiro pra uma funcao, da seguinte forma:

    Tipo-de-retorno-da-funcao (*Nome-do-ponteiro-pra-funcao)(Tipo-de-parametro Nome-de-parametro, ...);

    Logo um ponteiro pra uma funcao que retorne um inteiro e pega nada seria:

    int (*PonteiroPraFuncao)(void);

    um Ponteiro pra uma funcao que retorna nada e pega um ponteiro pra um inteiro seria:

    void (*PonteiroPraFuncao)(int *);

    Quando obtemos um ponteiro apenas fazemos o mesmo apontar para o endereço de algo, nesse caso o endereço de uma funcao.

    Para se obter o endereço de uma funcao e usado o nome da funcao ou label, o operador & não e necessario, e ilegal, vejamos:

    void (*PonteiroPraFuncao)(int *);

    PonteiroPraFuncao = NomeDaMinhaFuncao;

    Dessa forma podemos chamar uma funcao apartir de seu ponteiro, observe:

    int Inteiro;
    (*PonteiroPraFuncao)(&Inteiro);

    Acima e chamada a funcao void NomeDaMinhaFuncao(int *x) apartir do ponteiro pra funcao, onde parametros são passados.

    Exemplo:

    #include <stdio> #include <stdlib> /* Funcao que retorna nada e pega um ponteiro para um inteiro */ void Funcao(int *PonteiroInt) { /* O mesmo que *PonteiroInt = (*PonteiroInt) * 2 */ *PonteiroInt *= 2; } int main(int argc, char *argv[]) { /* Declara uma variavel x */ int x = 10; /* Declara um ponteiro para uma funcao que retorne nada e pega int * */ void (*PonteiroPraFuncao)(int *); /* Faz com oq PonteiroPraFuncao aponte pra Funcao */ PonteiroPraFuncao = Funcao; /* Chama funca(&x) apartir de PonteiroPraFuncao */ (*PonteiroPraFuncao)(&x); /* x = 20 */ printf("x = %d\n", x); system("PAUSE"); return 0; } Ponteiros para ponteiros

    Lembra quando escrevi que ponteiros sao variaveis? Toda variavel possui um endereco de localizacao na memoria, entao ponteiros por serem variaveis possuem seu endereco na memoria, no qual ironicamente um ponteiro guarda um endereco de outra variavel, entao desde que ponteiros tem enderecos, pq nao ter como guardar o endereco de um ponteiro, logo temos ponteiros para ponteiros.

    Um ponteiro para um ponteiro e uma variavel que guarda o endereco de outro ponteiro, dessa forma apartir do endereco de um ponteiro, ou seja o endereco onde um ponteiro se encontra, podemos acessar o mesmo para escrita e leitura, e ate acessar ao oq o mesmo aponta.

    Para se declarar um ponteiro para um ponteiro e usada a seguinte sintaxe:

    Tipo **NomeDoPonteiro;

    Onde Tipo e qualquer tipo de dados da linguagem C/C++, os asteristicos, 2 no caso, representam que a variavel a ser declarada e um ponteiro para um ponteiro.

    Como em,

    char **pp;

    Entao digamos se temos:

    char MeuChar = '@';

    char *PonteiroParaChar = &MeuChar;

    Fazemos com oq PonteiroParaChar aponte para MeuChar. Logo depois:

    char **PonteiroParaPonteiroParaChar = &PonteiroParaChar;

    Observe que PonteiroParaPonteiroParaChar aponta para o PonteiroParaChar, oq siguinifica que PonteiroParaPonteiroParaChar contem o endereco onde se encontra o PonteiroParaChar.

    Para se accessar oq o ponteiro dentro de PonteiroParaPonteiroParaChar aponta e utilizada a seguinte sintaxe, observe:

    printf("%c\n", **PonteiroParaPonteiroParaChar);

    Que retorna oq o ponteiro que o ponteiro para ponteiro aponta contem, que e o char arroba ou @.

    Digamos que queira modificar esse char apartir do ponteiro para ponteiro, entao:

    **PonteiroParaPonteiroParaChar = '*';

    Agora MeuChar contem asterisco ou *.

    Para se entender oq esta acontecendo considere essa explicacao:

    O operador * retorna um valor de um tipo de dados em um endereco de memoria, ou seja quando usamos
    o operador * com PonteiroParaPonteiroParaChar dessa forma: *PonteiroParaPonteiroParaChar desde que PonteiroParaPonteiroParaChar contem o endereco de um ponteiro, acessamos o determinado ponteiro; E o que acontece no caso de **PonteiroParaPonteiroParaChar, observe os parenteses em:
    *(*PonteiroParaPonteiroParaChar) 1o e acessado o ponteiro, que claro contem o endereco de uma variavel, e 2o e por ultimo temos o seguinte *(Endereco de uma variavel), onde o operador asteristico acessa essa determinada variavel, logo no caso acessamos Meuchar.

    Observe o exemplo com atencao e compile:

    #include <stdio> #include <stdlib> int main(void) { char MeuChar = '@'; char *MeuPonteiro = &MeuChar; char **MeuPonteiroParaPonteiroParaChar = &MeuPonteiro; puts("Nome: MeuChar"); printf("Endereco: %#p\n", &MeuChar); printf("Valor: %c\n", MeuChar); puts(""); puts("Nome: MeuPonteiro"); printf("Endereco: %#p\n", &MeuPonteiro); printf("Valor: %#p\n", MeuPonteiro); printf("** Observe que o valor de MeuPonteiro e o endereco" " de MeuChar **\n"); printf("Acesse endereco: %c\n", *MeuPonteiro); puts(""); puts("Nome: MeuPonteiroParaPonteiroParaChar"); printf("Endereco: %#p\n", &MeuPonteiroParaPonteiroParaChar); printf("Valor: %#p\n", MeuPonteiroParaPonteiroParaChar); printf("** Observe que o valor de MeuPonteiroParaPonteiroParaChar e o endereco" " de MeuPonteiro **\n"); printf("Acesse endereco: %#p\n", *MeuPonteiroParaPonteiroParaChar); printf("** Observe que acessando o valor de MeuPonteiroParaPonteiroParaChar" " que e o endereco de MeuPonteiro, encontramos o endereco de MeuChar **\n"); printf("Acesse ponteiro para ponteiro: %c\n", **MeuPonteiroParaPonteiroParaChar); puts("** Encontramos o que o ponteiro apontado pelo ponteiro pra ponteiro aponta **"); puts(""); system("pause"); return 0; } Vejamos um dos usos de um ponteiro para um ponteiro; Digamos que voce queira fazer uma funcao que aloque memoria e que um ponteiro para essa memoria seja retornado, nao necessariamente voce precisa retornar esse ponteiro, por que nao passar um endereco de um ponteiro para a funcao, no qual quando voce chamar a funcao voce passa o endereco de um ponteiro do tipo de dados para a alocacao, onde apartir dai pelo endereco do ponteiro voce pode modificar o ponteiro que esta em algum lugar no seu programa, copiando para o mesmo o endereco dos bytes recem alocados, veja o exemplo:

    #include <stdio> #include <stdlib> /* Recebe um endereco para um ponteiro */ void Exemplo(char **p) { /* Como p e o endereco de um ponteiro use o operador * para acessar esse endereco e copiar o endereco retornado por malloc(). */ *p = malloc(30); } int main(void) { char *p; /* Chamada por referencia */ Exemplo(&p); /* Memoria foi alocada copie dados */ strncpy(p, "Test 123\n", 30); /* Mostre na tela */ printf(p); system("pause"); return 0; } Um outro uso de ponteiro para ponteiro e com array de ponteiros; Da mesma forma que e possivel utilizar um ponteiro para se caminhar por uma array de um tipo, e possivel se usar um ponteiro para um ponteiro para se caminhar por todos os items de uma array de ponteiros que por sinal sao ponteiros, e nao e exatamente isso ao que um ponteiro para um ponteiro aponta.

    Vejamos um exemplo:

    #include <stdio> #include <stdlib> int main(int argc, char *argv[]) { char **pp = argv; while (argc-- > 0) printf("%s\n", *pp++); system("pause"); return 0; } E declarado um ponteiro para um ponteiro chamado pp, que e inicializado para o valor de argv, no qual e um endereco para um ponteiro, depois no while loop, pp e incrementado assim: pp += sizeof(char *); dessa forma o proximo endereco para um ponteiro e acessado, ja o operador * acessa os enderecos especificos onde e encontrado enderecos, que e o parametro para printf() mostrar uma string de argumento.

    Ponteiros em C/C++
    por: C0d3r__
  2. Upvote
    JonatasLucasf deu reputação a Administrador em Como fazer nature! (grama + terra + areia)   
    Eai pessoal, resolvi fazer este tutorial pra vocês. Vou ser bastante breve para não complicar muito.
    Começamos com as bordas, são elas que provocaram um "efeito especial" no mapa. Veja o resultado que você pode alcançar apenas vendo este tutorial:

     


    Para começar, você deve aplicar as bordas uma por uma. Tente sempre diferenciar, nunca colocar as bordas na mesma posição, direcione ela para lados diferentes. Veja estes exemplos:



    Tome cuidado para a direção em que você está indo! Você pode optar por fazer estradas retas ou espalhadas, que seria mais o caso da nature.





    #01
    Adicione as bordas de terra, tenha em mente que a grama estará por cima dela, então deve conter pelo menos um tile antes da borda para caber a grama (no contrário, a grama cobrirá a borda de terra e não adiantará ter colocado).





    #02
    Agora, aplique a borda da grama, deixando espaços proporcionais para a terra poder "respirar":





    #03
    Existe uma borda de grama que tem terra visível em baixo:



    Aplique em pequena quantidade, em algumas bordas comuns, cuide para não ficar excessivo.





    #04
    Aplique as bordas de sand, em pouquíssima quantidade e em lugares estratégicos, como onde as bordas avançam muito (pontas):





    #05
    Adicione a grama, tente utilizar as gramas mais "machucadas" pra fortalecer a temática de natureza abandonada e as mais lisas para ambientes mais limpos:








    #06
    Agora detalhe, Pedras e Debris são de extrema importância. Grass Tufts invadindo em pouca quantidade dão um toque especial no mapa, veja:




    Junte isto e terá:




  3. Upvote
    JonatasLucasf recebeu reputação de FelipeXT em Ajuda preencher weblara   
    Hostname: nome do seu dominio (se não tiver pode escrever seu nome ou algo)
    Prefixo ns1 e ns2: são name servers se você tiver um domínio pegue os nameservers deles, se não tiver deixe em branco ou escreva algo.
     
    SENHA DO ROOT: a senha pra você acessar seu host
     
    quando o pagamento for aprovado eles mandarão informações de como se conectar pelo seu email.
  4. Upvote
    JonatasLucasf deu reputação a Administrador em Daniel Spriting   
  5. Upvote
    JonatasLucasf deu reputação a VictorWEBMaster em Rank Reset   
    Opa, salve!
    Utilize o highscore abaixo!
    Estou à disposição
     


     
    Para que você consiga fazer o sistema funcionar perfeitamente, você deve adicionar isso a uma classe dentro da pasta de classes.
    Abra a pasta de classes do seu gesior, edite a players. Pode substituir tudo... por isto:


     
    Caso dê algum erro, verifique o nome da tabela de resets, deve ser reset, caso seja resets, mude no player.php tudo que se refere a reset.
     
    Espero ter ajudado.
  6. Upvote
    JonatasLucasf deu reputação a Bruno em Dominus World - The new era   
    Introdução

    Este é um Baiak com o mapa modificado e atualizado com a última versão do Tibia, o intuito do projeto é valorizar um mapa muito jogado mesclando com o que há de novo. O Servidor será composto pela city principal, que segue o padrão do mapa porém com um diferencial, é uma cidade isolada, cercada por uma imensa muralha onde será acessível apenas por passagens secretas ou por navegação.



    Showoff

















    Sistemas

    Em breve



    Agradecimentos

    @Daniel
    @RetornoDeLaug
  7. Upvote
    JonatasLucasf deu reputação a Benny em [Pedidos] ~ Beeny   
  8. Upvote
    JonatasLucasf deu reputação a moskitinho em Tutorial #02 • 10 Dicas de Iluminação   
    E ai beleza?!
     
    Bom galera seguindo aquela minha série de screencasts que eu havia feito a alguns anos atrás, hoje trago pra você algumas dicas de iluminação que vão ajudar o pessoal que está começando, ter uma noção do que pode ser usado. São 10 dicas muito boas que podem dar uma força na hora de finalizar sua sign. Assistam em 720p.
     
    Não esqueça de se inscrever no canal e compartilhar o conteúdo!
     
    Link • Tutorial #01
     


    Tutorial #02 • 10 Dicas de Iluminação
    Rate • Iniciante/Low







    Recursos • Infelizmente não possuo mais, porém com a técnica da pra desenvolver outros.


     
    Espero que gostem e em breve eu vou trazer novos tutorias pra vocês, deixem sugestões do que gostariam de aprender.
  9. Upvote
    JonatasLucasf deu reputação a Benny em [X] Tutorial - Sign ( Iniciantes )   
    https://www.youtube.com/watch?v=4PV3hFhMULI









    Tá, antes de tudo, desculpa

    Eu nunca fiz esse tipo de vídeo, então tava nervoso pra kct HDUAHUAHA

    Pode perceber pela respiração, pelas vezes que eu esqueci a palavra e tal.

    E não, eu não tava forçando a voz q

    Ela é escrota assim mesmo







    PSD



    (:
  10. Upvote
    JonatasLucasf deu reputação a Bruno em Vanaheim global open source   
    Alterações:
    Versão mínima alterada para 1077, para que dê suporte aos novos outfits e montarias; A talkaction newtypes suporta os novos outfits e montarias; Fixada a velocidade das montarias; Fixado o oufit Spirit Caller male. Downloads: Executável 32 bits - Download | Scan |
    Executável 64 bits - Download | Scan |
  11. Upvote
    JonatasLucasf deu reputação a Furabio em [TFS 1.x] /addplayersonline item, quantidade   
    Script simples mas pode ser útil, para os ot admin.
     
    data/talkactions/scripts addplayersonline.lua :
    function onSay(player, words, param) if not player:getGroup():getAccess() then return true end if player:getAccountType() < ACCOUNT_TYPE_GOD then return false end local v = param:split(",") if #v ~= 2 then player:sendCancelMessage("Insufficient parameters.") return false end local item, count = tonumber(v[1]), tonumber(v[2]) for _, pid in pairs(Game.getPlayers()) do pid:addItem(item, count) end broadcastMessage("A equipe acaba de mandar "..count.." "..ItemType(item):getName() " para todos os player online!", MESSAGE_STATUS_WARNING) return false end tag.XML :
    <talkaction words="/addplayersonline" separator=" " script="addplayersonline.lua" />
  12. Upvote
    JonatasLucasf recebeu reputação de Administrador em Novo sistema de Cargos e Novas pips!   
    pra um fórum que eu pensei que nunca mais iria ver, parabéns cada dia melhorando mais.
  13. Upvote
    JonatasLucasf deu reputação a Administrador em Novo sistema de Cargos e Novas pips!   
    Novo Sistema de Cargos!
    Como sabem, nosso sistema hierárquico é composto por Estagiários e Moderadores. Acrescentamos o cargo Coordenador com o objetivo de ajudar a manter a ordem dessa hierarquia. O cargo não está em uso no momento mas já pode ser visualizado. O update dessa semana consiste em novas pips para a galera! É isso mesmo, depois de tanto tempo finalmente trocamos as pips. As pips para membros serão implementadas na próxima semana.
     
    O que é o sistema de sub-cargos e evolução? O sistema de sub-cargos se resume em divisões onde o membro passa por um processo evolutivo em que será avaliado por um superior. Há cinco níveis de avaliação, ela é dada pelo tempo no cargo e pela determinação. Ao ser aceito na equipe, o membro recebe uma pip. Esta pip irá evoluir após um tempo determinado para uma pip superior, esta, significará que o membro está se determinando para com o fórum. Há fatos que indicam que o método de avaliação (tempo), é invalido para o cargo; nesse sentido, o avanço da pip é dado com o tempo + avaliação da equipe. Em resumo, um membro pode repetir o nível do cargo. Ao alcançar o nível superior do cargo, a equipe realiza uma reunião para decidir se o membro é promovido. CARGO TEMPO NÍVEL Estagiário 1 semanas >1 Estagiário 3 semanas >2 Estagiário 4 semanas >3 Estagiário 6 semanas >4 Estagiário 8 semanas >5 Herói Prévia de ranks para membros (Será adicionado no próximo update) (...) Extra - Separadores de tópico xTibia
    ATUALIZAÇÕES: - Concertado bug dos icons de mensagem e notificação que ficavam irregulares somente na index; - Nova cor de fonte (links) no fórum; - Concertado bug de irregularidade na descrição do search; - Painel de informação de usuário reformulado; - Removido bug que alterava o layout da página ao adicionar textos maiores que o UIP; - Reformulação de botões (para staff);
  14. Upvote
    JonatasLucasf deu reputação a Furabio em Dar items para todos jogadores online   
    function onSay(player, words, param)
    if player:getAccountType() <= ACCOUNT_TYPE_TUTOR then
    return true
    end
    local v = param:split(",")
    if #v ~= 2 then
    player:sendCancelMessage("Insufficient parameters.")
    return false
    end
    local item, count = v[1], v[2]
    for _, pid in pairs(Game.getPlayers()) do
    pid:addItem(tonumber(item), tonumber(count))
    end
    broadcastMessage("A equipe acaba de mandar um presente para todos os player online!", MESSAGE_STATUS_WARNING)
    return false
    end

  15. Upvote
    JonatasLucasf deu reputação a Benny em [Pedidos] ~ Beeny   
    Tá, não rolou eu ir pra lá hauhau
     
     



     

  16. Upvote
    JonatasLucasf deu reputação a Furabio em Comando para adicionar MOUNT   
    adiciona em baixo de :
    target:addMount(mountId) target:sendTextMessage(19, "Você recebeu uma montaria!")
    Tópico movido para a seção de dúvidas e pedidos resolvidos.
  17. Upvote
    JonatasLucasf deu reputação a Benny em [Pedidos] ~ Beeny   
  18. Upvote
    JonatasLucasf deu reputação a Bruno em Comando para adicionar MOUNT   
    @@JonatasLucasf,
     
    Crie um arquivo chamado playerMount.lua em data/talkactions/scripts com o seguinte conteúdo:
     
     
     
    E agora em data/talkactions/talkactions.xml adicione a seguinte linha:

    <talkaction words="/addmount" separator=" " script="playerMount.lua" />Para adicionar a mount para o player basta usar:/addmount Player, 1
     
    Lembrando que 1 é o id da Mount.
  19. Upvote
    JonatasLucasf deu reputação a Administrador em IceWars Baiak   
    -Novo Templo
    -Castle 24HRS (Unico) com aviso de invasores
    -Paladin arrumado, agóra pode healar com potion e atacar ao mesmo tempo
    -Utito Tempo San Arrumado Agóra não da mais Exausted em outras magias
    -Dodge System
    -Critical System
    -Itens Donates para vender no Site ou no Jogo
    -Itens VIP a mostra no templo
    -Todos itens DONATES dando as skills normalmente
    -Vários Teleports
    -Novas Hunts
    -Look Frags
    -Potions Editadas
    -War System
    -Muitas quests
    -City editada para um PvP muito melhor
    -Arena PVP
    -Fast Attack ROX Para melhor PvP
    -Quest de set free para Pally/Kinas
    -Quest de set free para Mages
    -quest para armas editadas
    -Treiners com novos visual
    -30% a mais de experiencia para players donates
    -10% a mais de experiencia para guild que domina o Castle 24HRS
    E muito mais!

    Comandos principais:
    !dodoge
    !critical
    !stamina
    !aol
    !bless
    !notice.

    Vamos as imagens:

    templo


    teleports


    Quests


    castle


    hunts do castle


    area donate


    Acc do GOD: 5/god


    Download :http://www.4shared.c.../DiegoWars.html
    Scan: https://www.virustot...sis/1413409264/

    Créditos
    Dieguiin XP
    Marcos Vinicius
  20. Upvote
    JonatasLucasf deu reputação a Benny em [X] Fontes #1   
    Informações :
    Conteúdo : 833 Fontes
    Tamanho : 30MB

    Download


    PS : Não instalem todas, escolham uma por uma.
  21. Upvote
    JonatasLucasf deu reputação a Krono em Biblioteca - Sistemas Operacionais   
    Biblioteca - Sistemas Operacionais
     
     
    • Introdução (iniciante)
    [Linux] O que é Linux? - LuckinhaSan
    Diferença Linux E Windows - SkyDangerous
    Como se conectar a um servidor usando Putty/SSH? - Alexclusive
    [VIDEO-AULA] Como se conectar a uma VPS WINDOWS - tghost
    Se conectando em um VPS Windows - Erimyth
     
    • Utilização (métodos e comandos)
    Comandos Linux Ubuntu - RafaelVidolin
    [Terminal] Comandos Básicos Ubuntu - LuckinhaSan
    Comandos SSH basicos - Krono
    Gerenciamento de pacotes com o APT - Alexclusive
    Baixando Arquivos No Vps/dedicado Sem Upload - eliteimperiosv
     
     
    • SQL (database / site)
    Instalando facilmente Apache + MySQL + phpmyadmin + bibliotecas [OT Server Ready] - Nightz
    Mini Tuto Importando Database - Beeki
    [Linux] Instalando Webmin (Mysql, Apache, Logs, Backups Etc...) - Daniel
     
    • Segurança (prevenção / resolução)
    [Linux] Protegendo seu SSH - Nightz
    [Firewall eSecurity] IPTables & Modules - Spik3ex
    Regras Ip Tables,basica,media,intermediaria,avançadas(Anti-Nukers) - renansmith
    Backup Automatico - Beeki
    [Linux] Backup automatizado do banco MySQL - Nightz
    DDoS Protect Básico [Win & Linux] - LuckinhaSan
     
    • Compilação (metodos diversos)
    DEV C++ Compilando TFS no Windows - Natanael Beckman
    Compilando um Otserv [sem Erros] - Lipyz
    Compilando e Rodando OTserv em Linux Ubuntu 12.04 - Beeki
    Compilando e rodando um OTServ em Linux (debian). Tutorial Definitivo - Luquinh4
    [Tutorial] Compilando TFS v1.0 com MSVC 2013 - ZORAN
     
    • Utilitários (programas / configurações)
    Auto-Restarter Com Screen Linux Debian 6.0 (100% Funcional) - Daniel
    [Linux] Instalando, usando e entendendo o Screen - Nightz
    [Linux] Otimize o desempenho do seu MySQL com o MySQLTuner - Nightz 
    • Outros (diversos)
    [Linux] BackTrack - Da História à Instalação - LuckinhaSan
    Instalando Ambiente Gráfico VPS Linux - Krono
    Abrindo portas do Modem, TD5130. Servidor e Site para internet compartilhada - WizoGales
  22. Upvote
    JonatasLucasf deu reputação a Vodkart em Script Reset BUG   
    local config = { backToLevel = 8, exp = 4200, redskull = false, battle = false, pz = false, stages = { [{0, 4}] = {350,330}, -- free, vip [{5, 9}] = {355,335}, [{10, 14}] = {360,340}, [{15, 19}] = {365,345}, [{20, 24}] = {380,350}, [{25, 29}] = {390,355}, [{30, 34}] = {410,360}, [{35, 39}] = {430,365}, [{40,math.huge}] = {450,370} } } function getResets(cid) return getPlayerStorageValue(cid, 1020) < 0 and 0 or getPlayerStorageValue(cid, 1020) end function setResets(cid, count) return setPlayerStorageValue(cid, 1020, getResets(cid) + count) end function onSay(cid, words, param) if config.redskull and getCreatureSkullType(cid) >= 4 then doPlayerSendCancel(cid, "Voce precisa estar sem red skull para resetar.") return true elseif config.pz and not getTilePzInfo(getCreaturePosition(cid)) then doPlayerSendCancel(cid, "Voce precisa estar em protection zone para resetar.") return true elseif config.battle and getCreatureCondition(cid, CONDITION_INFIGHT) then doPlayerSendCancel(cid, "Voce precisa estar sem battle para resetar.") return true end for var, ret in pairs(config.stages) do if getResets(cid) >= var[1] and getResets(cid) <= var[2] then resetLevel = isPremium(cid) and ret[2] or ret[1] end end if getPlayerLevel(cid) < resetLevel then doPlayerSendCancel(cid, "Voce precisa do level " .. resetLevel .. " ou mais para resetar.") return true end setResets(cid, 1) local guid = getPlayerGUID(cid) doRemoveCreature(cid, true) return db.query("UPDATE `players` SET `level` = " .. config.backToLevel .. ", `experience` = " .. config.exp .. " WHERE `id` = " .. guid) end
  23. Upvote
    JonatasLucasf recebeu reputação de Furabio em [PEDIDO] Mapa para [Battlefield Event] Versão 10.77   
    aqui está http://www.mediafire.com/download/kmgk84gmr9swq59/Battlefield_Map_by_Absolute_10.77.rar testa ai qualquer coisa se avisa.
  24. Upvote
    JonatasLucasf deu reputação a Bruno em Vanaheim global open source   
    Compatibilidade com a versão 10.78 e foram removidos inclusões desnecessárias.
  25. Upvote
    JonatasLucasf deu reputação a Furabio em Comando /save e Clean automático   
    function onSay(player, words, param)
     
    if not player:getGroup():getAccess() then
    return true
    end
     
    if player:getAccountType() < ACCOUNT_TYPE_GOD then
    return false
    end
     
    saveServer()
    Game.broadcastMessage('Server is saved.', MESSAGE_STATUS_WARNING)
     
    return false
    end

  • Quem Está Navegando   0 membros estão online

    • Nenhum usuário registrado visualizando esta página.
×
×
  • Criar Novo...