char dentro de estruct da falha de segmentação... [RESOLVIDO]

1. char dentro de estruct da falha de segmentação... [RESOLVIDO]

Alex Fernando Ferreira
staltux

(usa Slackware)

Enviado em 28/12/2007 - 03:55h

O problema aparece depois de compilado...
quando armazeno uma cor...até 3 letras vai normal...apartir disso da falha de segmentação.
oque seria isso?

#include <stdio.h>
struct casa{
char cor[20];
}
cadastro(struct casa *cad){
int x=0;
printf("Cor: %s\n",x);
scanf("%s", &cad[x].cor);
printf("\n");
}

int main(){
struct casa enter[0];
cadastro(enter);
printf("\n\n\nFim\n\n\n");
}


  


2. MELHOR RESPOSTA

Marcelo Utikawa da Fonseca
utikawa

(usa Ubuntu)

Enviado em 29/12/2007 - 01:23h

Na verdade você deu "sorte" de não dar erro antes... :-)
Como você mesmo disse, o problema acontece depois de compilado. Portanto não é erro de sintaxe! Assim o problema é com a lógica em si.
O erro de segmentação indica normalmente que houve acesso a uma região de memória que você não estava autorizado. Portanto o erro indica que seria problema com vetores sendo acessados após o seu limite.
Quanto ao erro que está acontecendo, o motivo é que existem três grandes problemas com o código! Vou comentar as linhas associadas e explicar o que está acontecendo no final:

#include <stdio.h>
struct casa{
char cor[20]; // Criada estrutura com apenas um elemento: vetor com 20 posições
}

// Função que recebe um ponteiro para elemento da estrutura criada, ou seja, endereço na memória onde está este elemento.
cadastro(struct casa *cad){
int x=0;
printf("Cor: %s\n",x); // Primeiro problema!
scanf("%s", &cad[x].cor); // Segundo problema!
printf("\n");
}

int main(){
struct casa enter[0]; // Terceiro problema!
cadastro(enter); // Passagem do ponteiro para função
printf("\n\n\nFim\n\n\n");
}

Primeiro vou falar do terceiro problema:

O que esta linha está fazendo? Como criamos um vetor?
Para declarar um vetor devemos colocar entre os colchetes o número de elementos que o vetor será capaz de armazenar. No seu caso você colocou zero! Ou seja: este é um vetor que não tem capacidade para armazenar nada! Eu mesmo não sabia que o compilador não dava erro por isso... :-)
O correto seria colocar um numero como, por exemplo, 5. Assim este vetor poderia armazenar 5 elementos da estrutura definida, sendo então estes elementos acessados pelos índices entre 0 e 4 pois em C/C++ os índices sempre começam em zero.
Portanto, apenas reforçando: ao criar o vetor devemos colocar o número de elementos e para acessá-lo devemos utilizar os índices entre zero e número de elementos - 1.

O primeiro problema é devido a tipos incompatíveis de variáveis. Nesta linha você está executando o printf que deveria receber como argumentos a string com o formato e as variáveis que serão exibidas. Neste caso o formato indica que será exibida uma string porém a variável é do tipo inteiro. A linha correta é:

printf("Cor: %d\n", x);

Outra coisa é que esta variável x será sempre o mesmo valor pois ela é criada, inicializada com zero e já é exibida. Pelo código o correto seria:

static int x=0;

Antes de sair da função deveria ser incrementado o valor de x.

O segundo problema é com o parâmetro sendo passado para o scanf.
Apenas para esclarecer: a função scanf recebe ao menos 2 argumentos: a string de formato e o endereço onde o dado digitado pelo usuário será salvo. Assim o segundo argumento deveria ser o endereço da variável cor da estrutura. Agora vamos analisar o que está sendo passado:

&cad[x].cor

& indica que é para ser retornado o endereço da variável a seguir.
cad[x] indica que está sendo acessado o elemento x do vetor cad
.cor indica a variável cor da estrutura. Porém esta variável é na realidade um vetor.

Resumindo: a linha está gerando o endereço do vetor cor no elemento x de cad. Porém, no caso de um vetor, se você passá-lo como parâmetro sem colocar um índice já será retornado o endereço do vetor. Assim o símbolo & indica algo como endereço do endereço do vetor. A linha correta seria:

scanf("%s", cad[x].cor);

Pronto! Só isso... :-)
Agora mais alguns comentários: este cad[x] acessa 20 elementos se você permitir. Deve ser criada alguma lógica que não permita acessar um elemento maior que o definido.
Outra coisa: tem muitos erros neste código, sinceramente me pareceu um exercício como um trabalho de escola. Caso for, está resolvido!
Não avaliei totalmente, podem existir mais coisas. Caso realmente seja um exercício, por favor tente aprender a linguagem. Ela é fantástica e permite que se faça virtualmente tudo que você possa imaginar!!! E se você não aprender nem mesmo a base mais nada será aprendido.
Este é um "segredo" para tudo na vida: quer aprender a fazer bem feito qualquer coisa? Treine bastante e nunca tente aprender mais rápido que o possível! É como construir um prédio: se você não souber construir as colunas e a fundação, nem adianta querer aprender a construir as paredes. Elas nunca ficarão certas, por mais que você tente...

