Ir ao conteúdo
  • Cadastre-se

C++ funções e matrizes ISBN


MATHEUSCDN
Ir à solução Resolvido por arfneto,

Posts recomendados

1430222046_CapturadeTela(895).png.7e33d1183a2c70ea791a7e347518df8a.png

Alguém pode me ajudar ? Tenho esse trabalho para fazer mas estou travado e não consigo pensar em uma solução 

 

Por enquanto meu código é esse :

 

#include <stdio.h>

int main ()
{
unsigned long long int isbn, copiaISBN;
int cont=1,soma=0, digito,ultdigito,aux;

printf ("Insira os primeiros doze digitos do ISBN: ");
scanf ("%lu",&isbn);

copiaISBN= isbn;
while (copiaISBN>0);
{
	digito= copiaISBN%11;
if (cont%2==0)
{
	soma = soma=(digito*1);
	cont=1;
}
else
{
	soma=soma+(digito*3);
	cont=2;
}
copiaISBN = copiaISBN/10;
}
aux= soma%11;
ultdigito=10 - aux;
printf ("Ultimo digito: %d", ultdigito);
return 0;
}

Ainda faltam as funções para teste e outra função para fazer a soma de s1 e s2

Link para o comentário
Compartilhar em outros sites

@MATHEUSCDN O cálculo deve ser feito na função que vai retornar o dígito. Acho mais fácil usar char em vez de um valor inteiro, assim fica mais simples pegar cada digito no loop. O protótipo da função pode ser assim,

 

int isbn_dv(const char *isnb);

 

No primeiro loop seu código pode pegar cada posição para calcular as somas, p.ex,

s1 += isnb[i] - '0';
s2 += s1;

 

E depois faça outro loop entre 0 e 10 para encontrar o dígito,

if((s1 + s2 + i) % 11 == 0){
    digito = i;
...

 

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

@Midori Então no caso eu chamaria a função e mostro o valor de digito ? E eu puxo os dados de um programa txt, então tenho que colocar um scanf antes disso tudo ne ?

 

@Midori Eu fiz isso

#include <stdio.h>

int isbn_dv(const char *isbn)
{
	int s1,s2,i,digito;
	
	s1 += isbn[i] - '0';
	s2 += s1;
	
	if((s1 + s2 + i) % 11 == 0)
	{
    digito = i;
	}
}

int main ()
{
unsigned long long int isbn;
int digito;
scanf ("%lu",&isbn);
isbn_dv(isbn);
printf ("Ultimo digito: %d",digito);
return 0;
}

E apareceu alguns erros 

image.png.182d00084d7c5314ec7c71273e91358a.png

 

O que está errado ?

Link para o comentário
Compartilhar em outros sites

1 hora atrás, MATHEUSCDN disse:

 E eu puxo os dados de um programa txt, então tenho que colocar um scanf antes disso tudo ne ?

 

Não necessariamente, e se for usar uma dessas funções seria fscanf() certo?

 

Esse exemplo "para deixar as coisas mais claras" que tem no enunciado é bem folclórico

 

Está entre mal escrito e simplesmente errado.

 

ISBN 'e normatizado e formado por 10 e em fase de transição para 13 dígitos, e eles são conhecidos pelos nomes ingênuos de ISBN-10 e ISBN-13, e nem sempre tem o hífen.

 

O DV nesse caso é o último dígito e é o clássico DV módulo 11, como é o caso das contas no banco, CPF, RG e tal.

 

Ao invés de duplas somas em cascata, como descrito acima, o simples: cada dígito tem um peso, os valores são somados e o dígito verificador é a soma módulo 11. 

 

Como a soma módulo 11 é um número entre 0 e 10 (inclusive) e só temos 10 dígitos em decimal então o 'X' é usado quando o módulo da soma for 10. É o mesmo caso do RG.

 

E que pesos são esses? 

 

NO ISBN-10 são complexos: 1,2,3,4,5,6,7,8 e 9

 

No exemplo...

   0   1   3   1   6   2   9   5   9 digitos
   1   2   3   4   5   6   7   8   9 pesos

E com as somas

   0    1    3    1    6    2    9    5    9
   1    2    3    4    5    6    7    8    9

   0    2    9    4   30   12   63   40   81  produtos

Com os totais

   0    1    3    1    6    2    9    5    9 digitos
   1    2    3    4    5    6    7    8    9 pesos

   0    2    9    4   30   12   63   40   81 produtos
        2   11   15   45   57  120  160  241 sub-totais

E tem a soma, 241

 

241 = 21*11 + 10, e assim o resto da divisão da soma por 11 é 10 e o dígito verificador é X.

 

Sugiro esquecer o que está escrito lá e calcular assim. Em geral os algoritmos de DV são calculados assim, uma soma aplicando pesos aos dígitos...

 

 

 

 

quanto à leitura, recomendo usar fgets() e ler a linha toda. É muito mais simples.

Link para o comentário
Compartilhar em outros sites

3 horas atrás, MATHEUSCDN disse:

@arfneto O trabalho pede pra puxar os dados de outro programa 

 

Não existe um programa txt.  Está confundindo as coisas. Trata-se de um arquivo onde tem uma série de números de 9 dígitos, 1 por linha. Eu te mostrei um exemplo, mas pode usar esse aqui também:

 

013162959X
3462150790
0198526636
0387901442
3540901442
0201179288

 

Esses estão já com o dígito então você sabe o que esperar. E o primeiro é o exemplo de seu professor. Apenas salve em seu computador como txt.
 

3 horas atrás, MATHEUSCDN disse:

E nesse trabalho pede pra fazer pelas somas parciais mesmo, o professor não aceita de outro jeito, infelizmente

 

Espero que não seja mesmo assim. Isso é coisa do ensino primário.

 

Cálculo de DV está em toda parte. Sobre o ISBN o oficial está documentado em https://isbn-information.com/the-10-digit-isbn.html e é algo sério. O mundo inteiro precisa usar isso. O padrão mudou em 2007 e agora tem 13 dígitos.

 

Sobre o programa que escreveu

 

int isbn_dv(const char *isbn)
{
	int s1,s2,i,digito;
	
	s1 += isbn[i] - '0';
	s2 += s1;
	
	if((s1 + s2 + i) % 11 == 0)
	{
    digito = i;
	}
}


Essa função está muito longe ainda de funcionar. Sequer tem um loop e não tem um retorno. O que é i por exemplo? E para que retornar um int se não vai operar com ele e recebeu um char[9]? retorne um char para ser anexado aos 9 que já tem lá de onde vieram... É mais prático.

 

E main()

 

 

int main ()
{
unsigned long long int isbn;
int digito;
scanf ("%lu",&isbn);
isbn_dv(isbn);
printf ("Ultimo digito: %d",digito);
return 0;
}

 

Pra que está lendo o valor a testar? Porque não faz o simples e testa primeiro até funcionar com 13162959 que você já tem no exemplo e sabe que tem que dar 'X'???

 

Não está sequer mostrando o valor que voltou da função.

O que acha que vai sair do printf() se digito nem foi inicializado?

Não está testando o valor de retorno de scanf() e nem está mostrando o valor lido, então como vai saber se a conta está certa?

 

SOBRE o cálculo em C

 

Fazer as somas parciais é trivial. Só é pouco inteligente. Pra você ter uma ideia da diferença, essa função calcula o dígito verificador do ISBN: 
 

char isbn_dv(char isbn[9])
{
    int soma = 0;
    for (int d = 1; d <= 9; d += 1)
      soma += (isbn[d-1] - '0') * d;
    int dv = soma % 11;
    if (dv == 10) return 'X';  return '0' + dv;
};

 

Passa o número, recebe o dígito...

 

Assim por exemplo:

 

    printf("%s-%c\n", p, isbn_dv( &linha[0]));


Para esse arquivo

 

013162959X
0387901442
3540901442
0201179288

 

mostra

 

013162959-X
038790144-2
354090144-2
020117928-8

 

image.png.f29f5a35386cfbb1fdeffe9a44f806f7.png

Notou quanto é a soma? 

s1 + s2 é 241... é só matemática.

 

image.png.1c3304f61a1f3c30bcdb89c0248c4a94.png

 

Essa tabela tem 10 dígitos

 

Entenda isso: essa tabela é para conferir o dígito. Seu professor pode ter feito de propósito pra ver se você está atento, ou pode ter só errado mesmo...

 

Como pode calcular e somar com 10 dígitos se só tem 9?  Não achou estranho?

 

A função oficial

 

char isbn_dv_oficial(char isbn[9])
{
    int soma = 0;
    for (int d = 10; d >= 2; d -= 1)
      soma += (isbn[10 - d] - '0') * d;
    int dv = 11 - (soma % 11);
    if (dv == 11) return '0';
    if (dv == 10) return 'X';
    return '0' + dv;
};

 

Essa função calcula do modo oficial, com os pesos de 10 a 2.

 

A função do professor :)

 

