Página 1 de 1
dúvidas usando arquivo.h struct e ponteiros, tudo junto

Enviado:
23 Jan 2009 10:38
por bfccardoso
estou tentando aprender o máximo possível de C pois vou começar a trabalhar com um ARM7 no mês que vem, só que cheguei em um ponto de um programinha que não consigo sair de jeito nenhum, quando eu uso o DEBUG, da o seguinte erro:
Uma violação de acesso (falta de segmentação) ocorreu em seu programa.
- a parte do programa que acontece o erro está em negrito.
- esta função encontra-se em um arquivo diferente do main (.h)
Se alguém puder me ajudar eu agradeço muito.
Obrigado
int cadastro(status *p, int pos)
{
if(pos>CODIGO_MAX)
printf("\nMemoria cheia!\n\n");
else
{
pos = 1;
while(p[pos-1].codigo!='\0')
pos++;
p[pos-1].codigo=(pos+5);
do{
printf("Entre com sua senha (0 a 15): ");
scanf("%d",*(p[pos-1].senha));
if(p[pos-1].senha<0 || p[pos-1].senha>15)
printf("\nSenha invalida\n");
}while(p[pos-1].senha<0 || p[pos-1].senha>15);
}
return pos;
}

Enviado:
23 Jan 2009 10:44
por bfccardoso
na verdade não existe esse * na linha onde ocorre o erro.
no programa a linha se encontra da seguinte forma:
scanf("%d",p[pos-1].senha);
Obrigado!

Enviado:
23 Jan 2009 11:04
por msamsoniuk
pis eh,s em saber o que eh a struct ali fica dificl... senha eh inteiro ou string ? se for inteiro, entao o correto eh:
- Código: Selecionar todos
scanf("%d",&p[pos-1].senha);
se for string, o correto eh:
- Código: Selecionar todos
scanf("%s",p[pos-1].senha);
isso pq no scanf vc nao diz o q vc quer ler, mas sim o tipo da variavel que vc vai escrever.
ah. e nunca se coloca funcoes em arquivos .h... sempre em arquivos .c. os .h sao para definicoes, typedefs e coisas do genero.

Enviado:
23 Jan 2009 12:35
por bfccardoso
de fato o arquivo foi salvo como "rotinas.c" mas no arquivo "main.c" eu o chamo como "rotinas.h". abaixo está o código inteiro dos dois arquivos.
main.c
#include <stdio.h>
#include <stdlib.h>
#include "rotinas.h"
#define CODIGO_MAX 4
typedef struct STATUS
{
unsigned int presente : 1;
unsigned int liberado : 1;
unsigned int senha:4;
unsigned int codigo : 2;
}status;
int opcoes (void);
int cadastro(status *p, int pos);
int main(int argc, char *argv[])
{
// struct STATUS teste[CODIGO_MAX];
status teste[CODIGO_MAX];
int cod,s,aux,pos=1;
for(aux=0;aux<CODIGO_MAX;aux++)
teste[aux].codigo = '\0';
for(;;)
{
switch(opcoes())
{
case 1:
{
pos=cadastro(&(teste),pos);
break;
}
case 2:
{
entrada();
break;
}
case 3:
{
saida();
break;
}
case 4:
{
exit(1);
break;
}
default:
{
printf("Opcão invalida!\n\n");
}
}
}
system("PAUSE");
return 0;
}
rotinas.c
#define CODIGO_MAX 4
typedef struct STATUS
{
unsigned int presente : 1;
unsigned int liberado : 1;
unsigned int senha:4;
unsigned int codigo : 2;
}status;
int cadastro(status *p, int pos);
int opcoes (void);
void entrada();
void saida();
int opcoes (void)
{
int aux;
printf("Digite uma das opcoes abaixo\n");
printf("1 - Cadastro\n");
printf("2 - Entrada\n");
printf("3 - Saida\n");
printf("4 - Sair\n");
printf("Opcao: ");
scanf("%d",&aux);
return aux;
}
int cadastro(status *p, int pos)
{
if(pos>CODIGO_MAX)
printf("\nMemoria cheia!\n\n");
else
{
pos = 1;
while(p[pos-1].codigo!='\0')
pos++;
p[pos-1].codigo=(pos+5);
do{
printf("Entre com sua senha (0 a 15): ");
scanf("%d",(p[pos-1].senha));
if(p[pos-1].senha<0 || p[pos-1].senha>15)
printf("\nSenha invalida\n");
}while(p[pos-1].senha<0 || p[pos-1].senha>15);
}
return pos;
}

Enviado:
23 Jan 2009 12:48
por joao
Vc já tentou a solução que o marcelo apresentou?
De colocar um & na linha que está dando erro?
Outra coisa, vc deve ter um arquivo chamado rotinas.h né?
Faça a declaração da struct e defines e também a declaração das funções neste arquivo. Dai vc pode apagar isso do seu rotinas.c e também faz apenas um include do .h no lugar do texto que vc deletou.
Por curiosidade, pq vc tá fazendo isso:
- Código: Selecionar todos
while(p[pos-1].codigo!='\0')
pos++;
p[pos-1].codigo=(pos+5);
Não consegui entender apenas olhando o código.
PS: Toda vez que colocar código aqui no forum, selecione ele e clique no botão "code"que existe em cima de onde vc está escrevendo. Dai o php não irá tirar a identação.
[]'s

Enviado:
23 Jan 2009 13:13
por bfccardoso
Vc já tentou a solução que o marcelo apresentou?
De colocar um & na linha que está dando erro?
sim, já tentei, mas aí o compilador da um erro dizendo que eu não posso ter um endereço de um campo de bit.
Outra coisa, vc deve ter um arquivo chamado rotinas.h né?
na verdade eu tenho um arquivo chamado rotinas.c mas eu o chamo no arquivo main.c desta forma: include "rotinas.h"
Faça a declaração da struct e defines e também a declaração das funções neste arquivo. Dai vc pode apagar isso do seu rotinas.c e também faz apenas um include do .h no lugar do texto que vc deletou.
minha intenção é aprender como fazer um programa simples no main.c e criar vários outros arquivos com as funções que necessito, será que se eu fizer o que você está dizendo vou estar fugindo disso?
Por curiosidade, pq vc tá fazendo isso:
Código:
while(p[pos-1].codigo!='\0')
pos++;
p[pos-1].codigo=(pos+5);
para poder achar a próxima posição vazia do vetor, e assim poder gravar um novo usuário na mesma. quando acho gravo qualquer coisa diferente de '\0', no caso (pos+5). (pura viagem pra dizer a verdade)
Não consegui entender apenas olhando o código.
PS: Toda vez que colocar código aqui no forum, selecione ele e clique no botão "code"que existe em cima de onde vc está escrevendo. Dai o php não irá tirar a identação.
valeu pela dica

Enviado:
23 Jan 2009 13:54
por bfccardoso
é...
se eu paro de trabalhar com bit's tudo funciona perfeitamente.
alguém sabe como eu faço para trabalhar com bit's e usar passagem por referência?
Obrigado!
_____________________________________________________________
O prego que mais se destaca é o primeiro a levar a martelada.

Enviado:
23 Jan 2009 14:20
por joao
Vc pode dar um exemplo de senha?
Porque vc reservou 4 BITS para a senha, mas está pegando um DECIMAL que é 4 BYTEs(32 BITS) no scanf.
Tá vendo porque ele está reclamando?
se vc realmente quer apenas os 4 BITS, eu acho que uma opção é usar um int no seu scanf e dai pegar apenas os 4 primeiros bits...
Bom, fiz um programinha aqui, tentando usar a idéia do seu programa. Tem algumas coisas que eu ainda acho que podem ser mudadas, mas é ao gosto do fregues então nem mexi!
main.c
- Código: Selecionar todos
#include "rotinas.h"
int main(int argc, char *argv[])
{
int cod,s,aux,error;
CADASTRO cadastro[CODIGO_MAX];
inicializa();
for(;;)
{
switch(opcoes())
{
case 1:
error = novo_cadastro(&cadastro);
if(error == 1)
printf("\nMemoria cheia!\n\n");
else
printf("\nCadastrado com sucesso!\n\n");
break;
case 2:
entrada();
break;
case 3:
saida();
break;
case 4:
exit(1);
break;
default:
printf("Opcão invalida!\n\n");
}
}
system("PAUSE");
return 0;
}
rotinas.c
- Código: Selecionar todos
#include "rotinas.h"
void inicializa()
{
//Tudo que precisa ser inicializado, coloca aqui
posi = 0;
}
int opcoes (void)
{
int aux;
printf("Digite uma das opcoes abaixo\n");
printf("1 - Cadastro\n");
printf("2 - Entrada\n");
printf("3 - Saida\n");
printf("4 - Sair\n");
printf("Opcao: ");
scanf("%d",&aux);
return aux;
}
int novo_cadastro(CADASTRO *p)
{
if( posi == CODIGO_MAX)
{
return 1; //Deu erro! Memoria Cheia!!!
}
else
{
do
{
int i;
printf("\nEntre com sua senha (0 a 15): ");
scanf("%b",&i);
p[posi].senha = i & 0x04; //Pegando apenas os 4 ultimos bits;
if(p[posi].senha < 0 || p[posi].senha > 15)
{
printf("\nSenha invalida\n");
}
else
{
posi++;
return 0; //Pegou a senha corretamente e retorna sem erros!
}
}while(1);
}
}
void entrada()
{
//PARA FAZER
}
void saida()
{
//PARA FAZER
}
rotinas.h
- Código: Selecionar todos
#include <stdio.h>
#include <stdlib.h>
#define CODIGO_MAX 4
typedef struct
{
unsigned int presente : 1;
unsigned int liberado : 1;
unsigned int senha : 4;
}CADASTRO;
int novo_cadastro(CADASTRO *p);
int opcoes (void);
void entrada();
void saida();
void inicializa();
int posi;
Testei no Dev-Cpp e tá rodando. Mas como eu disse, dá para ser mudado bastante este seu código. Como exemplo o if que vc verifica a senha não precisa pq vc só tem 4 bits, logo ele vai ser entre 0 e 15. Não tem como ser outro valor. Então daria para eliminar.
Também é comum deixar a variavel da estrutura no outro arquivo e não no main. Mas mantive lá para te mostrar passagem de parametros com ponteiros...
[]'s