3. Re: char dentro de estruct da falha de segmentação... [RESOLVIDO]

Alex Fernando Ferreira
staltux

(usa Slackware)

Enviado em 29/12/2007 - 15:47h

nao é exercicio de escola nao...eu estou de ferias do curso de programação...mas essa parte eu ainda nao vi...to tentando aprende sozinho mesmo...o erro do %s foi falta de atenção mesmo...
na linha do
cadastro(struct casa *cad){
nao pode omitir essa linha e no scanf usar o casa[x].cor
tambem na struct casa enter[0] omitir e passar
cadastro(casa)
ou usar struct casa *enter
ficar fazendo struct duas vezes(struct casa{} e depois struct casa enter[5]ou struct casa *enter) acaba me confundindo...

mas eu nao sabia que podia usar o scanf sem o "&"...


4. Re: char dentro de estruct da falha de segmentação... [RESOLVIDO]

Marcelo Utikawa da Fonseca
utikawa

(usa Ubuntu)

Enviado em 29/12/2007 - 17:34h

Legal que não é exercício! Eu falei isso pois muita gente reclama que C é ruim mas não tem vontade de aprender e não faz o mínimo esforço para isso... Que bom que você está tentando! :-)

Eu não entendi exatamente o que você quis dizer mas vou explicar melhor as partes que você comentou.

Primeiro: a função scanf recebe como parâmetro a string de formato e depois o endereço de memória onde o valor digitado será salvo. Normalmente o valor deve ser salvo em uma variável então utilizamos o & para passar o endereço desta variável. Este & serve justamente para isso: receber o endereço de memória de uma variável.
Porém existem casos em que a própria variável já contém o endereço de memória e portanto o & não deve ser usado: no caso de vetores onde não é colocado o índice e para ponteiros.
Ponteiros são uma variável como outra qualquer. A única diferença é que, ao invés de armazenar um número (como no caso de um int ou float) ou um caracter (como no caso do char), esta variável armazena um endereço de memória. Assim, se ele armazena um endereço de memória, não precisamos do & ao passar um ponteiro para o scanf pois senão cairá no caso do "endereço do endereço"...

Quanto a omitir algumas partes, pelo que eu entendi você está dizendo que colocar o struct casa em todo lugar confunde, é isso? Se for, não tem jeito! Pois primeiro você tem que criar a estrutura, depois é o parâmetro da função e portanto você tem que falar o que a função recebe. Depois, na função main, você tem que criar a variável e para isso tem que dizer qual o seu tipo, ou seja, o que ela irá armazenar.
Se você usar apenas casa[x].cor vai dar erro. O que poderia ser feito é o seguinte: ao criar uma estrutura colocamos o ; no final, correto? Pois antes de colocar este ; você pode criar uma variável desta estrutura. Depois essa variável poderia ser utilizada em todo lugar. Porém esta seria uma variável global e isto não deve ser generalizado pois gera muitos problemas quanto a quantidade de memória utilizada, dificuldade para programação e manutenção de programas, etc. Mas é uma alternativa e no seu caso, por ser um programa pequeno, poderia ser utilizado! Mais uma coisa: se você não quiser criar novas variáveis desta estrutura, nem nome precisa dar a ela. Assim a declaração da estrutura seria:

struct {
char cor[20];
} casa[10];

A sua função ficaria:

void cadastro() {

E na função main não teria que criar nenhuma variável.
Outra coisa: criar apenas um ponteiro para a sua struct como no comando que você passou:

struct casa *enter;

não servirá para você. Pois, como o próprio nome diz, você criou apenas um ponteiro, ou seja, uma variável que aponta para uma outra variável que já deverá existir. Se você apenas criar o ponteiro como na linha acima e passá-lo para a função irá gerar o erro de falha de segmentação.

Qualquer outra dúvida é só falar!


5. Re: char dentro de estruct da falha de segmentação... [RESOLVIDO]

Alex Fernando Ferreira
staltux

(usa Slackware)

Enviado em 03/07/2009 - 21:57h

obrigado pela resposta...eu ja avia lido ela, mas nao tinha comentado...
ainda acho C++ e principalmente Java bem mais facil...mas fazer oque né?
cada um se identifica com uma linguagem...

na primeira lida eu não entendi bem o que vc quis dizer...mas agora com um pouco mais de pratica entendi os erros que tinha cometido no struct
vlw mesmo...



  



Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts