• Revista PROGRAMAR: Já está disponível a edição #53 da revista programar. Faz já o download aqui!

pedrosorio

Problema... com estruturas?

21 mensagens neste tópico

Olá a todos, estou a tentar resolver este problema usando como input o sample input que aparece no enunciado. Mas fico sempre com o ficheiro gift1.out com 0 bytes, alguém me pode ajudar?

Este é o código:

#include <stdio.h>
struct person {char name[14]; int money;};
main () {
    FILE *fin  = fopen ("gift1.in", "r");
    FILE *fout = fopen ("gift1.out", "w");
    int np, it, it2, flag, curnum, curmoney, peeps;
    char curname[14];
    flag=1;
    fscanf (fin, "%d" , &np);
    struct person people[np];
    for(it=0;it<np;it+=1); {
        fgets(people[it].name, 14, fin);
    }
    while (flag) {
        fgets(curname, 14, fin);
        for(it=0;it<np;it+=1) {
            if (curname==people[it].name) {curnum=it;}
        }
        fscanf(fin,"%d %d",&curmoney,&peeps);
        people[it].money += ((curmoney % peeps) - curmoney);
        curmoney = (curmoney / peeps);
        if (peeps) {
            for(it=0;it<peeps;it+=1) {
                fgets(curname, 14, fin);
                for(it2=0;it<np;it+=1) {
                    if (curname==people[it2].name) {curnum=it2;}
                }
                people[curnum].money+=curmoney;
            }
        }
        else {
            flag=0;
        }
    }
    for(it=0;it<np;it+=1) {
        fprintf (fout, "%s %d\n", people[it].name,people[it].money);
    }
    exit (0);
}

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

A comparação de strings tem que ser feita com:

if (strcmp(str1,str2)==0)

e tens que incluir o <string.h>

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Ai que desgraça... Que erro básico =S

Obrigado ;)

No entanto... Continua a deixar o ficheiro de output com 0 kbytes...

#include <stdio.h>
#include <string.h>
struct person {char name[14]; int money;};
main () {
    FILE *fin  = fopen ("gift1.in", "r");
    FILE *fout = fopen ("gift1.out", "w");
    int np, it, it2, flag, curnum, curmoney, peeps;
    char curname[14];
    flag=1;
    fscanf (fin, "%d" , &np);
    struct person people[np];
    for(it=0;it<np;it+=1); {
        fgets(people[it].name, 14, fin);
    }
    while (flag) {
        fgets(curname, 14, fin);
        for(it=0;it<np;it+=1) {
            if (strcmp(curname,people[it].name)==0) {curnum=it;}
        }
        fscanf(fin,"%d %d",&curmoney,&peeps);
        people[it].money += ((curmoney % peeps) - curmoney);
        curmoney = (curmoney / peeps);
        if (peeps) {
            for(it=0;it<peeps;it+=1) {
                fgets(curname, 14, fin);
                for(it2=0;it<np;it+=1) {
                    if (strcmp(curname,people[it2].name)==0) {curnum=it2;}
                }
                people[curnum].money+=curmoney;
            }
        }
        else {
            flag=0;
        }
    }
    for(it=0;it<np;it+=1) {
        fprintf (fout, "%s %d\n", people[it].name,people[it].money);
    }
    exit (0);
}

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Substitui o exit(0) por return 0, ou fecha o ficheiro antes de chamares o exit. Provavelmente está a falhar o flush para o disco por estares a chamar o exit.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Nope... Já não é o primeiro que faço com exit e funciona sempre. Substituir por return dá o mesmo... :S

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Obrigado mas não é esse o problema. Tenho feito sempre assim e ao chegar a exit (0); ele grava-me automaticamente o ficheiro (com outros exercícios sempre funcionou).

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Mesmo que não seja esse o problema é sempre boa prática por o fclose. Não é garantido que o conteúdo seja gravado.

Substitui:

    for(it=0;it<np;it+=1) {
        fprintf (fout, "%s %d\n", people[it].name,people[it].money);
    }
    exit (0);

por

printf("np: %d", np);
    for(it=0;it<np;it+=1) {
        printf("%d: %s %d\n", it, people[it].name,people[it].money);
        fprintf (fout, "%s %d\n", people[it].name,people[it].money);
    }
    exit (0);

