Vectores de tamanho a definir... - C - Portugal-a-Programar
Vectores de tamanho a definir...
By Elyst, January 18, 2011 in C
Tenho andado a estudar C faz uns mesitos... aprendi estruturas de controlo, vectores, funções etc...
Uma coisa que os programadores fazem, no inicio, para inicializar uma variavel com um valor atribuído pelo utilizador é declarar a variavel sem inicialização (int x;) e depois pedir ao utilizador pelo scanf o valor que a variavel x vai ter.
MAS... com vectores já não podemos fazer o mesmo... para declarar um vector com um tamanho definido pelo utilizador seria preciso declarar o vector com um tamanho especifico e depois usar o realloc para alterar o tamanho do vector.
... ou será que não...
não podemos inicializar um vector como int n[]; porque o computador não sabe o tamanho ao inicializar o dito vector e não sabe quanto espaço de memória irá precisar.
Aí é que me ocorreu esta ideia, se pedir-mos um valor inteiro ao utilizador, poderiamos mais a frente no programa declarar um vector com o tamanho dito inicialmente pelo utilizador. Poderiamos até criar limites para o utilizador não criasse vectores grandes ou pequenos demais.
heis um pequeno programa que pede ao utilizador o tamanho do código, declara um vector com esse tamanho e depois escreve o mesmo vector.
//este programa é um metodo que descobri para permitir o utilizador declarar um vector do tamanho que desejar sem o uso do realloc
//Note: poderia juntar um if para limitar o tamanho do vector que o utilizador poderia criar.
//another note: não criei o dito if porque seria também preciso um ciclo que, ao encontrar o número errado voltaria a pedir o valor de i. Ao encontrar um valor válido continuaria a leitura... mas estava com problemas em defenir o ciclo
printf("define array size: ");
scanf("%d",&i);			//simples inicialização de um inteiro inocente
int v[i];				//heres the trick - o vector é inicializado com o valor que o user define
for(c=0;c<i;c++) {			//uma formas simples para o user escrever os valores no array
printf("define %c value of string:",(c+1));
scanf("%d",&v[c]); }
printf("program saved the array, now writing it... \n");		//hehehe, não pude resistir a formalizar uma separação entre escrita e leitura do array
for(c=0;c<i;c++) {			//a escrever o vector...
printf("%d\n",v[c]);
printf("program finished %d %d\n",v[2],i);	//TADA!!! estes numeros no final não são importantes mas ficaram...eram para outra coisa que queira fazer inicialmente
Tive uns problemas ao colocar limitações no valor que define o vector... noutra versão (que não funciona) criei uma nova variavel inteira inicializada com 0, depois havia um ciclo que envolvia o 1o printf e scanf, seguido de um if que se fosse maior esta ultima variavel então repetia o ciclo e pedia novos valores para i; se os valores estivessem dentro dos limites então esta ultima variavel era incrementada e o ciclo deveria seguir...
mas isso pode ter sido por azelhice minha de ter os if's ao contrario ou o while mal escrito. Mas fica a ideia...
Eu não sei quanto aos restantes programadores mas esta ideia fascinou-me... usar os realloc's, malloc's e calloc's é mt chato
Isso é tudo muito bonito mas é perigoso e em alguns compiladores, se não estou enganado, dá erro na compilação. Não é standard e não se deve usar.
Isso que tu criaste chama-se de variable-length array (VLA), arrays cujo tamanho é determinado em tempo de execução e que são alocados na stack.
Isso é tudo muito bonito mas é perigoso
Certo, é preciso ter cuidado pelo facto de serem alocados na stack.
Não é standard
É standard. Foi introduzido no C99.
e não se deve usar.
É como o goto. É preciso saber o que se está a fazer e porque se está a fazer.
Lembrem-se que podem sempre definir mais ou menos os limites que queremos que o utilizador defina o tamanho do vector.
Por exemplo, se não quiser que seja maior que 10 basta fazer um if na parte inicial... eu expliquei isso td no 1o post...
Mas fica a nota para futura referencia de que isto é potencialmente perigoso...
No entanto para mini programas como os que tenho andado a fazer e assumindo que os utilizadores são "de confiança"...não haverá problema.
...será que se usar isto num teste desconta como má prática? XDDD
Podes também inicializar a variável e mudar o seu valor com o que o utilizador pretender... custa assim tanto meter um "=0" à frente da variável?
Custa assim tanto usar o malloc? :| Eu compreendo que o código não fica tão... bonito, mas continuo a achar que é melhor usar os mallocs quando precisas.
O professor não pode ser considerado um utilizador de confiança...
Quanto a usar num teste... sinceramente acho que é uma questão do nível de conhecimento que tens e do professor em causa. Como foi referido atrás, esta é uma situação como o "goto". O meu professor de programação proibiu o uso do goto sem sequer explicar porquê... e claro, se alguém o usasse, levava um corte. Achas que tens capacidade para argumentar a utilização dos VLAs num teste? Estás disposto a correr esse risco?
Eu não estou a dizer que é uma má ou boa prática... apenas que o teu professor pode não te reconhecer conhecimento suficiente para fazeres uso de tal artefacto (que ele provavelmente não falou) e assumir que o uso dele foi um erro teu que por acaso funcionou. Podes sempre documentar com uns comentários no código para provares que sabes o que estás a fazer, mas ainda assim poderás ter de explicar em pessoa porque o usaste.
O ponto positivo disto é que, se realmente souberes o que fizeste, provavelmente levarás um bónus na nota do teste.
Mas claro, tudo isto é relativo porque depende do professor.
Eu cheguei a ter 19.3 num teste de informática porque não coloquei "C:\>" na resposta a indicar o directório local de onde iria fazer o comando para copiar o ficheiro X para o directório Y... E apesar do comando funcionar em qualquer directório porque tinha ambos os paths bem definidos e de ter mostrado ao professor num computador que o comando funcionava em qualquer directório, fiquei com o 19.3.
O mesmo pode-te acontecer... mas espero que não.
Concordo. é um risco a evitar... De qualquer forma vou mandar um mail ao professor só para saber a opinião dele e uso mallocs no teste e proximos programas.
engraçado que o meu professor também mal falou no goto... e como não explicou como usar ... ninguém o usa...
Mas parece-me uma função promissora...
para finalizar: é mais eficiente usar este método ou o malloc para deixar o utilizador definir o vector?
E vocês, experientes programadores, arriscariam a usar este método em vez do fiel malloc?
Existem mil e uma discussões em fóruns na net, inclusivé no P@P, para veres do que se está a falar.
Eu quase nunca uso gotos, e quando uso é normalmente com um salto para um único local dentro dum programa, posso ter vários pontos de partida, mas apenas um de chegada. Utilizado assim, o goto torna o código um pouco mais legível. No entanto, e o motivo pelo qual toda a gente prefere não dar a conhecer o goto é para evitar que hajam saltos por todo o programa tornando-o quase impossível de ler e depurar.
Eu sou tudo menos experiente pelo que não vou responder à pergunta do malloc. Agora a sério, os programas que faço em C para computadores não exigem muita memória. O último que fiz foi para sincronizar a hora entre o microcontrolador com o computador. Se precisar de algo mais, prefiro uma linguagem que permita um interface gráfico simples de construir. Pelo que não sou a pessoa para saber se o malloc é melhor que as VLAs.
goto não é uma função, é uma keyword (como o 'if', ou 'while').
Quanto ao VLA, eu acho que confiar no utilizador é sempre um erro, mas a minha pergunta é: precisas mesmo de alocar um array com até 2147483647 'slots'? Porque senão, podes ler declarar a v como outra variável (unsigned char, por exemplo) e ajustar o scanf de acordo. Assim nunca terias valores que te pudessem "rebentar" a stack.
A alternativa é como disseste usar um if para limitar o valor, saindo do programa caso seja demasiado elevado.
Uma terceira alternativa (não aconselhada em trabalhos/testes) seria configurares o compilador para aumentar a stack, de modo a ter espaço para guardar tudo. Meta-programação ftw
Um pouco já offtopic mas ...
Estou a realizar a um projecto dentro do kernel do linux, se analisares o código fonte do linux vais ver que eles utilizam bastante a keyword goto, principalmente quando querem fazer tratamento de erros.
Como foi dito anteriormente o goto pode ser considerado má pratica, quando se começa a assemelhar a "spaghetti code".
eu já sabia o que era o goto e porque não se deve usar. As a matter of fact a unica coisa que não sei é mesmo a sintaxe do goto... mas se não posso usar para já nem me interessa.
Se precisar de algo mais, prefiro uma linguagem que permita um interface gráfico simples de construir. Pelo que não sou a pessoa para saber se o malloc é melhor que as VLAs.
Se souberem de alguma linguagem assim avisem :thumbsup:
O que mais gosto em programação é poder fazer uns joguinhos e tal. A parte gráfica sempre me interessou. Mas até agora só uma olhada rápida para uns tutoriais de opengl que não parecia nada facil... servia para dar textura a uma img acho eu...
Fazes mal... tu podes usar... desde que o faças conscientemente. Daí que devas perceber porque é que as pessoas evitam de usar o goto e depois decidires mediante a situação. Como foi referido o kernel do linux tem imensos gotos e existe até uma discussão online onde o autor do código explica a escolha em fazê-lo.
Eu referia-me a text boxes, menus, etc, etc...
antes de mais, sim não me faria mal nenhum aprender isso, mas como para já não posso usar mesmo que conscientemente, vou deixar o assunto pendente para mais tarde.
e agora Correndo o risco de ir ainda mais off topic arrisco-me a dize-lo.
da parte da computação gráfica - andava eu muito feliz da vida a vasculhar o fórum numa secção algures aí perdida e descobri um post mesmo antigo a falar de DarkBasic. Não dizia nada de especial tirando a referencia à linguagem e um site com tutoriais lá para o meio.
Andei a escamutear o assunto e heis que descobri que DarkBasic é uma linguagem derivada do Visual Basic e é dedicada para desenhos e figuras 3D (vi até um código que desenha um quadrado e fa-lo rodar).
Será que alguém daqui já trabalhou com este DarkBasic que me possa dar uma opinião mais concreta da linguagem?
😳 Sem querer ser muito chato mas gostava de pedir ao pessoal se me podia arranjar uns tutoriais e programas para desenvolver isso... e também uns tutoriais simples para trabalhar com assembly...(não preciso de programa, já uso o mars mips)
para já de assembly estou a estudar em aulas mesmo e vou até fazer um teste sobre isso. De DarkBasic era mais por curiosidade própria...