Ir ao conteúdo
  • Cadastre-se

C Como corrigir os erros mostrados?


Posts recomendados

Estou tentando solucionar uma questão, mas estão aparecendo estes erros (no site ao submeter o meu código)

 

1782075974_2019-08-20(6).thumb.png.455b13b46949472bb3e16d17434c25a5.png

 

499241960_2019-08-20(7).thumb.png.8bc361a961ab896a42b6316f9c47c635.png

 

591932938_2019-08-20(8).thumb.png.73bff4cf61deae9c163d1b25b98bcdf0.png

 

981419850_2019-08-20(9).thumb.png.456046b42d71ba2ac702c176e04e6056.png

 

1965354821_2019-08-20(10).thumb.png.ae39e11f2bf8ad1481932f17436a88c1.png

 

1192135482_2019-08-20(11).thumb.png.aedb40b09393715dc6c74affdc6e8002.png

 

E o meu código é este:

#include <stdio.h>
#include <string.h>

typedef struct {
	int idade;
	char nome[50];
	char sexo[2];
	char estado_civil[2];
	int qtd_amigos;
	int qtd_fotos;
} cliente;

int main() {
	
	int qtd, i;
	
	scanf("%d", &qtd);

  cliente	clientes[qtd];
	
	for (i = 0; i < qtd; i++) {
		
		scanf("%d", &clientes[i].idade);
		scanf("%s", clientes[i].nome);
		getchar();
		scanf("%s", clientes[i].sexo);
		getchar();
		scanf("%s", clientes[i].estado_civil);
		getchar();
		scanf("%d", &clientes[i].qtd_amigos);
		scanf("%d", &clientes[i].qtd_fotos);
		
	}
	
	for (i = 0; i < qtd; i++) {
		
		printf("Idade: %d\n", clientes[i].idade);
		printf("Nome: %s\n", clientes[i].nome);
		printf("Sexo: %s\n", clientes[i].sexo);
		printf("Estado Civil: %s\n", clientes[i].estado_civil);
		printf("Numero de amigos: %d\n", clientes[i].qtd_amigos);
		printf("Numero de fotos: %d\n", clientes[i].qtd_fotos);
		printf("\n");
		
	}
	
	return 0;
}

 

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

Tenta dessa forma:

#include <stdio.h>
#include <stdlib.h>

typedef struct {
    char nome[50];
    char sexo;
    char estadoCivil;
    int idade;
    int qtdAmigos;
    int qtdFotos;
} Cliente;

int main() {
    int qtd = 0;

    system("clear");    // Mude para cls no Windows
    printf("Quantidade de Pessoas: ");
    scanf(" %i", &qtd);

    Cliente clientes[qtd];

    system("clear");    // Mude para cls no Windows
    for(int i = 0; i < qtd; i++) {
        printf("-------------------------------- \n");
        printf("Nome: ");
        scanf(" %s", clientes[i].nome);

        printf("Sexo [ F / M ]: ");
        scanf(" %c", &clientes[i].sexo);

        printf("Estado [ C / S / N / D ]: ");
        scanf(" %c", &clientes[i].estadoCivil);

        printf("Idade: ");
        scanf(" %i", &clientes[i].idade);

        printf("Amigos: ");
        scanf(" %i", &clientes[i].qtdAmigos);

        printf("Fotos: ");
        scanf(" %i", &clientes[i].qtdFotos);

        printf("-------------------------------- \n");
    }

    system("clear");    // Mude para cls no Windows
    for(int i = 0; i < qtd; i++) {
        printf("-------------------------------- \n");
        printf("  Nome: %s \n", clientes[i].nome);
        printf("  Sexo: %c \n", clientes[i].sexo);
        printf("Estado: %c \n", clientes[i].estadoCivil);
        printf(" Idade: %i \n", clientes[i].idade);
        printf("Amigos: %i \n", clientes[i].qtdAmigos);
        printf(" Fotos: %i \n", clientes[i].qtdFotos);
        printf("-------------------------------- \n");
    }

    return 0;
}

 

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