E mostra-nos o output.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Não produz output.

Este é um problema do USACO, ao submeter deu-me o seguinte resultado:

Your program (`gift1') exited with signal

        #8 (floating point exception [usually caused by accessing memory

        out of bounds]).

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Faz uns printfs em cada linha para perceber onde tás a aceder a memória que não é tua. Ou então usa o ddd ou assim.

É importante é perceber a linha do erro.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

É uma ferramente de debugging.

Faz antes assim:

    int np, it, it2, flag, curnum, curmoney, peeps;
    char curname[14];
    flag=1;
printf("1\n");
    fscanf (fin, "%d" , &np);
    struct person people[np];
printf("2\n");
    for(it=0;it<np;it+=1); {
printf("3 %d\n", it);
        fgets(people[it].name, 14, fin);
    }
printf("4\n");

..

Depois corre o programa e tenta perceber qual é a linha que está a dar problemas. Isto é a forma mais simples de debugar.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Já o fiz... Só faz printf do 3 uma vez "3 5" (são 5 pessoas na lista, mas devia fazer 3 1\n 3 2\n 3 3\n 3 4\n, certo?). O 4 aparece, no 5 disse para pôr o nome e aparece "dave" como devia ser (mas com o \n a mais) e no 6 que é o ciclo for seguinte aparece bem também, no 7 é depois desse ciclo para ver qual é o número a que corresponde o nome aparece-me 4012856 (provavelmente um valor que estava na posição de memória e não foi apagado, devia aparecer algo entre 0 e 4 já que são 5 pessoas). E depois é natural que dê erro porque estou a tentar aceder à 4012856 ésima posição de uma structure com 5 posições... Não sei é porque é que ele não reconhece o nome...

Mudei o printf("6") para me dizer não só o valor da iteração como para imprimir as strings 'curname' e 'people[it].name'. A primeira aparece dave como seria de esperar, a segunda aparece-me símbolos estranhos o que deve vir do passo 3 em que ele n me faz o printf normal e como tal nao deve estar a recolher os nomes...

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

    for(it=0;it<np;it+=1); {
        fgets(people[it].name, 14, fin);
    }

Tens um ; a mais antes do {. Nada como fazer debug.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

;) Excelente... Por acaso gostava de aprender a usar a ferramenta de debug do Dev-C++. Mesmo assim, continuo com problemas, nesse ponto 3 aparece:

3 0 -

3 1 - dave

3 2 - laura

3 3 - owen

3 4 - vick

Logo o quinto elemento "amr" não fica guardado... Porque o dave deveria ficar na posição 0.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Isso é porque o fgets está a ler o resto da linha de onde antes fizeste o fscanf. Utiliza um fscanf(fin, " %13s", person[i].name) em vez do fgets. Nota o espaço antes do %13s, que serve para ignorar os caracteres whitespace antes da string a ler. O 13 é mais ou menos como o 14 que usaste no fgets, mas como não inclui o terminador da string tem que ser menos 1 que o tamanho total do array.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Tenho que ler melhor estas definições dos scanf e cia.

Ele vai ler uma string que tem no máximo 13 caracteres, nesse caso, certo? E lê o \n?

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

    for(it=0;it<np;it+=1); {
        fgets(people[it].name, 14, fin);
    }

Tens um ; a mais antes do {. Nada como fazer debug.

Nice Catch.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Ele vai ler uma string que tem no máximo 13 caracteres, nesse caso, certo?

Certo.

E lê o \n?

Se te estás a referir ao '\n' que ficou da linha anterior, é ignorado, tal como qualquer espaço ou tabulação, porque são considerados whitespace characters e o espaço antes do "%13s" serve para os ignorar. Neste caso até nem é necessário, porque o %s exclui os whitespaces todos, só quando é para ler um único caracter é que é mais crítico.

O '\n' seguinte também não é lido, pela mesma razão.

Nice Catch.

Como disse, debug rula ;)

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

É mesmo... Obrigado pela lição... Isto ainda vai ser útil muitas vezes de certeza ;)

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Crie uma conta ou ligue-se para comentar

Só membros podem comentar

Criar nova conta

Registe para ter uma conta na nossa comunidade. É fácil!


Registar nova conta

Entra

Já tem conta? Inicie sessão aqui.


Entrar Agora