char isbn_dv_professor(char isbn[9])
{
    int s1 = 0;
    int s2 = 0;
    for (int d = 0; d < 9; d += 1)
      s1 += isbn[d] - '0', s2 += s1;
    int dv = 11 - ((s1 + s2) % 11);
    if (dv == 11) return '0';
    if (dv == 10) return 'X';
    return '0' + dv;
};

 

Essa é a função do seu professor, e não muda muito, só não há razão pra fazer desse jeito, como eu te disse

 

EXEMPLO: um milhão de testes com as 3 funções

 

É claro que se as 3 estiverem ok vão gerar o mesmo dígito. Então esse programa 

gera 1 milhão de ISBN (que não tem plural), e calcula os DV (que não tem plural) usando as 3 funções, parando assim que der alguma diferença..

 

É melhor o computador testar do que um de nós digitando 9 números para cada teste :D um milhão de vezes

 

int main(void)
{
    srand(210904);
    char  linha[20] = {0};
    char* p         = linha;
    printf( "\
    %d testes com valores aleatorios. '*' = 1.000 testes\n\
    [Parando na primeira diferenca]\n\n", N);
    for (int i = 0; i < N; i += 1)
    {
        for (int d = 0; d < 9; d += 1)
          linha[d] = '0' + rand() % 10;
        char dv1 = isbn_dv(&linha[0]);
        char dv2 = isbn_dv_oficial(&linha[0]);
        char dv3 = isbn_dv_professor(&linha[0]);
        if ((dv1 != dv2) || (dv2 != dv3))
        {
            printf("%s: %c\t%c\t%c\n", p, dv1, dv2, dv3);
            return -1;
        }
        if (i % 1000 == 999) printf("* ");
        if (i % 50000 == 49999) printf("\n");
    };  // for(i)
    return 0;
}

 

A saída de um teste:

 


Clube>./ft-0903
    1000000 testes com valores aleatorios. '*' = 1.000 testes
    [Parando na primeira diferenca]

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
...
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Clube>

 

Apaguei algumas linhas de asteriscos claro.

 

Um teste completo, com as 3 funções

 

