-
Total de itens
884 -
Registro em
-
Última visita
Tudo que vangodp postou
-
o primeiro é uma declaração de ponteiro a slNode. Ponteiros são um tipo especial de memória, servem para guardar direções de memória para manipular outras variáveis do mesmo tipo indiretamente. O segundo se trata de um declaração de variável.
-
No fundo a declaração de uma variável implica na reserva de memória, e cada tipo de dado quer dizer o tamanho que vai ocupar, normalmente se medi em Bytes.
-
busque no google "programação orientada a eventos". Leia coisas como "send keys" en google, busque informação sobre a função keybd_event(), entc. https://msdn.microsoft.com/es-es/library/windows/desktop/ms646304%28v=vs.85%29.aspx Da uma olhada nesse pequeno programa que manda mensagens automaticos por chat, serve em qualquer chat: http://darkgames.forumeiros.com/t635-fts-flood-MSN ...Nele você pode ver como funciona keybd_event(), e aqui você tem uma lista de teclas que pode usar com keybd_event(): https://msdn.microsoft.com/es-es/library/windows/desktop/ms646304%28v=vs.85%29.aspx
-
ok! Qual sua duvida?
-
Acho que o livro que você está lendo parece algo desatualizado, void main não é muito recomendável atualmente, certamente com compiladores mais modernos podem mostrar avisos. Sobre sua pergunta posso lhe dizer que sim é possível efetuar operações aritméticas sobre praticamente qualquer tipo de dados básicos como float, int, char, etc. No caso de chars pode parecer algo descabelado, porem tem uma explicação, a causa é por conta da tabela asc2. Na tabela asc2 cada letra tem um valor decimal atribuído, no seu exemplo, t=5 quer dizer que t é igual ao caractere não imprimível ENQ, que em outras palavras é um caractere de "consulta", não sei realmente o que faz esse caractere, só sei que quando você faz char t = 5; quer dizer que você quer pegar o caractere numero 6... ele é o seis porque começa a contar de zero(zero, um, dois, três, quatro e cinco = 6), e você joga ele na variável t que é do tipo char, então ele vai tomar o caractere ENQ, em outras palavras, vamos ver um exemplo com o caractere 'a'. Se declaro uma variável tipo char e a chamo de t(char t;) se logo depois eu pegar e jogar o valor em decimal que corresponde ao 'a', t vai tomar a letra 'a', porque como falei antes, trata-se de um char. Veja o exemplo: char t = 97; // t recebeu 'a' por que é do tipo char. 97 corresponde a 'a' na tabela asc2 int t= 'a'; // t recebeu 97 porque é do tipo int. Recebeu 97 porque trata-se de uma variavel inteira, ela guarda valores e não letras, ela guardou o valor em decimal da letra 'a' conforme a tabela asc2. char t = 97+1; // t vai receber 'b', pois 97+1 é 98, e 98 na tabela asc2 corresponde a 'b'. int t = 'a'+'b'; // t vai receber 195 pois t é do tipo int, por isso receberá somente inteiros. Receberá o valor somado da tabela asc2 correspondente a 'a' + 'b' (97+98) equivale a int t = 97+98 ; Acho que ficou claro... se eu tiver uma variável do tipo char vamos recebe letras, si efetuamos uma operação de soma, receberemos letras porem em base a ordem que vai de 0 a 255 em decimal, é como si somamos "posições", se a variável fosse do tipo int então recebo valores esses valores em decimal(0 a 255), por isso se pode aplicar operações básicas ao tipo char, porque se aplica a esses valores decimais que na realidade estão marcando a posição das letras. Eu posso somar 97+97 ou 'a' + 'a', o que você deve ter em conta é o tipo da variavel que vai ser "jogado" o resultado, se for um int só guarda números, se for char só guarda letras, mas tudo vai em base desses valores de 0 a 255 que representa as posiçoes de cada letra na tabela. Essa tabela é muito importante na programação, guarde ela. Agora que aconteceria se somo 255+1? voltamos ao zero! Em outras palavras, 255+1 é igual a zero, zero representa NULL na tabela, pois se estou na ultima letra e somo um volto ao principio pois não existe 256, eu falei antes que só temos de 0 a 255, porem imagine que é algo como isso 0, 1, 2, 3.........253, 254, 255, 0 <-voltamos a zero si passamos de 255, é como se fosse um bucle. Vamos ver algo de código: #include <stdio.h> int main (){ char t = 255+1; // if (t == NULL)//se t é igual a NULL mostra "NULL" na tela printf("NULL"); else printf("não é null"); return ; } Como você pode ver se somo a ultima letra da tabela que é a 255 com 1 volto ao principio, ou seja zero, dai vai mostrar o mensagem "NULL", ou mostra "Não é Null" se troco o 255+1 por qualquer outros valores. se ponho char t = 800 é como se eu passa-se 3 vezes por zero, 0, 1, 2, 3...253, 254, 255, 0, 1, 2, 3...253, 254, 255, 0, 1, 2, 3...253, 254, 255, 0..., nunca saímos desses 0 a 255, algo semelhante acontece com todos os tipos de variáveis, você só pode representar uma "margem" de valores de x a z valores. veja isso para entender: http://1.bp.blogspot.com/-_s9g4AGdR7Q/Tz0s3bFJxII/AAAAAAAAAGE/tG8jGzF4Rro/s1600/Tipos+de+dados(C++).png A mesma coisa acontece ao contrario, se a 0 resto 1 então vai mostrar o caractere 255 porem para isso devo usar um cast a unsigned char na hora de imprimir para mostrar corretamente já que se imprimimos um char como int(%d) mostraria resultados negativos. Veja o exemplo seguinte: #include <stdio.h> int main (){ char t = - 1; printf("%d", (unsigned char)t ); return ; } É algo complicado ao principio porem não é nada de outro mundo. com cada tipo de variável você pode representar X valores dependendo do tipo de dado que você escolheu. O tipo de dados depende da sua necessidade, com um short int eu tenho menos valores possíveis, se preciso de mais dados necessito um int o inclusive algo maior como um long ou long long int, mas a maior é a variável, maior é a memória que ocupa, não tem cabimento você usar long int que permite números de -2.147.483.648 a 2.147.483.647 para guardar uma idade, com um short int bastaria, e com ele podemos guardar -32.768 a 32.767, e sinceramente não conheço ninguém com a idade de 32.767 anos, você até poderia usar um char para guardar a idade, com ele você poderia guardar de 0 a 255 valores. você conhece alguém com 255 anos? >_< Bastaria tratar esse char como se fosse int fazendo seus devidos casts. Claro que para uma só idade é uma estúpido usar char, mas pense se você fosse guardar a idade de todas as pessoas do planeta.... se você usar char para isso você gasta 4 vezes menos memória que com int. imagina você trabalhar para google ou facebook e você desperdiçar memória assim, certamente você irá para o olho da rua hahaHAHAH. já cansei>_<. Faça leituras no google sobre "tipos de dados em C", "tabela ascii", "conversões de tipo em C(casts)", "especificadores de formato printf/scanf" entre outros assuntos, veja videos também em YouTube, se uma imagem vale mais que mil palavras, um vídeo vale mais que mil imagens >_<. Fui!
-
Legal... Algo mais?
-
Linguagem C - problema com leitura de arquivo txt
pergunta respondeu ao LRicardor de vangodp em Grupo de Estudos
não tenho muito tempo para repassar códigos "titânicos" de mil linhas. Olhando assim por em cima seu código é um pouco caótico. O primeiro aviso é por que ele está tratando de usar um vetor como se fosse uma matriz, ou seja que ele está pondo & adiante da string, isso tá errado, tipo scanf("%s", &string) quando deveria ser scanf("%s", string) sem a &. O segundo aviso é por causa que a variável é do tipo unsigned long int porem ele usa o especificador %u quando deveria ser %lu. Exemplo unsigned long int n; scanf("%lu", &n); Porem são muitos os erros. O maior de todos é usar getch e conio >_< -
Acho que deveria ler isso, possui exemplos e está bem explicado. Tente criar uma e conte como foi.
-
modularização Exercícios de Modularização
pergunta respondeu ao Rodolfo Lima de vangodp em Grupo de Estudos
A tá! >_< -
Sim! Veja um caso curioso... Se pegar e enviar essa estrutura a um arquivo, você estará enviando 3 direções de memória na qual estaria armazenadas horas, minutos e segundos, porem se tentar ler esses dados do arquivo, na realidade você estaria obtendo a direção onde estavam os dados anteriormente, porem o programa poderia(e certamente terá) esses dados em outra parte, se tentar manipular essas direções você pode causar um desastre no seu sistema, pois nessa direção já não estariam as variáveis que você quer, e sim pode haver algum dado critico, dai você vai tentar manipula-lo e pode dar um erro de segmento ou algo pior, certamente o windows mostraria um aviso(ou pode que não). >_< Por esse motivo você precisa certificar de nunca enviar estruturas que contenham ponteiros a arquivos, si não de enviar cada dado por separado, dai você envia o conteúdo da variável apontada pelo ponteiro, e não o valor que armazena o ponteiro já que é um int que representa a direção de memória que de nada vai te servir. então em vez de enviar struct ao arquivo você envia struct->pHora, struct->pMinuto e struct->pSegundos, e para ler faça o processo contrario. Ok?! XD chau!
-
1-Um ponteiro é a mesma coisa em qualquer caso. Para não se complicar muito, melhor recorde que um ponteiro é uma variável que guarda a direção de memória de outra variável do mesmo tipo, não guarda dados, funciona igualmente em todos os casos, ele não guarda valores se não direções, lembre disso. 2-acho que a resposta anterior já responde isso... um ponteiro é uma variável que guarda a direção de memória de outra variável do mesmo tipo, por isso devemos fazer coisas como hoje.pHora = &hora. O operador & "entrega" a hoje.pHora a direção de hora, em outras palavra, se eu ponho & adiante de uma variável eu quero a direção da memória, mas se eu por *eu quero o valor que tem a variável "indiretamente" através do ponteiro. E como um ponteiro guarda direções é ilógico fazer coisas como hoje.pMinuto = *minuto, o certo é hoje.pMinuto = &minuto. Espero ter ajudado, se tiver duvidas pergunte.
-
todos os comandos que começam com # é trabalho para o pré-processador. Que quer dizer isso? Que quando fizer um define como o que você mencionou( #define PI 3.14159265 ) e chegar por exemplo a algo como float valor = PI;, o que acontece é que em tempo de compilação o pré-processador troca tudo o que for "PI" por 3.14159265, então na realidade esse 3.14159265 não passa de uma "literal", tem o mesmo valor float valor = PI que float valor = 3.14159265, não é atribuído memória alguma para esse define. Sobre o de "definição de struct" não entendo bem ao que você se refere. Talvez você quer dizer "definição de um novo tipo"? Algo como os typedefs? Se for isso são temas completamente diferentes. A linguagem C permite a criação de novos tipos de dados a partir de tipos primitivos, se agrupamos vários dados em uma struct podemos usar um typedef para criar uma nova definição de tipo especificada pelo programador. Não sei se é bem isso o que você se refere, vamos com exemplos. struct dados{ int n; }; Definição de estrutura anterior, não ocupa memória, somente "modelamos" a aparência dos dados. Ou melhor explicado... com a definição de uma estruct queremos dizer ao programa o tamanho que vai ocupar um objeto do tipo "dados" na memória. Quando criamos um objeto dados, ou seja, quando fizer struct dados d;, é neste momento que criamos um conjunto de variáveis em memória que vai ocupar um tamanho de " struct dados". O fato de definir estruturas não consumirá espaço, e sim o fato de criar copias desses dados na memória quando criamos um objeto do tipo dados. typedef struct { int n; }dados; Neste caso sim consume memória, pois trata-se de 2 comandos e não de um. Tem claro que a ultima forma de declarar uma estrutura é equivalente a: //definimos a forma de Dados struct Dados{ int n; }; //definição de um novo tipo typedef struct Dados data; //momento em que criamos um conjunto de dados na memória, agora já ocupa espaço em memória. data dados; //troca todas as entradas do arquivo onde estiver escrito dados por data. É óbvio que deveria ser feito um typedef anteriormente. #define dados data; Espero ter deixado claro.
-
Se a estrutura tiver tipos de dados que não sejam ponteiros sim! Caso a estrutura tenha ponteiros como membro então somente o ponteiro estará dentro, o dado apontado estará em outra parte obviamente. Pense em uma estrutura como se fosse um array de dados de diferente tipos. Um array tem os dados idênticos, por isso podemos usar índices, por que ao incrementar o ponteiro o mesmo vai ir "pulando" X bytes que sempre serão iguais, porem na estrutura os dados podem ter muitos tipos diferentes, então ao não saber o tamanho dos dados não podemos pular de um dado a outro com aritmética de ponteiros por exemplo. Porem falando, a estrutura de uma struct e de um array são parecidas, se poderia definir como um conjunto de dados que são apontados por um ponteiro ao seu primeiro elemento, mas um array é um conjunto de dados do mesmo tipo, e a struct não, mas ambos são apontados por um ponteiro ao seu primeiro elemento, e todos os dados são consecutivos, menos os que são apontados, esses estarão em outra parte, cuidado ao enviar estruturas a arquivos que contenham ponteiros porque certamente o dado apontado não irá a parar ao arquivo.
-
#include <iostream> #include <sstream> using namespace std; int main () { stringstream ss ( "ID: 1 - Nome: aa - Cnpj: aa - Endereco: aa " ); string s; while ( getline ( ss, s, ' ' ) ) { //ler palavra por palavra if( s == "Nome:" ){ //...até chegar no nome... getline ( ss, s, ' ' ); // ...e ler o que está depois do "Nome:" cout << s ; // "aa" TADAH! PREMIO! break; // BYE! } } cin.ignore(); return 0; } #include <iostream> #include <sstream> using namespace std; int main () { stringstream ss ( "ID: 1 - Nome: aa - Cnpj: aa - Endereco: aa " ); string s; while ( getline ( ss, s, ' ' ) ) { //ler palavra por palavra if( s == "Nome:" ){ //...até chegar no nome... getline ( ss, s, ' ' ); // ...e ler o que está depois do "Nome:" cout << s ; // "aa" TADAH! PREMIO! break; // BYE! } } cin.ignore(); return ; }
-
Mas qual é o problema que você tem especificamente? Mostre seu código
- 1 resposta
-
#include <stdio.h> #include <locale.h> #include <string.h> #define TAM 40 int main () { setlocale(LC_ALL,""); int i, j; char palavra[TAM],palavra2[TAM]; printf("Palavra: "); gets(palavra); for(i=strlen(palavra)-1, j=; i>=; i--, j++){ palavra2[j]=palavra[i]; } printf("Palavra ao contrario: %s\n", palavra2); return ; }
- 1 resposta
-
- palíndromo
- vetor de caractere
- (e %d mais)
-
função que receba 3 listas duplamente encadeadas
pergunta respondeu ao rodrigo.ferreira de vangodp em C, C++
Certamente todos nós podemos dar essa força. Qual é a duvida? -
Beleza! XD Aqui encontrei um vídeo muito interessante que vai tirar suas duvidas sobre a memoria que é criada para o processo do seu programa: O vídeo está em inglês, porem você aperte na engrenagem e escolha traduzir ao português que e vai lendo as explicações do rapaz que são muito boas. Nesse vídeo você pode ter uma idéia do por quê dos falhos de segmentação, toda a memória é alojada umas junto a outras, se saltamos os segmentos... BOOM! >_< Existe também outro tema de paginação que é interessante ver, se encontro algo deixo aqui, mas não se preocupe que esse não vai lhe afetar, somente ampliaria seus conhecimentos sobre a estrutura da memoria. Sorte!
-
a memória RAM é volátil, se apagar o computador tudo o que está na RAM se apaga por falta de corrente elétrica, é como se pegasse um formatado instantâneo, todos os bits se colocam a zero, isso faz com que o pedaço(assim como toda a memória) que estava ocupado fique disponível novamente. O ruim da memory leak é que se você tiver um programa que cause muita fuga de memória, você pode acabar por saturar a RAM, dai você vai precisar fazer um reinicio do sistema para que toda a RAM esteja disponível novamente tal como comentei. A ver... vou tentar explicar um pouco melhor, faz tempo que não toco no tema e já estou um pouco enferrujado, certamente algumas coisas nem lembro mais. Quando executamos nosso programa é criado um processo no nosso computador. Uma porção de memória é reservada para o tal processo. Nessa porção de memória é criado 3 zonas (resumindo algo o tema). As zonas são: -A zona de memória estática(por assim dizer), ela é a zona que se encarrega de manter as variáveis globais e static. -A zona da pilha, onde se armazena as variáveis locais, e o heap que já conhecemos. Na parte da pilha suponho... existe uma zona chamada stack frame, onde se reserva espaço para as variáveis da função main tais como parâmetros, variáveis locais, etc, mas não é reservado as variáveis para outras funções, quando fazemos a chamada de outra função é adicionado um novo quadro, ou como já falei o tal frame, será apilhado um frame encima de outro, tendo o comportamento de uma pilha(ultimo a entrar, primeiro em sair). Tanto a pilha como o heap são expansíveis, ou seja que podem ser aumentadas, e também diminuir, porem claro que tem limitações. A pilha por exemplo já vimos que chega cerca de 2 megabytes mais ou menos(ao menos no meu sistema sim), claro que disso depende vários fatores como já falei antes(compilador, sistema operativo, etc), pode variar de pc a pc, por isso você poderá declarar mais que eu, talvez seu computador tenha muita mais RAM e o pc designe mais para sua pilha, realmente não faço a mínima idéia o por quê, o fato é de que tem um limite. -O heap por outro lado é possível reservar muita mais RAM, se não me engano você pode reservar toda a memória disponível do sistema se fizer falta, mas realmente não é o problema. A wikipedia diz o seguinte sobre o erro de segmentos: Falha de segmentação (segmentation fault, também referido por segfault) é um erro que ocorre em programa quando este tenta acessar (para leitura ou escrita) um endereço na memória RAM que está reservado para outro programa (ou o próprio sistema operativo) ou que não existe. Se fizer a pilha crescer muito está claro que você vai acabar invadindo outras zonas da memória, por isso deve ter um limite, e isso acontece quando saimos desse limite, no caso do heap o limite é toda a memória, porque a memória é finita. O importante é você saber onde estão esses limites para cuidar que seu programa não pule a cerca. Consulte a documentação do seu compilador para saber. Acho que já fica claro, porem vou deixar algo de leitura para que tire suas conclusões. Essa é bem clara e resumida: http://cpp.drgibbs.com.br/cursos/1-c-para-iniciantes/16-ponteiros/01-a-memoria Essa é muito mais técnica, nem eu entendi muitas coisas, porem a imagem explica bem a estrutura de um processo. http://www.revista-programar.info/artigos/programacao-insegura-transbordo-de-memoria/ Nessa imagem você pode apreciar que tem segmento de texto, esse será usado para estipular o tamanho das funções como você falou. Os segmentos de.BSS e .DATA ao parecer é o que eu falei sobre a zona donde se guarda as globais e estáticas, logo você tem o segmento do heap, um espaço livre, certamente é o espaço permitido para que tanto o segmento de heap como da pilha se expandam, e por ultimo o segmento da pilha do outro lado. Na imagem podemos apreciar também 2 flechas que apontam para o espaço de segmento em branco(sem nome), isso quer dizer que se crescerem muito, no final acho que devem chocar. Não acha? O melhor é buscar por internet algumas ou varias matérias para aprender sobre o tema, uma sempre complementa a outra. Até logo e muita sorte.
-
1 Essa variável dinâmica é visível em todos os escopos, ou seja, em um programa você pode ter varias funções, quando você invocar uma função é nesse momento que é reservado a memória para as variáveis que estão declaradas nessa função, incluindo os ponteiros, quando a função chegar no return, ou sair sem mais, todas as variáveis serão liberadas automaticamente, porem as variáveis que você reservar dinamicamente vão a continuar até que você use free ou apague o pc. Por que isso é assim? Vamos pensar da seguinte forma... se eu falei que você precisa de um ponteiro no stack para manipular a uma variável que está no heap, imagine que você cria uma função e a invoca, dentro dessa função você supostamente criaria um ponteiro e alocaria a memória dinamicamente, dai sua função terminou e você não liberou com free, o que vai acontecer é que seu ponteiro será destruído, deixando a memória dinâmica "abandonada", resultado é que você perdeu o ponteiro que apontava para o heap, agora você não saberá onde está a variável, a menos que antes de sair da funão você tenha passado por return ou outro sistema a direção dela, lá no heap tem muitas outras variáveis, porem nenhum programa vai poder usar esse pedaço de memória, porque o seu computador vai ter marcado essa zona como ocupada, justo quando você apagar o pc, por ausência de luz, ele vai "esquecer" que isso tava reservada, todos os bits se colocam a zero(ausência de de corrente elétrica=0). Mesmo seu programa finalizado essa variável vai continuar aí, só que você perdeu o controle sobre ela a causa de ter destruído o ponteiro que a apontava ao finalizar seu programa. 2 Sim exatamente! Eu fiz um pequeno programa para demonstrar o que acontece. No meu computador dentro de main eu declarei um vetor de exatamente 521132 posições, esse foi o maior vetor que consegui declarar sem que meu programa soltasse os fogos artificiais >_<, se tentar declarar um numero maior salta o aviso(int n[521133];). Dai criei outra função e tentei declarar a mesma quantidade de inteiros, para minha surpresa... porque eu também nunca usei tanta memória, é que não foi possível. Na verdade o programa me permitiu declarar algo bem mais modesto, ele somente me permitiu declarar um vetor de int n[997] posições na função foo sem explodir XD. Isso me leva a crer, com "demonstrada evidencia" que a pilha é de aproximadamente 2 megas pois 521132 de inteiros equivale a 2,084528 megabytes, isso inclui todas as funções. int foo(){ int n[996]; // com 997 explodi >_< return ; } int main(void) { int n[521132]; // com 521133 faz boom! foo(); return ; } Faça provas depois e comente. Claro que isso pode variar de um sistema a outro e de um compilador a outro... eu por exemplo to usando um sistema operativo windows 7 de 32 bits com o compilador gcc 5 e codeblocks, realmente o programa deixou de trabalhar cerca dos 2 megabytes que falei antes. Agora respondendo a sua pergunta... O tal erro de segmentação é o seguinte... um segmento é um pedaço de memória de um X tamanho(ponho X porque não sei exatamente o tamanho que tem um segmento), no qual vai alojado seu programa. Se seu programa excede o tamanho do segmento, então serão designados 2 segmentos a seu programa, pode que sobre espaço do segundo segmento, e assim por diante, a coisa consiste em que ele fique alojado em um ou mais seguimentos até ele "caber". Na verdade nem lembro muito bem de todos esses conceitos, mas é mais ou menos isso mesmo. O erro de segmentação é quando você está tentando acessar fora do seu segmento, certamente você está tentando acessar memória pertencente a outro programa que está em outro segmento, por isso dá esse erro. Como falei antes, na pilha você não pode acessar a memória de outra aplicação, porque windows está vigiando isso. Se não seria muito fácil hackear outras aplicações não acha? Se você tiver dentro da sua função uns 3 vetores de 100 posições certamente você poderá ler os 3. vamos fazer uma prova? #include <stdio.h> #include <stdlib.h> int main (){ char a[10] = "Alo\0"; char b[10] = "mundo"; int i; for (i = ; i<20; i++) { printf("%c", b[i]); } getchar(); return ; } esse programa você pode imprimir os 2 vetores com um só loop e não da erro de segmentação, somente sai ao contrario as palavras pela disposição da pilha, o a será o prato de abaixo, e b o de acima, se imprimo a primeiro não sairá b porque esta em cima, porem se imprimo b sairão as 2. Por quê? Fácil.. você não está saindo do seu segmento, você esta dentro dele, e C permite você acessar qualquer parte da sua função. Quando o programa diz que tem problemas com outro segmento é justo quando nós fazemos isso: #include <stdio.h> #include <stdlib.h> int main (){ char a[10] = "Alo\0"; char b[10] = "mundo"; int i; for (i = ; /*i<20*/; i++) { //<-note o comentario!!! Não tem condição, é um loop infinito!BUG!! >_< printf("%c", b[i]); } getchar(); return ; } Certamente o programa imprime um montão de lixo(letras estranhas) porque a memória contem resíduos de outros programas, mas certamente serão esses 2 megabytes o que serão imprimidos, até que o sistema operativo se de conta que você esta tentando saltar o segmento, que é quando monstra o bendito mensagem do erro de segmentação. Costuma acontecer muito quando usamos funções recursivas que de não ter um limite de chamadas pode dar esse tipo de erros. Agora fique tranqüila que a pilha terá 2 megabytes mais ou menos para cada programa que executar, certamente esses 2 megabytes serão repartido entre todas as funções como vimos antes, e que se o programa não for alterado o tal parâmetro que aumenta a pilha parâmetro já que sei que pode ser aumentada a pilha. Eu acho que é mais que suficiente 2 megabytes para a pilha para a maioria das suas aplicações, porem sabendo que pode ser ampliado não temos motivos para alarmarmos, somente você deve saber que memória excessivamente grande deve ser reservada no heap para não saturar seu programa. Também acho que deve ficar tranqüila porque quando você fazer chamadas a funções, você deve saber que MAIS memória será reservada, porem ao terminar essa função será liberada, não abuse de muitas chamadas a funções pesadas e nada acontecerá, tudo é questão de um bom desenho do soft. Alguns conselhos são o reaproveitamento de variáveis, tipo em vez de declarar 3 variáveis, tente reutilizar uma só delas. A não ser que tenha que ter 2 ocupadas ao mesmo tempo. Não faça funções muito saturadas... separe por temas, tipo lerDados, porem não a utilize para alterar, para isso faça outra tipo alterarDados(). Isso fará que em cada função seja declarado somente o conjunto justo de variáveis que sejam necessárias para realizar a tarefa, você a invoca e se reserva, se cumpre com o requerido e se libera. Se você fizer tudo isso dentro de main essas variáveis não estariam sendo utilizadas o tempo todo, porem sim ocupando espaço, por isso dividir entre "subfunções" traz muito beneficio em rendimento. Use memória dinâmica sempre que for usar vetores muito grandes, e/ou que você quiser que tenha uma longa vida, você só precisará ir passando a direção dela de uma função a outra, e sempre terá ela num lugar que não conta como sobrecarga para a pilha, não se esqueça de libera-la, ela pode ser utilizada em qualquer escopo se esse receber o ponteiro nos parâmetros da função. Certamente tem muitos mais truques para melhorar o rendimento dos seus programas, conforme você for aumentando sua experiência você irá adquirindo esses conhecimentos, não deixe de visitar fóruns e ler problemas e soluções de outros programadores, você aprenderá muito, um fórum não é só para consulta, mas também para referencia. Conhecer como funciona e como é a estrutura da memória certamente fará com que sejas uma melhor programadora, muitos cursos não abarcam isso. ok? =D Fui!
-
Entrar em um fórum de programação e perguntar se te podem ajudar a fazer programas é como entrar na padaria e perguntar se tem pão. XD Não obstante pode acontecer que o pão da padaria não seja do seu agrado.>_< Exponha seu problema e veremos que podemos fazer. sorte
-
C funciona da seguinte forma... quando você tem um string dessa forma: char frase[100] frase é um conjunto de 100 espaços reservados na RAM do seu computador, nunca use 100 em caso de strings, use sempre um menos por causa do null que deve marcar o fin da string, si não invadimos memória que não nos pertence. Então literamente se eu declaro 100 posso só usar 99 letras. Continuando... Quando chegar no scanf scanf("%s",frase); o programa se coloca em modo de espera e habilita a entrada de dados por teclado(entrada padrão). Quando eu escrevo algo como "Alo mundo" isso tudo se vai acumulando no buffer de entrada padrão, e justo quando pulso enter é quando tudo o que está no buffer vai parar na string frase, pois ao pulsar enter o buffer de entrada será esvaziado nas seguintes variáveis que vão aparecendo, nesse caso frase. Um detalhe é que o compilador bota u NULL no fim do "Alo mundo\0", o NULL é o \0. Para que serve o NULL? já pensou como sabe printf onde tem que parar de imprimir se eu reservei 100 letras e só usei "Alo mundo"? O printf só imprime até o \0, si não se imprimiria algo como "Alo mundo... ..." XD. Bem... quando você quer imprimir letra por letra do seu string, você deve usar o especificador %c e não %s, pois %s já tem um loop interno que faz o trabalho por vc, então acho que seu programa na verdade o que você quer é isso: #include <stdio.h> int main() { int i; char nome[100]; scanf("%s", nome); /*eu sei que não é a melhor função para 'pegar' strings, mas basta para o quê eu quero.*/ for(i=; nome[i]!='\0'; i++) printf("%c", nome[i]); } o segredo está em que nome será impresso letra a letra até encontrar o NULL que marca o fim da string que é justo esse comando aqui: nome!='\0' que quer dizer por enquanto nome seja diferente que '\0' (NULL).... a variável i incrementará. não sei se ficou claro. ;)
-
quando você cria uma função ela vai parar no stack, cada função pode conter até 2 megabytes mais ou menos dependendo do compilador utilizado, para serem criado variaveis, se eu crio uma função tipo assim: int foo(){ int a; int b; int *c; } a pilha toma a aparência de uma pilha de pratos dentro do stack(uma zona especial da memória): A variavel é a primeira que aparece na sua função então o programa pega essa int a que é o primeiro prato e bota ele "em cima da mesa", logo pega a int b e bota em cima do int a, e o mesmo acontece com int *c, "pilha" fica algo assim: int *c; ultimo variável declarada na sua função(ultimo prato), é o de em cima da pilha, será o primeiro a ser liberado quando a função deixar de existir int b; segundo prato que apareceu int a; prato de abaixo, foi o primeiro que apareceu na sua função. Essas variáveis ficarão no stack durante toda a vida da função, quando fechar o programa essa parte da memória será limpada automaticamente começando por liberar a ultima variável que foi jogada na pilha, ou seja int *c. Logo depois libera b e depois a. Lógico... pense que em uma pilha de pratos você não pode tirar o prato de abaixo, o normal é você tirar o prato de acima. O que tem que ver tudo isso? Como falei... a vida dessas variáveis que estão na pilha(stack) tem sua "vida util" durante a existência da função, depois disso ela deixa de existir porque como falei, o programa libera ela. O problema é que no heap(também conhecido como free storage) isso não acontece, se você reservar memória no heap, você terá que liberar esse espaço com free(), si não esse espaço vai ficar aí para sempre até que você apague o computador causando o borrado de dados por ausência de corrente elétrica, isso se conhece como fuga de memória, é uma espécie de bug. você tem controle absoluto sobre a pilha, mas o stack é um "espaço de memória compartilhado" entre todos os programas que estão rodando no seu pc. já pensou o que passaria se 2 programas tivessem uma variável chamada de nomes iguais? Um rolo né >_<. Por isso você deve apontar desde sua pilha a direção reservada no heap, porque na pilha nenhum outro programa tem acesso, porem no heap é memória compartilhada entre vários programas, dai o sistema de dar nomes a variáveis vai por agua abaixo. Porem como falei antes você não pode abusar da pilha já que ela é limitada, você dispõe mais o menos de 2 mega bytes, esse tamanho não é fixo, e pode ser aumentado ou variar de um compilador a outro, mas não aconselho tocar nisso, isso faria seu código menos portável.