Em 21/08/2019 às 08:39, programadornovatoc disse:

2019-08-21.thumb.png.b7f07b059c4c9314108796740b5dc1c0.png

 

Logo depois disto deve estar o objetivo em si... Note a barra de rolagem do lado direito. O que vai fazer com esse "banco de dados"?  vai ser mantido em disco? em memoria? que operações deve implementar? Apenas um printf() de tudo que leu?

 

Mas já dá pra entender. Mais tarde vou ver seu código pra ver se posso ajudar em algo

Link para o comentário
Compartilhar em outros sites

Olá!

 

Acho que o aviso sobre a quebra de linha é porque tem que ter uma linha em branco ao final de cada perfil, mesmo que só tenha um cliente

Sobre os \n no final do buffer é porque quando se está lendo da entrada padrão e ao ler o total de arquivos, num int, a chamada a getchar() não consome os dados todos da linha e então sobra um enter ao final e vai zoar a próxima leitura... Testou sua leitura?

Sobre a string nome, ela pode ter 50 caracteres então falta um byte para o null que vem ao final dos dados em cada string. Você fez isso para sexo e estado civil mas não fez para o nome, alocar um byte extra

 

Agora isso:

Em 20/08/2019 às 21:41, programadornovatoc disse:

int qtd, i;

scanf("%d", &qtd);

cliente clientes[qtd];

 

Ou similar:

Em 21/08/2019 às 12:06, AdrianoSiqueira disse:

scanf(" %i", &qtd);

Cliente clientes[qtd];

 

Pode parecer conveniente, mas não existe em C. O valor entre os [] tem que ser uma constante. Ou você aloca um tamanho arbitrário que ache suficiente ou aloca dinamicamente depois de ler o valor na entrada...

 

Vou mostrar um exemplo usando o mais certo, que é alocar depois de saber quantos vai usar. Talvez a coisa mais importante em C é essa simplicidade na manipulação de endereços: se você tem uma coisa tipo

Cliente caras[200]; voce tem 200 Cliente na memória. Se você declara um ponteiro para Cliente e aponta para o primeiro, quando você incrementa o ponteiro ele passa a apontar para o próximo Cliente. Nada mal.Nesse exemplo

Cliente caras[200];
Cliente* p;
p = Clientes[0];
p = p + 2;

Isso funciona e p passa a apontar para o terceiro elemento, Caras[2]. 

 

Um exemplo

Vou mostrar um hipotético programa chamado teste que você roda assim:

 teste arquivo.txt

 e que  lê os dados a partir desse arquivo cujo nome você passa na linha de comando. Porque não ler da entrada padrão inicialmente? Porque?

  • é muito chato ter que digitar toda hora os argumentos
  • se perde muito tempo quando tem que digitar muitos dados.
  • se você lê a partir de um arquivo você pode ter vários arquivos de teste e ir testando com eles até funcionar, e pode repetir o teste em ter que digitar tudo de novo
  • passar a ler da entrada padrão depois é trivial
     

main(int argc, char** argv) e a linha de comando
 

Esses parâmetros de main() indicam o número de argumentos e os valores deles, todos bem arrumadinhos no formato string. argv[0] sempre existe e é o nome do programa. No nosso caso, argv[1] é o nome do arquivo de entrada.

 

Os dados

typedef struct
{
    int idade;
    char nome[51];
    char sexo[2]; // MF
    char estado_civil[2]; // SCND
    int qtd_amigos;
    int qtd_fotos;
}    Cliente;

Essa estrutura serve para o exemplo. 

O programa então lê o total de clientes, roda um loop para ler os dados, roda um loop para imprimir e termina. Só isso.

 