/*
* https://www.clubedohardware.com.br/
  topic/1561085-fun%C3%A7%C3%B5es-e-matrizes-isbn/
  ?tab=comments#comment-8259599
  ARFNeto '21
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char isbn_dv(char[9]); // a funcao
char isbn_dv_oficial(char[9]); // com os pesos oficiais
char isbn_dv_professor(char[9]); // como seu professor gosta

int main(int argc, char** argv)
{
    const char  padrão[]    = "isbn.txt";
    char        arquivo[30] = {0};
    char        linha[80];

    if (argc > 1)  // veio algo entao e o nome do arquivo
        strcpy(arquivo, argv[1]);
    else
        strcpy(arquivo, padrão);

    printf("Arquivo de entrada: \"%s\"\n", arquivo);

    FILE* entrada = fopen(arquivo, "r");
    if (entrada == NULL) return -1;
    printf("Aberto \"%s\"\n", arquivo);

    char* p = fgets(linha, sizeof linha, entrada);

    while (p != NULL)
    {
        *(p+9) = 0;
        printf("%s-%c\t%s-%c\t%s-%c\n",
            p, isbn_dv(          &linha[0]),
            p, isbn_dv_oficial(  &linha[0]),
            p, isbn_dv_professor(&linha[0])
        );
        p = fgets(linha, sizeof linha, entrada);
    }
    fclose(entrada);
    return 0;
}

char isbn_dv(char isbn[9])
{
    int soma = 0;
    for (int d = 1; d <= 9; d += 1)
      soma += (isbn[d - 1] - '0') * d;
    int dv = soma % 11;
    if (dv == 10) return 'X';
    return '0' + dv;
};

char isbn_dv_oficial(char isbn[9])
{
    int soma = 0;
    for (int d = 10; d >= 2; d -= 1)
      soma += (isbn[10 - d] - '0') * d;
    int dv = 11 - (soma % 11);
    if (dv == 11) return '0';
    if (dv == 10) return 'X';
    return '0' + dv;
};

char isbn_dv_professor(char isbn[9])
{
    int s1   = 0;
    int s2   = 0;
    for (int d = 0; d < 9; d += 1)
        s1 += isbn[d] - '0', s2 += s1;
    int dv = 11 - ((s1+s2) % 11);
    if (dv == 11) return '0';
    if (dv == 10) return 'X';
    return '0' + dv;
};

 

Usando o arquivo acima, deve mostrar

 

Clube> ./or-0903
Arquivo de entrada: "isbn.txt"
Aberto "isbn.txt"
013162959-X     013162959-X     013162959-X
038790144-2     038790144-2     038790144-2
354090144-2     354090144-2     354090144-2
020117928-8     020117928-8     020117928-8
Clube>

 

Claro que cada coluna é o cálculo com uma função diferente: a que eu mostrei, a oficial e que seu professor "exige".

 

 

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

16 horas atrás, MATHEUSCDN disse:

O que está errado ?

A variável i é o contador do loop, então faltou fazer os dois loops que comentei e retornar o valor do dígito assim,

 

#include <stdio.h>

char isbn_dv(const char *isbn){
    int s1 = 0;
    int s2 = 0;
    int digito = 0;
	
    for(int i = 0; isbn[i] != 0; i += 1){
        s1 += isbn[i] - '0';
        s2 += s1;
    }
	
    for(int i = 0; i <= 10; i += 1){
        if((s1 + s2 + i) % 11 == 0){
            digito = i;
            break;
        }
    }
    if(digito == 10){
        return 'X';
    }
    return digito + '0';
}

int main(void){
    char isbn[9];
	
    scanf("%9s", isbn);
    printf("%s-%c", isbn, isbn_dv(isbn));
	
    return 0;
}

 

Link para o comentário
Compartilhar em outros sites

 

 

Porque está usando um compilador com mensagens em inglês?

 

msg.png.2440553a0ec1d4c4046d105055499852.png

 

Está escrito aí o que está errado: você está usando seu ambiente configurado para a linguagem C de 30 anos atrás. Mude para alo mais moderno e em português se possível.

 

Quanto ao que fazer, está escrito na tela de seu micro... use por exemplo -std=c17 nas opções do compilador. E aproveite e acrescente -Wall para mostrar os avisos todos...

 

18 minutos atrás, MATHEUSCDN disse:

E mais uma dúvida, como eu posso fazer uma repetição em que a leitura pare apenas quando o usuario digitar " 000000000 " ?

 

 

Use um if, compare o valor e pare quando for esse... E tire os espaços entre as aspas e os zeros a menos que pretenda que o usuário de fato digite assim... Use strcmp() para comparar as strings...

 

 

 

Link para o comentário
Compartilhar em outros sites

@arfneto Eu troquei o nome de atividade.c para atividade.cpp e não aparece mais esse erro

@arfneto E em vez de if eu poderia usar um while para fazer essa repetição ? Tipo :

while (isbn != 000000000){
do
...

}

Esse exemplo que dei não funcionou não sei o porque, eu queria fazer algo tipo esse exemplo mas ele só ler a primeira linha do arquivo.txt e encerra 

image.thumb.png.6ca22903f61f5925ce8db3a48cf63da0.png

Link para o comentário
Compartilhar em outros sites

1 hora atrás, MATHEUSCDN disse:

Eu troquei o nome de atividade.c para atividade.cpp e não aparece mais esse erro

 

Faça o certo. O que eu disse. E o que o compilador disse. Use as opções de que eu falei. 

 

Se está aprendendo tem uma razão a mais para não ficar improvisando. 

 

 

1 hora atrás, MATHEUSCDN disse:

Esse exemplo que dei não funcionou não sei o porque, eu queria fazer algo tipo esse exemplo mas ele só ler a primeira linha do arquivo.txt

 

Esse é outro caso em que não deveria "inventar" nada. Porque redirecionar a entrada se quer ler um arquivo? E porque simplesmente não abrir um arquivo, considerando que eu te mostrei um exemplo completo de como fazer isso e como rodar 1 milhão de testes com 3 funções que funcionam, incluindo uma que "o professor exige"?

 

E onde está a pare em que diz pro seu programa continuar lendo outras linhas? 

 

Leu o exemplo que te mostrei? Rodou em sua máquina? Deveria...

 

2 horas atrás, arfneto disse:

Use um if, compare o valor e pare quando for esse... E tire os espaços entre as aspas e os zeros a menos que pretenda que o usuário de fato digite assim... Use strcmp() para comparar as strings...

 

Leu isso?

 

 

@Midori, sobre essa sua versão da função

 

char isbn_dv_mdr(char isbn[9])
{
    int s1     = 0;
    int s2     = 0;
    int digito = 0;

    for (int i = 0; isbn[i] != 0; i += 1)
    {
        s1 += isbn[i] - '0';
        s2 += s1;
    }

    for (int i = 0; i <= 10; i += 1)
    {
        if ((s1 + s2 + i) % 11 == 0)
        {
            digito = i;
            break;
        }
    }
    if (digito == 10) { return 'X'; }
    return digito + '0';
}

 


image.png.6eeb3b2dcb70d73b9b59fc56c21b1234.png
Compare com a tabela do enunciado, aqui ao lado..

 

 

Esta função usa dois loops e no segundo calcula uma soma de 3 parcelas para depois chamar % dentro do loop.

 

Compare com o simples, uma das funções que eu mostrei

 

char isbn_dv_professor(char isbn[9])
{
    int s1 = 0;
    int s2 = 0;
    for (int d = 0; d < 9; d += 1) s1 += isbn[d] - '0', s2 += s1;
    int dv = 11 - ((s1 + s2) % 11);
    if (dv == 11) return '0';
    if (dv == 10) return 'X';
    return '0' + dv;
};

 

Como eu disse, essa não é assim uma ideia muito boa, tem uma soma em cascata que não é necessária, mas aí você acrescentou mais um loop, uma soma com resultados temporários e uma chamada de módulo dentro do loop.

 

Deve ser bem mais lento.  Mas seria mesmo? E quanto?

 

Numa época em que tudo está mudando (voltando, de certo modo) para a "nuvem", e que Amazon vende funções e computadores são vendidos divididos em armazenamento, processamento e memória, tudo virtual, é hora de se preocupar muito com essas coisas. Cada milissegundo de processamento custa dinheiro.

 

Eu mostrei um exemplo antes de como chamas as 3 funções para um certo número de testes e ver se todas calculam o mesmo DV.

 

Vou adaptar esse exemplo para testar as agora 4 funções e mostrar uma maneira simples, mas usada na prática, para medir essas coisas.

 

Nada exótico. O simples.

 

O objetivo:

 

 Função     Tempo
--------------------
oficial       T
   v1         xT
   v2         yt 
   v3         zt

 

Tabelar o resultado em termos de tempo de execução para as 4 funções, considerando a versão "oficial"  como 1, e avaliar x, y e z. Por exemplo, se o tempo de v1 for .75T que dizer que a versão 1 levou 75% do tempo.

 

Em termos de complexidade e armazenamento elas são similares.

 

Escrevendo em torno dos dados

 

Claro, vou usar o exemplo que mostrei antes, para não gastar tempo com isso.

 

As funções

 

    char isbn_dv(char[9]);            // a funcao
    char isbn_dv_oficial(char[9]);    // com os pesos oficiais
    char isbn_dv_professor(char[9]);  // como seu professor gosta
    char isbn_dv_mdr(char[9]);        // midori verison as posted

 

A representação da  tabela para os dados

 


typedef struct
{
    const char* descricao;
    char      (*Funcao)(char[9]);
    clock_t     tempo;

} Tabela;

 

E vamos usar uma função para testar a versão e retornar o tempo gasto para N testes, como no programa original, essa função:

 

    clock_t testa_funcao(unsigned, char (*)(char[9]));

 

Nada especial: para testar 1200 vezes a função que você escreveu, por exemplo, se usa

 

    clock_t testa_funcao( 1200, isbn_dv_mdr );

 

clock_t é definido em time.h, um long int. E em geral representa um tempo em milissegundos

 

E na struct Tabela tem o nome e a descrição para as funções, porque eu quero deixar um exemplo genérico e fácil de adaptar.

 

Como preencher Tabela nesse caso?

 

Um modo simples, talvez o mais simples:

 

    Tabela grade[4] = {
        [0].descricao = "oficial",
        [0].Funcao    = isbn_dv_oficial,
        [0].tempo     = 0,
        [1].descricao = "pesos 1..9",
        [1].Funcao    = isbn_dv,
        [1].tempo     = 0,
        [2].descricao = "aprovada pelo professor :)",
        [2].Funcao    = isbn_dv_professor,
        [2].tempo     = 0,
        [3].descricao = "@Midori",
        [3].Funcao    = isbn_dv_mdr,
        [3].tempo     = 0,
    };

 

Os tempos estão claro com 0. mas serão preenchidos pelo teste, afinal esse é o objetivo.

 

A execução:

 

    // primeiro roda com a versão oficial
    printf("Rodando a versão oficial... ");
    grade[0].tempo = testa_funcao(N, grade[0].Funcao);

    printf(" ok!\nRodando as outras versões. versão oficial = 1.0X\n");
    for (int i = 1; i < 4; i += 1)
    {   srand(210904);
        grade[i].tempo = testa_funcao(N, grade[i].Funcao);
    }

 

Esse loop faz o serviço e depois é só mostrar a tabela

 

Os resultados, em um único comando:

 

    for (int i = 1; i < 4; i += 1)
        printf("%4.2fX para versão %s\n", 
            (double)grade[i].tempo/ grade[0].tempo,
            grade[i].descricao);

 

Saída de um teste para as 4 funções, com 2 milhões de testes:

 

    [Comparando as 4 funcoes]
    2000 (*1.000) testes com valores aleatorios, mesma serie

Rodando a versão oficial...  ok!
Rodando as outras versões. versão oficial = 1.0X
0.91X para versão pesos 1..9
1.10X para versão aprovada pelo professor :)
3.64X para versão @Midori

 

E assim temos números:

 

a versão oficial é ok, oficial. Como eu escrevi é uns 10% mais rápida. Seguindo o enunciado com a soma estranha em cascata 10% mais lento, e escrevendo como você sugeriu 364% mais lento.

 

Como eu sempre dizia pro meu pessoal, em dúvida ou mesmo sem dúvida, meça. Compare e teste.

 

A função de teste

 

Com 4 linhas, não em muito que dizer sobre isso

 

clock_t testa_funcao(unsigned n, char (*F)(char[9]))
{
    char    linha[20];
    for (int d = 0; d < 9; d += 1) linha[d] = '0' + rand() % 10;
    clock_t inicio = clock();
    for (unsigned i = 0; i < n; i += 1) (*F)(linha);
    clock_t fim = clock();
    return (fim - inicio);
}

 

Apenas cria um ISBN e chama a função n vezes. Retorna o tempo que passou no loop.

 

O programa completo

 

/*
* https://www.clubedohardware.com.br/
  topic/1561085-fun%C3%A7%C3%B5es-e-matrizes-isbn/
  ?tab=comments#comment-8259599
  ARFNeto '21
*/

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