Enviado:
23 Jan 2009 15:15
por bfccardoso
joao,
valeu cara, fico te devendo essa!
comecei a estudar C na segunda-feira desta semana, já tinha visto antes mas muito pouco, e como vou ter que trabalhar profissionalmente com ele agora fazendo softwares embarcados, peguei o livro C Completo e Total e não estudo menos 10 horas por dia.
Como as memórias dos microcontroladores não são grande coisa, tenho que trabalhar muito com bit's.
Obrigado mais uma vez!
Abraços.

Enviado:
23 Jan 2009 15:30
por joao
Ola bfccardoso,
É claro que é importante vc trabalhar com bits!
mas realmente eu acho que vc deveria primeiro trabalhar com o código em si, pois como vc viu, é bem simples usar os bits.
Te aconselho a pegar algum código de alguma coisa já implementada e trabalhar com ele, por exemplo, mudar cor, frases e etc, para entender o jeito do C.
Tente ver nestes exemplos como se usa vários arquivos, como se consegue compartilhar a variável e etc...
Depois veja algumas coisas mais chatas de aprender, como bits, structs, unions, static variables, void *(ponteiros do tipo void) e etc...
Mas parabéns pela dedicação!
Aproveita e vai perguntando o que precisa que o pessoal vai ajudando no que puder...
[]'s

Enviado:
23 Jan 2009 16:25
por msamsoniuk
bfccardoso escreveu:Vc já tentou a solução que o marcelo apresentou?
De colocar um & na linha que está dando erro?
sim, já tentei, mas aí o compilador da um erro dizendo que eu não posso ter um endereço de um campo de bit.
para vc ver neh, ninguem iria adivinhar que era um bitfield se vc nao colasse o codigo inteiro... mas dae nao dah mesmo, pq o scanf com parametro %d requer um ponteiro para inteiro!
receba numa variavel temporaria e depois copie para o campo:
- Código: Selecionar todos
int lalala;
scanf("%d",&lalala);
valor.bitfield_doido = lalala;

Enviado:
23 Jan 2009 16:35
por msamsoniuk
o bom eh estudar pelo K&R segunda edicao (padrao ANSI)...
todo mundo que eu vi aprender pelo "C completo e total" me parece escrever um codigo ruinzinho (nunca tive curiosidade de ver o livro, mas pelo jeito eh ruim). quem eu vi aprender pelo K&R geralmente escreve um codigo melhor. o K&R eh antigao, vc encontra em qq biblioteca... e ateh em pdf se vc procurar bem.
bfccardoso escreveu:joao,
valeu cara, fico te devendo essa!
comecei a estudar C na segunda-feira desta semana, já tinha visto antes mas muito pouco, e como vou ter que trabalhar profissionalmente com ele agora fazendo softwares embarcados, peguei o livro C Completo e Total e não estudo menos 10 horas por dia.
Como as memórias dos microcontroladores não são grande coisa, tenho que trabalhar muito com bit's.
Obrigado mais uma vez!
Abraços.

Enviado:
23 Jan 2009 22:32
por chrdcv
Valiosas contribuições também podem ser encontradas em:
http://www.ioccc.org/ o qual recomendo que diariamente abra um código fonte e faça algumas verificações!
christian