Abre o arquivo, le o total de clientes e aloca a memoria que vai usar

    Entrada = fopen(argv[1], "r");
    int n = fscanf(Entrada, "%d", &total);

    printf("Vai ler %d registros\n", total);
    total_bytes = total * sizeof(Cliente);
    printf("Vai alocar memoria para conter os %d registros de %d bytes. Total = %d bytes\n",
        total,
        sizeof(Cliente),
        total_bytes);
    Cliente* clientes = malloc(total_bytes);

sizeof(Cliente) devolve o tamanho em bytes da estrutura. Como acabamos de ler total que é o total delas, nossa necessidade de memória é de total * sizeof(Cliente), claro.

 

Feito isso temos que ler e mostrar os caras. Como estamos aprendendo e queremos testar em separado vamos usar pequenas funções, nada especial.

codigo para ler os clientes:

    for (int n = 0; n < total; n = n + 1)
    {
        le_cliente(Entrada, (clientes+n) );
    }    // end for

codigo para mostar os clientes:

 for (int n = 0; n < total; n = n + 1)
    {
        mostra_cliente(clientes+n);
    }    // end for  

codigo para terminar o programa:

    // libera a memoria alocada
    if (clientes != NULL) free(clientes);
    // fecha o arquivo 
    fclose(Entrada);
    return 1;

pronto.

 

E pra ler um cliente? Pode ser assim 

int le_cliente(FILE* arquivo, Cliente* um_cliente)
{
    // le um cliente do arquivo e guarda no endereco
    int n;
    n = fscanf(arquivo, "%d",    &um_cliente->idade);
    n = fscanf(arquivo, "%51s",  &um_cliente->nome);
    n = fscanf(arquivo, "%2s",   &um_cliente->sexo);
    n = fscanf(arquivo, "%2s",   &um_cliente->estado_civil);
    n = fscanf(arquivo, "%d",    &um_cliente->qtd_amigos);
    n = fscanf(arquivo, "%d",    &um_cliente->qtd_fotos);
    return 0;
}

Uma vantagem de ter uma função separada é que pra passar a ler da entrada padrão depois  só precisa mudar aqui ou

escrever outra função...

E pra mostrar na tela? Pode ser assim:

int mostra_cliente(Cliente* um_cliente)
{
    // mostra dados do cliente
    printf("               ....*....0....*....0....*....0....*....0....*....0 regua\n");
    printf("Idade:........[%d]\n",           um_cliente->idade);
    printf("Nome:.........[%s]\n",           um_cliente->nome);
    printf("Sexo:.........[%s]\n",           um_cliente->sexo);
    printf("Estado Civil:.[%s]\n",           um_cliente->estado_civil);
    printf("Amigos:.......[%d]\n",           um_cliente->qtd_amigos);
    printf("Fotos:........[%d]\n\n",         um_cliente->qtd_fotos);
    return 0;
}

Que #$%#$% é essa de régua e esse colchetes? Simples: usando os campos entre colchetes durante os testes a gente sabe se está em branco ou se não saiu nada porque tem um delimitador. E a régua ajuda a contar até 50 que é o campo mais comprido, sem ter que perder tempo. Depois que estiver ok a gente apaga ao invés de colocar depois que está dando erro....

               ....*....0....*....0....*....0....*....0....*....0 regua
Idade:........[56]
Nome:.........[01234567890123456789012345678901234567890123456789]
Sexo:.........[F]
Estado Civil:.[N]
Amigos:.......[45]
Fotos:........[56]

Assim você pode conferir o alinhamento e depois que estiver ok é só mudar essa função. Apenas essa escreve na tela...

Para essa entrada em "txt.txt" 

2
12
NOME
M
S
12
34
56
01234567890123456789012345678901234567890123456789
F
N
45
56

O programa mostra

Rodando: C:\Users\toninho\source\repos\ch-190823-struct\Debug\ch-190823-struct.exe


Lendo arquivo txt.txt
Vai ler 2 registros
Vai alocar memoria para conter os 2 registros de 68 bytes. Total = 136 bytes
               ....*....0....*....0....*....0....*....0....*....0 regua
Idade:........[12]
Nome:.........[NOME]
Sexo:.........[M]
Estado Civil:.[S]
Amigos:.......[12]
Fotos:........[34]

               ....*....0....*....0....*....0....*....0....*....0 regua
Idade:........[56]
Nome:.........[01234567890123456789012345678901234567890123456789]
Sexo:.........[F]
Estado Civil:.[N]
Amigos:.......[45]
Fotos:........[56]

Eis um código completo, que roda ao menos em Windows com Visual Studio. Não tenho tempo para testar em outros ambientes :( 

 

#define _CRT_SECURE_NO_WARNINGS
#include "stdio.h"
#include "stdlib.h"

typedef struct
{
    int idade;
    char nome[51];
    char sexo[2]; // MF
    char estado_civil[2]; // SCND
    int qtd_amigos;
    int qtd_fotos;
}    Cliente;

int flush_in()
{
    char c;
    do
    {
        c = getchar();
        if (c == '\n') return 1;
        if (c == EOF)    return 2;
    }while (1);
}

int le_cliente(FILE* arquivo, Cliente* um_cliente)
{
    // le um cliente do arquivo e guarda no endereco
    int n;
    n = fscanf(arquivo, "%d",    &um_cliente->idade);
    n = fscanf(arquivo, "%51s", &um_cliente->nome);
    n = fscanf(arquivo, "%2s",    &um_cliente->sexo);
    n = fscanf(arquivo, "%2s",    &um_cliente->estado_civil);
    n = fscanf(arquivo, "%d",    &um_cliente->qtd_amigos);
    n = fscanf(arquivo, "%d",    &um_cliente->qtd_fotos);
    return 0;
}

int mostra_cliente(Cliente* um_cliente)
{
    // mostra dados do cliente
    printf("               ....*....0....*....0....*....0....*....0....*....0 regua\n");
    printf("Idade:........[%d]\n", um_cliente->idade);
    printf("Nome:.........[%s]\n",                    um_cliente->nome);
    printf("Sexo:.........[%s]\n",                    um_cliente->sexo);
    printf("Estado Civil:.[%s]\n",            um_cliente->estado_civil);
    printf("Amigos:.......[%d]\n",                um_cliente->qtd_amigos);
    printf("Fotos:........[%d]\n\n",                    um_cliente->qtd_fotos);
    return 0;
}


int main(int argc, char** argv)
{
    FILE* Entrada;
    char * arquivo = "txt.txt";

    int total = 0;
    int total_bytes;

    if (argc < 0)
    {
        printf("Faltou o nome do arquivo\n");
        return 0;
    }    // end if

    printf("Rodando: %s\n\n\n", argv[0]);
    printf("Lendo arquivo %s\n", argv[1]);

    Entrada = fopen(argv[1], "r");
    int n = fscanf(Entrada, "%d", &total);

    printf("Vai ler %d registros\n", total);
    total_bytes = total * sizeof(Cliente);
    printf("Vai alocar memoria para conter os %d registros de %d bytes. Total = %d bytes\n",
        total,
        sizeof(Cliente),
        total_bytes);
    Cliente* clientes = malloc(total_bytes);

    // le os clientes
    for (int n = 0; n < total; n = n + 1)
    {
        le_cliente(Entrada, (clientes+n) );
    }    // end for
    // mostra os clientes
    for (int n = 0; n < total; n = n + 1)
    {
        mostra_cliente(clientes+n);
    }    // end for
    // libera a memoria alocada
    if (clientes != NULL) free(clientes);
    // fecha o arquivo 
    fclose(Entrada);
    return 1;
}
  • Obrigado 1
Link para o comentário
Compartilhar em outros sites

@programadornovatoc , tudo certo?

 

Sugere-se na dica do site que a largura para string nome é insuficiente (mal lido).

 

Nas orientações do exame é sugerido uma com comprimento mínimo de 50 caracteres, isso significa que se quero estruturar 50 caracteres preciso de um vetor de 51 elementos, pois o que diferencia a string do vetor é o caractere nulo no final.

 

 

 

Observações extras.

 

1#

Em 21/08/2019 às 12:06, AdrianoSiqueira disse:

scanf(" %s", clientes[i].nome);

Nome se composto não captura integralmente por esses comandos.

 

2#

Em 24/08/2019 às 00:52, arfneto disse:

n = fscanf(arquivo, "%51s", &um_cliente->nome);

Não preciso endereçar (referenciar) uma referência. Mesmo especificando a largura do campo (51) e endereçando um objeto de mesmo tamanho, char (*) [51], a função só captura até a primeira ocorrência de espaço e isso não é o que se espera de 51 caracteres.  *Aproposito não 51 e sim 50.

 

 

 

 

 

Link para o comentário
Compartilhar em outros sites

16 horas atrás, arfneto disse:

Agora isso:

Em 20/08/2019 às 21:41, programadornovatoc disse:

int qtd, i;

scanf("%d", &qtd);

cliente clientes[qtd];

 

Ou similar:

Em 21/08/2019 às 12:06, AdrianoSiqueira disse:

scanf(" %i", &qtd);

Cliente clientes[qtd];

 

Pode parecer conveniente, mas não existe em C. O valor entre os [] tem que ser uma constante. Ou você aloca um tamanho arbitrário que ache suficiente ou aloca dinamicamente depois de ler o valor na entrada...

 

Exste sim, o nome disso é arranjo/vetor de comprimento variável (Variable Length Array ou VLA), e foi introduzido na versão C99 da linguagem C.

 

Mas é necessário ter cuidado ao usar, pois existe um limite de tamanho máximo para alocar um vetor assim, ainda mais se levar em conta que está alocando vetor de um struct que pode ocupar bastante espaço, então o certo nesse caso seria limitar o tamanho de qtd digitado pelo usuário para ir até um valor máximo apenas, ou então usar alocação dinâmica mesmo.

Link para o comentário
Compartilhar em outros sites

45 minutos atrás, isrnick disse:

Exste sim, o nome disso é arranjo/vetor de comprimento variável (Variable Length Array ou VLA), e foi introduzido na versão C99 da linguagem C.

 

Mas é necessário ter cuidado ao usar, pois existe um limite de tamanho máximo para alocar um vetor assim, ainda mais se levar em conta que está alocando vetor de um struct que pode ocupar bastante espaço, então o certo nesse caso seria limitar o tamanho de qtd digitado pelo usuário para ir até um valor máximo apenas, ou então usar alocação dinâmica mesmo

 

:) Grato por esclarecer isso!

O compilador que eu uso não aceita isso que eu não sabia que era possível. Mas não parece algo interessante. Passei uns minutos procurando habilitar isso na minha máquina sem sucesso. Tenho outras aqui com outros compiladores que devem aceitar isso mas quando tenho tempo livre para acessar esse forum ou outros em geral uso uma maquina que roda Windows 10 e Visual Studio '19 e fica perto do café :D 

 

Voltando ao recurso, note que essa alocação acontece no stack. E é uma alocação estática, não tem como liberar depois. E a implementação parece nem ser obrigatória. Dei uma olhada no documento no ISO 9899 referencia do C99 em open-sttd.org e não parece mesmo algo recomendável. Mas como eu disse tem um apelo pela comodidade.

 

De todo modo eu não recomendaria para quem está aprendendo a programar considerar isso. Se tem uma razão para usar C hoje em dia está em alocação dinâmica e aritmética de ponteiros. Nunca vi isso sendo usado em um programa de produção, e eu até achava que não existia.

 

O pequeno programa que postei mostra um uso simples de malloc() e free() e acho que vale a pena aprender se quer programar em C e ler/entender programas de produção

 

 

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

Crie uma conta ou entre para comentar

Você precisa ser um usuário para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar agora

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...

Ebook grátis: Aprenda a ler resistores e capacitores!

EBOOK GRÁTIS!

CLIQUE AQUI E BAIXE AGORA MESMO!