char isbn_dv(char[9]);            // a funcao
char isbn_dv_oficial(char[9]);    // com os pesos oficiais
char isbn_dv_professor(char[9]);  // como seu professor gosta
char isbn_dv_mdr(char[9]);        // midori verison as posted

clock_t testa_funcao(unsigned, char (*)(char[9]));

typedef struct
{
    const char* descricao;
    char      (*Funcao)(char[9]);
    clock_t     tempo;

} Tabela;

int main(void)
{
    Tabela grade[4] = {
        [0].descricao = "oficial",
        [0].Funcao    = isbn_dv_oficial,
        [0].tempo     = 0,
        [1].descricao = "pesos 1..9",
        [1].Funcao    = isbn_dv,
        [1].tempo     = 0,
        [2].descricao = "aprovada pelo professor :)",
        [2].Funcao    = isbn_dv_professor,
        [2].tempo     = 0,
        [3].descricao = "@Midori",
        [3].Funcao    = isbn_dv_mdr,
        [3].tempo     = 0,
    };

    const int N = 2000 * 1000;
    char  linha[20] = {0};
    char* p         = linha;
    printf("\
    [Comparando as 4 funcoes]\n\
    %d (*1.000) testes com valores aleatorios, mesma serie\n\n",
        N/1000 );

    // primeiro roda com a versão oficial
    printf("Rodando a versão oficial... ");
    grade[0].tempo = testa_funcao(N, grade[0].Funcao);

    printf(" ok!\nRodando as outras versões. versão oficial = 1.0X\n");
    for (int i = 1; i < 4; i += 1)
    {   srand(210904);
        grade[i].tempo = testa_funcao(N, grade[i].Funcao);
    }
    // mostra a tabela
    for (int i = 1; i < 4; i += 1)
        printf("%4.2fX para versão %s\n", 
            (double)grade[i].tempo/ grade[0].tempo,
            grade[i].descricao);
    return 0;
}

char isbn_dv(char isbn[9])
{
    int soma = 0;
    for (int d = 1; d <= 9; d += 1) soma += (isbn[d - 1] - '0') * d;
    int dv = soma % 11;
    if (dv == 10) return 'X';
    return '0' + dv;
};

char isbn_dv_oficial(char isbn[9])
{
    int soma = 0;
    for (int d = 10; d >= 2; d -= 1) soma += (isbn[10 - d] - '0') * d;
    int dv = 11 - (soma % 11);
    if (dv == 11) return '0';
    if (dv == 10) return 'X';
    return '0' + dv;
};

char isbn_dv_professor(char isbn[9])
{
    int s1 = 0;
    int s2 = 0;
    for (int d = 0; d < 9; d += 1) s1 += isbn[d] - '0', s2 += s1;
    int dv = 11 - ((s1 + s2) % 11);
    if (dv == 11) return '0';
    if (dv == 10) return 'X';
    return '0' + dv;
};

char isbn_dv_mdr(char isbn[9])
{
    int s1     = 0;
    int s2     = 0;
    int digito = 0;

    for (int i = 0; isbn[i] != 0; i += 1)
    {
        s1 += isbn[i] - '0';
        s2 += s1;
    }

    for (int i = 0; i <= 10; i += 1)
    {
        if ((s1 + s2 + i) % 11 == 0)
        {
            digito = i;
            break;
        }
    }
    if (digito == 10) { return 'X'; }
    return digito + '0';
}

clock_t testa_funcao(unsigned n, char (*F)(char[9]))
{
    char    linha[20];
    for (int d = 0; d < 9; d += 1) linha[d] = '0' + rand() % 10;
    clock_t inicio = clock();
    for (unsigned i = 0; i < n; i += 1) (*F)(linha);
    clock_t fim = clock();
    return (fim - inicio);
}

 

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

1 hora atrás, arfneto disse:

E onde está a pare em que diz pro seu programa continuar lendo outras linhas?

Não coloquei a segunda página aqui mas ele colocou isso como exemplo :

 

image.png.1bf601c8bfa7b45d230e265f4b478a93.png

 

1 hora atrás, arfneto disse:

Esse é outro caso em que não deveria "inventar" nada. Porque redirecionar a entrada se quer ler um arquivo? E porque simplesmente não abrir um arquivo, considerando que eu te mostrei um exemplo completo de como fazer isso e como rodar 1 milhão de testes com 3 funções que funcionam, incluindo uma que "o professor exige"?

Eu não escolho isso , o proprio professor pede para executar o arquivo no cmd assim : atividade.exe < isbn.txt 

1 hora atrás, arfneto disse:

a versão oficial é ok, oficial. Como eu escrevi é uns 10% mais rápida. Seguindo o enunciado com a soma estranha em cascata 10% mais lento, e escrevendo como você sugeriu 364% mais lento.

 

Como eu sempre dizia pro meu pessoal, em dúvida ou mesmo sem dúvida, meça. Compare e teste.

Ainda estou iniciando em C, tem muita informação ae que não consigo compreender e por enquanto não estamos sendo ensinados a fazer versões que são mais rápidas e sim versões que executem o que o professor pede

Mas obrigado pela ajuda, vou dar uma estudada e achar alguma forma de criar essa repetição

 

Link para o comentário
Compartilhar em outros sites

41 minutos atrás, MATHEUSCDN disse:

Não coloquei a segunda página aqui mas ele colocou isso como exemplo

 

@MATHEUSCDN, eu me referia a qual parte do seu programa estava a instrução para o programa fazer isso.

 

Você entendeu as coisas que eu expliquei?

 

Rodou os exemplos?

 

42 minutos atrás, MATHEUSCDN disse:

Eu não escolho isso , o proprio professor pede para executar o arquivo no cmd assim : atividade.exe < isbn.txt 


:) Entenda:

sue professor pede pra executar assim, e o que está escrito lá?

 

Existe um arquivo isbn.txt...

 

E é muito melhor para você escrever um programa que usa o arquivo, porque pode usar arquivos diferentes para testar, sem nenhum esforço. 

 

44 minutos atrás, MATHEUSCDN disse:

Ainda estou iniciando em C, tem muita informação ae que não consigo compreender e por enquanto não estamos sendo ensinados a fazer versões que são mais rápidas e sim versões que executem o que o professor pede

 

@MATHEUSCDNO que eu estou explicando é sobre a versão postada por outro usuário, @Midori, cujo nome está lá e que eu juntei às outras 3 versões e mostrei uma maneira simples de comparar uma com a outra.

 

Não conte muito com alguém te ensinando a "escrever versões mais rápidas na escola. Mas acho que não devia achar que não é hora de aprender, por outro lado.

 

Eu não estou escrevendo explicitamente para  você e esse exercício. É um forum público. Se você pesquisar por essas coisas usando o Google Search o o Bing pode acabar aqui nesse forum. E sua questão é interessante e pode ajudar outras pessoas.

 

Pessoas que estejam escrevendo sobre DV em CPF ou RG ou ISBN, que estejam procurando justamente tornar trechos de código mais rápidos, coisas assim.

 

Quando tenho tempo eu escrevo sobre esses problemas. Só isso.

 

E eu te mostrei como resolver o seu problema, com 3 funções diferentes. Te mostrei argumentos, referências e programas completos.

 

E te expliquei aqui

 

4 horas atrás, arfneto disse:

Use um if, compare o valor e pare quando for esse... E tire os espaços entre as aspas e os zeros a menos que pretenda que o usuário de fato digite assim... Use strcmp() para comparar as strings...

 

Como escrever o tal loop.

 

Não tem muito sentido parar com um certo número se está lendo de um arquivo. Qual o propósito? Vamos supor que o arquivo tenha 500 ISBN. Se você quer tratar só os 4 primeiros então edita o arquivo para colocar um "000000000" na 5a linha? E se quer ler todos e tem 500 vai editar o arquivo para acrescentar uma linha 501 com o tal "000000000" ? Pouco útil. Mas assim é o enunciado. Faça como eu disse, ou te outro modo. MAs faça algo.

 

Programas são instruções detalhadas para chegar a algo.

 

image.png.1fd924e901c0031aadbe67f8f7b628a9.png

 

Onde aqui em seu programa está tentando ler mais que um ISBN?

 

Onde está o conceito de linha?

 

Onde estaria a comparação com o valor final?

 

 

57 minutos atrás, MATHEUSCDN disse:

Ainda estou iniciando em C, tem muita informação ae que não consigo compreender e por enquanto não estamos sendo ensinados a fazer versões que são mais rápidas e sim versões que executem o que o professor pede

Mas obrigado pela ajuda, vou dar uma estudada e achar alguma forma de criar essa repetição

 

Talvez você possa ter uma atitude mais ativa em relação à hora de aprender algo.

 

O forum, como você está tentando, pode ser mesmo uma boa maneira de perguntar. E você nada perguntou sobe o que julgou "muita informação".

 

Sobre a repetição, pode dar olhada aqui mesmo no exemplo que eu te mostrei, certo???

 

    printf("Arquivo de entrada: \"%s\"\n", arquivo);

    FILE* entrada = fopen(arquivo, "r");
    if (entrada == NULL) return -1;
    printf("Aberto \"%s\"\n", arquivo);

    char* p = fgets(linha, sizeof linha, entrada);

    while (p != NULL)
    {
        *(p+9) = 0;
        printf("%s-%c\t%s-%c\t%s-%c\n",
            p, isbn_dv(          &linha[0]),
            p, isbn_dv_oficial(  &linha[0]),
            p, isbn_dv_professor(&linha[0])
        );
        p = fgets(linha, sizeof linha, entrada);
    }
    fclose(entrada);
    return 0;
}

 

Aquela parte onde está o while(0 é o LOOP que consome o arquivo. E eu já te disse duas vezes como comparar com o valor final.  Vamos para 3 vezes:

 

use

 

    strcmp( "000000000", isbn )

 

e se voltar zero é porque é igual....

 

 

Link para o comentário
Compartilhar em outros sites

2 horas atrás, arfneto disse:

@MATHEUSCDNO que eu estou explicando é sobre a versão postada por outro usuário, @Midori, cujo nome está lá e que eu juntei às outras 3 versões e mostrei uma maneira simples de comparar uma com a outra.

 

Não conte muito com alguém te ensinando a "escrever versões mais rápidas na escola. Mas acho que não devia achar que não é hora de aprender, por outro lado.

 

Eu não estou escrevendo explicitamente para  você e esse exercício. É um forum público. Se você pesquisar por essas coisas usando o Google Search o o Bing pode acabar aqui nesse forum. E sua questão é interessante e pode ajudar outras pessoas.

 

Pessoas que estejam escrevendo sobre DV em CPF ou RG ou ISBN, que estejam procurando justamente tornar trechos de código mais rápidos, coisas assim.

 

Quando tenho tempo eu escrevo sobre esses problemas. Só isso.

 

E eu te mostrei como resolver o seu problema, com 3 funções diferentes. Te mostrei argumentos, referências e programas completos.

 

E te expliquei aqui

 

Entendi

 

 

2 horas atrás, arfneto disse:

Como escrever o tal loop.

 

Não tem muito sentido parar com um certo número se está lendo de um arquivo. Qual o propósito? Vamos supor que o arquivo tenha 500 ISBN. Se você quer tratar só os 4 primeiros então edita o arquivo para colocar um "000000000" na 5a linha? E se quer ler todos e tem 500 vai editar o arquivo para acrescentar uma linha 501 com o tal "000000000" ? Pouco útil. Mas assim é o enunciado. Faça como eu disse, ou te outro modo. Mas faça algo.

 

Programas são instruções detalhadas para chegar a algo.

 

image.png.1fd924e901c0031aadbe67f8f7b628a9.png

 

Onde aqui em seu programa está tentando ler mais que um ISBN?

 

Onde está o conceito de linha?

 

Onde estaria a comparação com o valor final?

 

 

Eu fiz uma modificação e adaptei com um dos exemplos que você me mostrou, agora está dessa forma 

 

 

#include <stdio.h>

char isbn_dv(char isbn[9])
{
	
    int s1 = 0;
    int s2 = 0;
    for (int i = 0; i < 9; i++)
        s1 += isbn[i] - '0', s2 += s1;
    int digito = 11 - ((s1+s2) % 11);
    if (digito == 11) return '0';
    if (digito == 10) return 'X';
    return '0' + digito;
	 
}

int main(void){
    char isbn[9];
	
    scanf("%9s", isbn);
    printf("%s-%c", isbn, isbn_dv(isbn));
	
    return 0;
}

 

2 horas atrás, arfneto disse:

Talvez você possa ter uma atitude mais ativa em relação à hora de aprender algo.

 

O forum, como você está tentando, pode ser mesmo uma boa maneira de perguntar. E você nada perguntou sobe o que julgou "muita informação".

 

Sobre a repetição, pode dar olhada aqui mesmo no exemplo que eu te mostrei, certo???

 

Estou sempre buscando aprender coisas novas e vi muitas coisas interessantes as quais você me mostrou, porém como eu disse tem muita coisa que eu ainda não entendo pois meu ensino é bem básico. 

2 horas atrás, arfneto disse:

Aquela parte onde está o while(0 é o LOOP que consome o arquivo. E eu já te disse duas vezes como comparar com o valor final.  Vamos para 3 vezes:

 

use

 

    strcmp( "000000000", isbn )

 

e se voltar zero é porque é igual....

 utilizei isso que você falou mas não deu certo , poderia me explicar o porque ? 

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

char isbn_dv(char isbn[9])
{
	scanf("%9s", isbn);
    int s1 = 0;
    int s2 = 0;
    int rep;
  	
	rep = strcmp ("000000000",isbn);
	do {
    for (int i = 0; i < 9; i++)
        s1 += isbn[i] - '0', s2 += s1;
    int digito = 11 - ((s1+s2) % 11);
    if (digito == 11) return '0';
    if (digito == 10) return 'X';
    return '0' + digito;
	}
	while (rep != 0);

}

int main(void){
    char isbn[9]; 
    printf("%s-%c", isbn, isbn_dv(isbn));
	
    return 0;
}

 

Link para o comentário
Compartilhar em outros sites

14 horas atrás, MATHEUSCDN disse:

utilizei isso que você falou mas não deu certo , poderia me explicar o porque ? 

 

Pois é.

 

Só que não utilizou isso "de que eu falei".

 

Como te disse, um programa de computador é uma lista absolutamente detalhada de instruções para fazer algo

 

Sobre o trecho abaixo, que eu vou postar pela 3a vez:

 

printf("Arquivo de entrada: \"%s\"\n", arquivo);

    FILE* entrada = fopen(arquivo, "r");
    if (entrada == NULL) return -1;
    printf("Aberto \"%s\"\n", arquivo);

    char* p = fgets(linha, sizeof linha, entrada);

    while (p != NULL)
    {
        *(p+9) = 0;
        printf("%s-%c\t%s-%c\t%s-%c\n",
            p, isbn_dv(          &linha[0]),
            p, isbn_dv_oficial(  &linha[0]),
            p, isbn_dv_professor(&linha[0])
        );
        p = fgets(linha, sizeof linha, entrada);
    }
    fclose(entrada);
    return 0;
}

 

Isso acima abre o arquivo, le linha a linha até acabar o arquivo, chama as 3 funções e mostra os DV.

 

Qual a diferença para o que quer fazer?

 

Vai ler até o ISBN marcador de fim, o tal "000000000" ao invés do óbvio que seria ler até o fim do arquivo.

 

Então:

  • porque não roda esse exemplo na sua máquina até entender como funciona? Eu postei até o arquivo de entrada e também a saída.
     
  • Depois de entender apenas deixa de chamar as outras duas funções

 

Acha que não é só mudar a condição do loop? É. É só isso. É só uma condição.

 

Sobre seu programa

 

14 horas atrás, MATHEUSCDN disse:
	rep = strcmp ("000000000",isbn);
	do {
    for (int i = 0; i < 9; i++)
        s1 += isbn[i] - '0', s2 += s1;
    int digito = 11 - ((s1+s2) % 11);
    if (digito == 11) return '0';
    if (digito == 10) return 'X';
    return '0' + digito;
	}
	while (rep != 0);
  • Você colocou o teste DENTRO da função, apesar de ter ao menos dois programas exemplo completos que eu te mostrei. E esses exemplos mostrarem que o loop é o que controla a chamada da função. Qual o sentido disso? Quando isbn for "000000000" não é pra chamar a função, é para encerrar o programa....
     
  • A função recebe 9 dígitos e retorna o DV
     
  • Você trocou o while() por um do(). Porque? Código é uma coisa objetiva, uma programação. Pode usar while(), do(), for() ou um goto e um label. Vai funcionar. Apenas programe a ação e os testes direito. Porque mudou?

 

Sobre o redirecionamento da entrada padrão

 

Você tem um livro? Seu curso adota um livro-texto? Tem uma apostila?

 

Em C 3 arquivos sempre estão abertos para o programa: stdin, o teclado, stdout, a saída por exemplo de puts() e printf(), e stderr, a saída padrão de erro.

 

Uso é o básico, fundamental, e deveria estar na primeira aula de C junto com o lance dos argumentos.

 

Em geral o primeiro programa que TODO MUNDO vê em C e qualquer linguagem de programação  é o tal "hello world". Em C algo assim:

 

int main( int argc, char** argv)
{
    printf("Hello World\n");
    return 0;
}

 

E já tem um arquivo aberto...

 

E a partir daí começa o livro ou o curso. Nunca fiz um curso de C, então não tenho essa memória. Mas já estudei outras linguagens e foi assim. E já vi uns livros.

 

 

Qual o tipo da entrada padrão?

 

Pois é: seu professor talvez tenha ensinado, seu livro talvez explique isso: 
 

Citação

        stdin é FILE*

 

 

Mais um exemplo

 

    FILE* ent;
    if (argc > 1)
    {  // veio algo entao e o nome do arquivo
        ent = fopen(argv[1], "r");
        if (ent == NULL) return -1;
    }
    else
        ent = stdin;  // não veio o arquivo...

 

Como stdtin está sempre aberto isso sempre funciona...

 

E é a solução para o seu problema...

 

Link para o comentário
Compartilhar em outros sites

1 hora atrás, arfneto disse:

porque não roda esse exemplo na sua máquina até entender como funciona? Eu postei até o arquivo de entrada e também a saída.

 

 

Já rodei.

1 hora atrás, arfneto disse:
  • Você colocou o teste DENTRO da função, apesar de ter ao menos dois programas exemplo completos que eu te mostrei. E esses exemplos mostrarem que o loop é o que controla a chamada da função. Qual o sentido disso? Quando isbn for "000000000" não é pra chamar a função, é para encerrar o programa....
     
  • A função recebe 9 dígitos e retorna o DV
     
  • Você trocou o while() por um do(). Porque? Código é uma coisa objetiva, uma programação. Pode usar while(), do(), for() ou um goto e um label. Vai funcionar. Apenas programe a ação e os testes direito. Porque mudou?

 

Então é so colocar a estrutura de repetição no int main ?

1 hora atrás, arfneto disse:
 FILE* ent;
    if (argc > 1)
    {  // veio algo entao e o nome do arquivo
        ent = fopen(argv[1], "r");
        if (ent == NULL) return -1;
    }
    else
        ent = stdin;  // não veio o arquivo...

 

Mas nesse exemplo ele abre o arquivo e verifica ate a última linha, correto ? Não posso fazer dessa forma pois não foi assim que o professor exigiu e eu nem cheguei a ver isso em aula ainda . A única e exclusiva coisa que eu preciso fazer é o programa para de rodar quando o usuario digitar 000000000, não importando se tiver mais números depois. A única coisa que foi dita é que tenho que fazer de uma forma, mas não foi dita como. Se eu tenho que colocar fora da função , então como eu poderia executar essa repetição até o usuario digitar 000000000 ? É isso que não estou entendendo !

Agora fiz o codigo dessa forma mas fica dizendo que o inicializador de string para array de char é muito longo 

 

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

char isbn_dv(char isbn[9])
{
	scanf("%9s", isbn);
    int s1 = 0;
    int s2 = 0;
	
    for (int i = 0; i < 9; i++)
        s1 += isbn[i] - '0', s2 += s1;
    int digito = 11 - ((s1+s2) % 11);
    if (digito == 11) return '0';
    if (digito == 10) return 'X';
    return '0' + digito;
	
	

}

int main(void)
{ 
    char isbn[9];
    char rep[9] = {"000000000"};
    int comp;
    comp = strcmp(rep,isbn);
    while (comp !=0){
    printf("%s-%c", isbn, isbn_dv(isbn));
    }
    return 0;
}

Ele só rodou quando eu coloquei 8 zeros em rep, mas ae ele entrou em um loop infinito

Link para o comentário
Compartilhar em outros sites

3 horas atrás, MATHEUSCDN disse:

Não posso fazer dessa forma pois não foi assim que o professor exigiu e eu nem cheguei a ver isso em aula ainda

 

Já que falei sobe isso, e é só minha opinião. Não me leve a mal, mas isso é de ensino primário, quando a professora explicava como segurar a tesoura na aula de artes, como segurar a caneta pra letra não sair tremida, coisas assim.

 

Isso não se aplica a uma formação acadêmica de nível superior. E nem a uma formação profissional.

 

Ninguém vai te culpar por ler a página seguinte do livro que seu curso adota, se é que tem um.  Eu até te perguntei.

 

3 horas atrás, MATHEUSCDN disse:

Mas nesse exemplo ele abre o arquivo e verifica ate a última linha, correto ?

 

Leia o código. Esse trecho só abre o arquivo. E te expliquei antes sobre isso, os 3 arquivos abertos, algo que você deveria ter aprendido na primeira aula de C   entrada padrão, saída padrão e saída padrão de erro.

 

3 horas atrás, MATHEUSCDN disse:

Se eu tenho que colocar fora da função , então como eu poderia executar essa repetição até o usuario digitar 000000000 ? É isso que não estou entendendo !

 

 

Como te disse mais de uma vez, apenas pegue o exemplo que te mostrei e se rodou mesmo a essa altura já sabe que funciona para um mihão de ISBN e 3 funções ao mesmo tempo, e altere para que funcione para 1 função e meia dúzia de ISBN.

 

Como eu também disse, apenas altere a condição de saída.

 

Viu isso no post anterior?:

image.png.b199d34895a6a607bb63edcfcf936fbb.png

 

pois é. 

 

Eu perguntei porque você trocou de lugar o loop, você não respondeu.

 

Eu perguntei porque trocou o comando de while() para do() e você não respondeu.

Link para o comentário
Compartilhar em outros sites

10 minutos atrás, arfneto disse:

Eu perguntei porque você trocou de lugar o loop, você não respondeu.

 

Eu perguntei porque trocou o comando de while() para do() e você não respondeu.

Troquei pra testar se ia dar certa mas não deu.

 

E usei o do while em vez de apenas while porque queria que ele rodasse a primeira linha sem consultar e depois consultava as linhas restantes

Link para o comentário
Compartilhar em outros sites

5 minutos atrás, MATHEUSCDN disse:

Troquei pra testar se ia dar certa mas não deu

 

Mesmo um teste tem que ter um motivo. Testar só para ver se dá certo em geral só é perda de tempo.

 

6 minutos atrás, MATHEUSCDN disse:

E usei o do while em vez de apenas while porque queria que ele rodasse a primeira linha sem consultar e depois consultava as linhas restantes

 

Não faz sentido, e por isso deu errado. Pode usar do() mas vai acabar testando duas vezes a mesma coisa. Pode usar for ou goto. Não faz diferença. Acho que o mais esperto é fazer como eu mostrei.

 

Só que aparentemente você não prestou atenção ao rodar o programa, como diz que rodou...

 

O trecho do exemplo, pela 4a vez:

 

printf("Arquivo de entrada: \"%s\"\n", arquivo);

    FILE* entrada = fopen(arquivo, "r");
    if (entrada == NULL) return -1;
    printf("Aberto \"%s\"\n", arquivo);

    char* p = fgets(linha, sizeof linha, entrada);

    while (p != NULL)
    {
        *(p+9) = 0;
        printf("%s-%c\t%s-%c\t%s-%c\n",
            p, isbn_dv(          &linha[0]),
            p, isbn_dv_oficial(  &linha[0]),
            p, isbn_dv_professor(&linha[0])
        );
        p = fgets(linha, sizeof linha, entrada);
    }
    fclose(entrada);
    return 0;
}

 

Entenda:

 

primeiro lê

depois testa

entra no loop 

no final do loop lê outra linha

 

...

 

Se mudar isso tem que mudar a lógica toda e não só trocar o comando.

porque não tenta escrever um programa pequeno só com o loop, usando o exemplo?

 

Link para o comentário
Compartilhar em outros sites

3 minutos atrás, arfneto disse:

Se mudar isso tem que mudar a lógica toda e não só trocar o comando.

porque não tenta escrever um programa pequeno só com o loop, usando o exemplo?

Porque eu só queria fazer a repetição da forma que estou tentando, usando o while, como mostrei acima. No seu método pelo o que entendi ele já abre o arquivo automaticamente e eu não quero isso pois não é o que o professor pede, pede apenas que abra na hora de executar usando um atividade.exe < isbn.txt. Qualquer coisa que é fora disso eu não posso usar.

 

Apenas quero uma solução para esse meu problema envolvendo o while 

3 horas atrás, MATHEUSCDN disse:
int main(void)
{ 
    char isbn[9];
    char rep[9] = {"000000000"};
    int comp;
    comp = strcmp(rep,isbn);
    while (comp !=0){
    printf("%s-%c", isbn, isbn_dv(isbn));
    }
    return 0;
}

 

Link para o comentário
Compartilhar em outros sites

Talvez você precise mais detalhista com essas coisas...

 

Programação é assim. Em especial em C. Essa linguagem não foi escrita para aprender a programar, então não ajuda muito...

 

Não escreva linhas para testar apenas. Isso como escreveu

 

int main(void)
{ 
    char isbn[9];
    char rep[9] = {"000000000"};
    int comp;
    comp = strcmp(rep,isbn);
    while (comp !=0){
    printf("%s-%c", isbn, isbn_dv(isbn));
    }
    return 0;
}

 

É (muito) diferente de

 

    printf("Arquivo de entrada: \"%s\"\n", arquivo);

    FILE* entrada = fopen(arquivo, "r");
    if (entrada == NULL) return -1;
    printf("Aberto \"%s\"\n", arquivo);

    char* p = fgets(linha, sizeof linha, entrada);

    while (p != NULL)
    {
        *(p+9) = 0;
        printf("%s-%c\t%s-%c\t%s-%c\n",
            p, isbn_dv(          &linha[0]),
            p, isbn_dv_oficial(  &linha[0]),
            p, isbn_dv_professor(&linha[0])
        );
        p = fgets(linha, sizeof linha, entrada);
    }
    fclose(entrada);

 

E a essa altura sabe que o primeiro não funciona e o segundo sim. Porque não parte do segundo? A função que está usando é uma das 3 que escrevi para te mostrar. 

 

Você tem um livro-texto? uma apostila? Eu perguntei e não respondeu.

 

Do seu programa:

 

    char isbn[9];
    char rep[9] = {"000000000"};
    int comp;
    comp = strcmp(rep,isbn);

 

isbn é char[9]. Não é uma string e não serve para comparar com rep[9] que por sinal nem deve compilar.

 

warning C4295: 'rep': array is too small to include a terminating null character

 

Isso quer dizer que precisa corrigir ao menos duas coisas aí.

 

Como está o programa TODO que está usando? Poste o código todo, é pequeno. Ajude os outros a ajudarem você.

 

E no caso da comparação, notou que não leu nada ainda?

 

Depois de corrigir esses 2 problemas de que falei vai ver que de nada adiantou, porque está testanto antes de ler... que acha que vai ter em isbn[]?

 

Mais uma vez sugiro que compare com um dos programas que te mostrei...

 

Notou que no programa inteiro não lê a entrada?

 

31 minutos atrás, MATHEUSCDN disse:

No seu método pelo o que entendi ele já abre o arquivo automaticamente e eu não quero isso pois não é o que o professor pede, pede apenas que abra na hora de executar usando um atividade.exe < isbn.txt. Qualquer coisa que é fora disso eu não posso usar.

 

Como já te disse, essa não é uma boa atitude de quem está aprendendo algo. "isso não poso usar"

 

Como te expliquei claramente, 3 arquivos são apresentados abertos para todo programa em C. Pela 3a vez vou listar os 3: stdin, stdout e stderr. 

 

33 minutos atrás, MATHEUSCDN disse:

pede apenas que abra na hora de executar usando um atividade.exe < isbn.txt

 

?  Como assim? Notou que seu programa não abre um único arquivo, já que não tem um fopen()? 

 

34 minutos atrás, MATHEUSCDN disse:

Qualquer coisa que é fora disso eu não posso usar.

 

De novo isso? Para sua sorte não é um estágio ou um emprego.

 

Apenas peque o programa que mostrei e junte as coisas que te expliquei.

 

Continua com o scanf() dentro da função? Poste o programa completo

Link para o comentário
Compartilhar em outros sites

9 minutos atrás, arfneto disse:

?  Como assim? Notou que seu programa não abre um único arquivo, já que não tem um fopen()? 

No cmd tem essa função que você digita isso e ele ler tudo que está no arquivo txt e leva para o programa

 

11 minutos atrás, arfneto disse:

Continua com o scanf() dentro da função? Poste o programa completo

 

 

Aqui o programa completo

 

4 horas atrás, MATHEUSCDN disse:
#include <stdio.h>
#include <string.h>

char isbn_dv(char isbn[9])
{
    int s1 = 0;
    int s2 = 0;
	
    for (int i = 0; i < 9; i++)
        s1 += isbn[i] - '0', s2 += s1;
    int digito = 11 - ((s1+s2) % 11);
    if (digito == 11) return '0';
    if (digito == 10) return 'X';
    return '0' + digito;
	
	

}

int main(void)
{ 
    char isbn[9];
    char rep[9] = {"000000000"};
    int comp;
    scanf("%9s", isbn);
    comp = strcmp(rep,isbn);
    while (comp !=0){
    printf("%s-%c", isbn, isbn_dv(isbn));
    }
    return 0;
}

 

 

Link para o comentário
Compartilhar em outros sites

3 minutos atrás, MATHEUSCDN disse:

No cmd tem essa função que você digita isso e ele ler tudo que está no arquivo txt e leva para o programa

 

Não, não tem. Seu programa tem que ler as coisas.

 

Você tem ou não tem um livro-texto? Seu curso não adota um? Você tem uma apostila ao menos?

 

Sobre o programa como está agora que mostrou

 

Nem corrigiu os erros que te expliquei acima. Acha que estou errado? :( Não, não estou. Use -Wall em seu compilador como expliquei antes

 

Em 04/09/2021 às 15:36, arfneto disse:

Quanto ao que fazer, está escrito na tela de seu micro... use por exemplo -std=c17 nas opções do compilador. E aproveite e acrescente -Wall para mostrar os avisos todos...

 

 

 

 

Link para o comentário
Compartilhar em outros sites

agora, arfneto disse:

Você tem ou não tem um livro-texto? Seu curso não adota um? Você tem uma apostila ao menos?

Tenho 

1 minuto atrás, arfneto disse:

Nem corrigiu os erros que te expliquei acima.

É que eu não estou entendendo, você fala apenas pra eu usar da forma que você mostrou e falou que está errado o local do scanf, mas eu não sei onde devo colocar então. estou achando é que vou desistir desse código pois já está me dando dor de cabeça, tem dois dias que procuro uma forma de corrigi-lo e não acho, Se eu usar dessa forma que foi mostrada o professor me pergunta como eu sei disso, como eu fiz isso e eu não vou saber explicar porque eu não entendo.

Muito obrigado por toda a sua ajuda e por ter dedicado o seu tempo ! Mas eu infelizmente não estou conseguindo entender.

 

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!