Ir ao conteúdo
  • Cadastre-se

C++ funções e matrizes ISBN


MATHEUSCDN
Ir à solução Resolvido por arfneto,

Posts recomendados

36 minutos atrás, MATHEUSCDN disse:

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

 

@MATHEUSCDNporque não faz o simples e pergunta sobre o que você não entende?

Se aí alguém te explica e você entende, então se alguém vier depois a te perguntar você sabe e, mais ainda, você afinal sabe é isso o que importa afinal, não é?

 

E é mais produtivo do que tentar comandos mais ou menos a olho par ver se dá certo...

 

Eu te expliquei o que está errado

 

o que você fez a respeito do rep[9]? Entendeu? Não perguntou nada. "000000000" é char[10] não cabe em 9 porque tem um zero no fim, como TODA string em C.

 

Por outro lado char isbn[9] não é uma string PELO MESMO MOTIVO: tinha que ter um 0 no fim e nem cabe.

 

E você não perguntou nada. Te falei 3 vezes disso.

 

Eu te mostrei os exemplos e você não fez uma única pergunta. Te mostrei onde mudar e você não mudou nada como eu falei. 

 

Nem sempre alguém vai ter o tempo e a paciência que eu tenho para seguir nisso. Eu te mostrei o loop e onde mudar. 4 vezes. Não perguntou nada. Nem tentou mudar lá. E removeu as leituras sem colocar outras  no lugar.

 

Era assim

 

    while (p != NULL)

 

para ler até o fim do arquivo. Mas pode ter que parar antes se ler o tal 000000000. Então onde será quie tem que mudar? 🤔

 

Na condição, claro. E como mudar? será a tal comparação de strings? Pois é...
 

    while ( (p != NULL) && (strcmp(linha,final) != 0) )

 

Não seria isso? Enquanto o arquivo não acabar e o valor lido não for o indicador de final?

 

Acha que funciona? claro que funciona.

 

Desde que linha e final sejam strings.

 

E entenda que pode e deve declarar assim:

 

    char  final[] = "000000000";

 

E o compilador conta o tamanho para você e não teria criado o erro que você nem corrigiu ainda.

 

Qual é o seu livro-texto?

 

 

 

Link para o comentário
Compartilhar em outros sites

6 minutos atrás, arfneto disse:

Qual é o seu livro-texto?

É o livro de deitel

 

7 minutos atrás, arfneto disse:

@MATHEUSCDNporque não faz o simples e pergunta sobre o que você não entende?

Se aí alguém te explica e você entende, então se alguém vier depois a te perguntar você sabe e, mais ainda, você afinal sabe é isso o que importa afinal, não é?

 

E é mais produtivo do que tentar comandos mais ou menos a olho par ver se dá certo...

 

Eu te expliquei o que está errado

 

o que você fez a respeito do rep[9]? Entendeu? Não perguntou nada. "000000000" é char[10] não cabe em 9 porque tem um zero no fim, como TODA string em C.

 

Por outro lado char isbn[9] não é uma string PELO MESMO MOTIVO: tinha que ter um 0 no fim e nem cabe.

 

E você não perguntou nada. Te falei 3 vezes disso.

 

Eu te mostrei os exemplos e você não fez uma única pergunta. Te mostrei onde mudar e você não mudou nada como eu falei. 

 

Nem sempre alguém vai ter o tempo e a paciência que eu tenho para seguir nisso. Eu te mostrei o loop e onde mudar. 4 vezes. Não perguntou nada. Nem tentou mudar lá. E removeu as leituras sem colocar outras  no lugar.

 

Era assim

 

    while (p != NULL)

 

para ler até o fim do arquivo. Mas pode ter que parar antes se ler o tal 000000000. Então onde será quie tem que mudar? 🤔

 

Na condição, claro. E como mudar? será a tal comparação de strings? Pois é...
 

    while ( (p != NULL) && (strcmp(linha,final) != 0) )

 

Não seria isso? Enquanto o arquivo não acabar e o valor lido não for o indicador de final?

 

Acha que funciona? claro que funciona.

 

Desde que linha e final sejam strings.

 

E entenda que pode e deve declarar assim:

 

    char  final[] = "000000000";

 

E o compilador conta o tamanho para você e não teria criado o erro que você nem corrigiu ainda.

 

Eu meio que entendo sua solução mas não sei como atribuir ela ao meu programa, você poderia usar meu código e adaptar a sua solução nele ? Assim acho q eu entenderia um pouco melhor todos os erros .

#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;
}

 

Link para o comentário
Compartilhar em outros sites

1 minuto atrás, MATHEUSCDN disse:

Eu meio que entendo sua solução mas não sei como atribuir ela ao meu programa, você poderia usar meu código e adaptar a sua solução nele ? Assim acho q eu entenderia um pouco melhor todos os erros

 

A função que está usando é uma das 3 que eu escrevi, agora que desistiu de colocar uma chamada a scanf() dentro dela.

 

E o programa principal eu já te mostrei todinho. 

 

Isso que postou agora tem só 4 linhas:

 

 char isbn[9];
	
    scanf("%9s", isbn);
    printf("%s-%c", isbn, isbn_dv(isbn));
	
    return 0;

 

E nenhuma leitura, por exemplo. e sumiu o indicador de final. E o loop.

 

5 minutos atrás, MATHEUSCDN disse:

Eu meio que entendo sua solução mas não sei como atribuir ela ao meu programa

 

porque "meio que não pergunta" algo objetivo?

Esse livro tem um nome? Você tem o livro? Não conheço um Deitel.

Link para o comentário
Compartilhar em outros sites

1 minuto atrás, arfneto disse:

A função que está usando é uma das 3 que eu escrevi

Sim 

 

1 minuto atrás, arfneto disse:

E o programa principal eu já te mostrei todinho.

 

 

Se for aquele "programa completo" ele não rodou

 

2 minutos atrás, arfneto disse:

Isso que postou agora tem só 4 linhas:

 

Então deve ser bug do site, porque eu coloquei o codigo inteiro

 

image.thumb.png.64e9bc464f83f2a1212702fcdecc94fb.png

 

Link para o comentário
Compartilhar em outros sites

?? De onde tirou isso?

 

E está usando um newfile.cpp? Sério? Isso é para C++. Uma linguagem totalmente diferente.

 

Você está programando em C.

 

Use um compilador C. Faça o simples.

 

Esse é o loop do exemplo. E funciona perfeitamente, e note que você disse que tinha rodado em sua máquina...

 

    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 condição nova de final eu te mostrei há pouco.

 

 

Link para o comentário
Compartilhar em outros sites

8 minutos atrás, MATHEUSCDN disse:

O que rodei foi esse que usei pro meu código, pelo visto você de referiu ao código completo e este não rodei 

 

Claro que eu me referia ta todos os exemplos completos que te mostrei.

 

Deve imaginar que podiam ser úteis, já que fazem o que você precisa.

Corrigiu os erros afinal? Mudou o tipo do arquivo? Entende que é outra linguagem?

Link para o comentário
Compartilhar em outros sites

  • Solução

image.png.4fa609085c6a6f36063ca6023aa8fa79.png

 

Eu não entendo o que está tentando fazer.

 

Essa tabela aí fui eu que escrevi. O objetivo disso era calcular quando tempo cada uma dessas funções que eu escrevi, e mais essa outro que o usuário @Midoriescreveu, levam par calcular um certo n'mero de DV. E mostrar o resultado, uma tabela. Na posição 1 da tabela está o tempo com 0, que vai ser preenchido com os tempos calculados. E o  valor será impresso foi no tópico #12 e a saída do programa era essa:
 

    [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

 

O programa não lê nada. Apenas roda as 4 funções para uma mesma série de 2 milhões de ISBN e mede o tempo. Leia o tópico #12.  Era para testar 4 funções de cálculo.

 

Nada tem a ver com seu problema original, que é ler uns números de ISBN, e calcular o DV usando uma função, que pode por exemplo ser uma das que eu escrevi ou essa quarta aí. 

 

Eu expliquei poruqe eu estaa escrevendo aquilo.

 

Assim me vem a pergunta:

 

Porque está usando essa estrutura no meio disso? 

 

E onde está o resto do código? E porque mudou de IDE no meio disso tudo?

 

No tópico #5, https://www.clubedohardware.com.br/forums/topic/1561085-funções-e-matrizes-isbn/?tab=comments#comment-8259805 eu te mostrei esse programa, de onde tirou a função que está usando

 

 

/*
* 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;
};

 

É um programa completo. Te mostrei o arquivo de saída e o de entrada...

 

013162959X
0387901442
3540901442
0201179288

 

E a saída
 

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>

 

Onde cada coluna é o resultado de uma função.

 

O que falta aqui para o seu caso?

 

Tirar duas funções e colocar o lance do loop. Eu já te mostrei umas 4 vezes maneiras de fazer isso, e te mostrei em vários casos onde você está errando.

 

Já sabe o que mudar no loop. Eu te mostrei acima. Já tem a função. Eu escrevi 3. 

 

Sequer precisa de um IDE para um programa de 50 linhas. E que já está pronto. Use os exemplos.

 

Juntando o que eu te disse o dia todo

 

char isbn_dv(char[9]);            // a funcao

int main(int argc, char** argv)
{
    char       arquivo[30] = {0};
    char       linha[80];

    FILE* entrada = stdin;
    if (argc > 1)  // veio algo entao e o nome do arquivo
    {
        strcpy(arquivo, argv[1]);
        printf("Arquivo de entrada: \"%s\"\n", arquivo);
        entrada = fopen(arquivo, "r");
        if (entrada == NULL) return -1;
        printf("Aberto \"%s\"\n", arquivo);
    };

    char  final[] = "000000000";
    linha[9]     = 0; // tem que ser uma string afinal
    char* p = fgets(linha, sizeof linha, entrada);
    while ( (p != NULL) && (strcmp(linha,final) != 0) )
    {
        linha[9] = 0;
        printf("%s-%c\n", p, isbn_dv(&linha[0]));
        p = fgets(linha, sizeof linha, entrada);
        linha[9] = 0;
    }
    fclose(entrada);
    return 0;
}
// fim

 

É só isso.  E tem a vantagem de funcionar com qualquer arquivo na linha de comando ou lendo os dados do teclado, como seu professor folclórico recomenda.  mesmo programa.

 

Veja (em Windows)

 

CH> isbn.txt | outro-0905
013162959-X
038790144-2

CH> outro-0905 < isbn.txt
013162959-X
038790144-2
                         
CH>outro-0905 isbn.txt
Arquivo de entrada: "isbn.txt"
Aberto "isbn.txt"
013162959-X
038790144-2

CH> type isbn.txt
013162959X
0387901442
0000000000
3540901442
0201179288
CH>

 

Link para o comentário
Compartilhar em outros sites

 

Consegui rodar !!!!!!!!!

 

image.png.d0fdbd15b137ed88907905039a3f612c.png

 

Muito obrigado pela sua paciência , o problema estava nas bibliotecas, eu estava utilizando apenas stdio.h e string.h , quando usei stdlib.h o codigo rodou !

o código definitivo é esse 

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

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

int main(int argc, char** argv)
{
    char       arquivo[30] = {0};
    char       linha[80];

    FILE* entrada = stdin;
    if (argc > 1)  // veio algo entao e o nome do arquivo
    {
        strcpy(arquivo, argv[1]);
        printf("Arquivo de entrada: \"%s\"\n", arquivo);
        entrada = fopen(arquivo, "r");
        if (entrada == NULL) return -1;
        printf("Aberto \"%s\"\n", arquivo);
    };

    char  final[] = "000000000";
    linha[9]     = 0; // tem que ser uma string afinal
    char* p = fgets(linha, sizeof linha, entrada);
    while ( (p != NULL) && (strcmp(linha,final) != 0) )
    {
        linha[9] = 0;
        printf("%s-%c\n", p, isbn_dv(&linha[0]));
        p = fgets(linha, sizeof linha, entrada);
        linha[9] = 0;
    }
    fclose(entrada);
    return 0;
}

 

Mas tem algumas coisas que eu queria entender...

 

int main(int argc, char** argv)
{
    char       arquivo[30] = {0};
    char       linha[80];

    FILE* entrada = stdin;
    if (argc > 1)  // veio algo entao e o nome do arquivo
    {
        strcpy(arquivo, argv[1]);
        printf("Arquivo de entrada: \"%s\"\n", arquivo);
        entrada = fopen(arquivo, "r");
        if (entrada == NULL) return -1;
        printf("Aberto \"%s\"\n", arquivo);
    };

 

O que está acontecendo nessa parte do código ? Qual a função de argc e argv ? E a função desse FILE ? Tem muita coisa ai que eu nunca vi e por mais que o código tenha rodado eu queria entender como essa parte funciona 

 

 

 

 

E nesta parte aqui você transformou P em um ponteiro e mediu o tamanho de linha ? 

 

A parte da comparação eu entendi que se o valor de P for nulo e a comparação entre linha e final for diferente de 0 ele entra na condição 

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

 

Link para o comentário
Compartilhar em outros sites

2 horas atrás, MATHEUSCDN disse:

Muito obrigado pela sua paciência , o problema estava nas bibliotecas, eu estava utilizando apenas stdio.h e string.h , quando usei stdlib.h o codigo rodou !

 

Está errado. O problema não estava nas bibliotecas.

 

Não deveria ficar surpreso por o código rodar. É um exemplo. E já tinha a entrada e a saída dele em umas 3 versões. Trata-se apenas de copiar e compilar direito.

 

E pode ser algo simples como

 

CH>gcc -o pgm -Wall -std=c17 outro.c
CH>dir pgm.*
 O volume na unidade C não tem nome.
 O Número de Série do Volume é 7E52-1BF2

 Pasta de C:\src

06/09/2021  23:45           292.107 pgm.exe
               1 arquivo(s)        292.107 bytes
               0 pasta(s)   35.486.453.760 bytes disponíveis

CH>

 

Não precisa de um IDE para isso. Estou supondo que seu IDE usa gcc para compilar seus programas, claro. 

 

Mas não faz diferença: apenas precisa usar as opções de seu compilador. Se usa o compilador da Microsoft, como eu em geral uso aqui no forum, usaria para criar o pgm.exe a partir do exemplo outro.c:

 

CH>CL  /W4 /std:c17 /D_CRT_SECURE_NO_WARNINGS /Fe:pgm outro.c

 

E não precisa de stdlib nesse programa. Pode tirar e ver que não faz diferença. Precisa de string.h por causa de strcmp() por exemplo. E stdio.h por causa de printf() por exemplo. De onde tirou essa conclusão sobre essa stdlib.h?

 

E já te disse umas vezes que PRECISA mudar o tipo do arquivo para C. Esse não é um programa em C++. É importante.

 

Deve usar o compilador certo ou seus próximos programas vão ser um inferno pra compilar de novo. Use a extensão .c. Atente para tudo o que eu já te expliquei, ou esqueça tudo e faça apenas isso de usar .c e já terá ganho algo para os próximos programas.

 

2 horas atrás, MATHEUSCDN disse:

O que está acontecendo nessa parte do código ? Qual a função de argc e argv ? E a função desse FILE ? Tem muita coisa ai que eu nunca vi e por mais que o código tenha rodado eu queria entender como essa parte funciona 

 

Eu te mostrei o exemplo! Mesmo assim não entendeu?

 

E o livro que diz que tem ? Qual o nome?

 

Repetindo o que escrevi há pouco

 

CH> isbn.txt | outro-0905
013162959-X
038790144-2

CH> outro-0905 < isbn.txt
013162959-X
038790144-2
                         
CH>outro-0905 isbn.txt
Arquivo de entrada: "isbn.txt"
Aberto "isbn.txt"
013162959-X
038790144-2

CH> type isbn.txt
013162959X
0387901442
0000000000
3540901442
0201179288
CH>

 

Essa é a saída do programa, de 3 modos. Rodou isso em sua máquina? Dos 3 modos? Teve a curiosidade de comparar a diferença?

 

Como acha que o programa achou o nome do arquivo?  Viu essas linhas
 

        strcpy(arquivo, argv[1]);
        printf("Arquivo de entrada: \"%s\"\n", arquivo);
        entrada = fopen(arquivo, "r");

 

 

é como lê o nome do arquivo. Os argumentos da linha de comando. É o básico. TODO programa em C recebe isso.

 

Como se chama seu livro-texto?

 

FILE é o tipo do arquivo. Como te expliquei um certo número de vezes todo programa C tem 3 arquivos sempre abertos: stdin, stdout e stderr. Veja nos tópicos anteriores.

 

Os outros arquivos você abre, usando claro o tal fopen() -- de file open. Como está nos exemplos todos.

 

E como esses arquivos sempre abertos são, claro, arquivos...  também são FILE*, ponteiros para arquivo. E assim pode escrever 

 

        FILE* entrada = stdin;

 

e testar se o usuário deu um nome de arquivo como o primeiro parâmetro. Se ele deu usa esse. Se não deu lê do teclado. O simples.

 

Assim o programa funciona de qualquer jeito. Essa ideia de redirecionamento é bobagem. Em geral não se quer fazer isso. Mas se sair de graça, como nesse exemplo, mal não faz.

 

2 horas atrás, MATHEUSCDN disse:

E nesta parte aqui você transformou P em um ponteiro e mediu o tamanho de linha ?

 

 

Não. Leia no seu livro, ou no manual: fgets() retorna um ponteiro. Nesse programa não se usa o tamanho da linha. O enunciado é claro no sentido de que tem um ISBN por linha. 9 dígitos. O resto não importa. O tamanho da linha não imorta. Eu usei 10 porque é mais esperto já colocar o ISBN de verdade porque assim já tem como conferir ;) É claro que se ao rodar o programa você olha o arquivo de entrada e já confere os dígitos está sendo mais esperto do que mantendo uma lista em outro lugar, ou quem sabe fazendo as contas a mão.  Mas só importam claro os primeiros 9 dígitos.

 

O lance de fgets() é o seguinte: se a função não ler nada ela não faz nada. A variável fica igualzinha. E seu programa entra em loop... Muitos e muitos programas de iniciantes --- e alguns de profissionais --- entram em loop por causa disso. É tão ingênuo quanto não estar o retorno de scanf(), que você não testou em lugar nenhum. Mas fgets() retorna o endereço de linha, ou NULL. Usando como eu mostrei resolve o problema.

 

3 horas atrás, MATHEUSCDN disse:

A parte da comparação eu entendi que se o valor de P for nulo e a comparação entre linha e final for diferente de 0 ele entra na condição

 

Entendeu errado. 

 

A condição: 
 

    while ( (p != NULL) && (strcmp(linha,final) != 0) )

 

Se o valor de p não for nulo então leu algo. E aí, e somente aí, faz a segunda parte e vê se o que leu não é o final. E isso é o AND, &&

 

E se der verdadeiro então calcula o DV e lê o próximo ISBN.

 

Como eu expliquei no parágrafo acima, se não ler nada fgets() não muda nada em linha e por isso não deve usar linha nos testes.

 

E se não ler nada não pode comparar porque vai ter o mesmo valor de antes, o ISBN anterior.

 

Ninguém garante que tem um "000000000" na entrada, afinal.

 

 

 

 

Link para o comentário
Compartilhar em outros sites

17 minutos atrás, arfneto disse:

FILE é o tipo do arquivo. Como te expliquei um certo número de vezes todo programa C tem 3 arquivos sempre abertos: stdin, stdout e stderr. Veja nos tópicos anteriores.

 

Os outros arquivos você abre, usando claro o tal fopen() -- de file open. Como está nos exemplos todos.

 

E como esses arquivos sempre abertos são, claro, arquivos...  também são FILE*, ponteiros para arquivo. E assim pode escrever

Foi exatamennte isso que aconteceu, como não tinha um arquivo de entrada ele leu as informações que digitei

 

21 minutos atrás, arfneto disse:

Não. Leia no seu livro, ou no manual: fgets() retorna um ponteiro. Nesse programa não se usa o tamanho da linha. O enunciado é claro no sentido de que tem um ISBN por linha. 9 dígitos. O resto não importa. O tamanho da linha não imorta. Eu usei 10 porque é mais esperto já colocar o ISBN de verdade porque assim já tem como conferir ;) É claro que se ao rodar o programa você olha o arquivo de entrada e já confere os dígitos está sendo mais esperto do que mantendo uma lista em outro lugar, ou quem sabe fazendo as contas a mão.  Mas só importam claro os primeiros 9 dígitos.

 

O lance de fgets() é o seguinte: se a função não ler nada ela não faz nada. A variável fica igualzinha. E seu programa entra em loop... Muitos e muitos programas de iniciantes --- e alguns de profissionais --- entram em loop por causa disso. É tão ingênuo quanto não estar o retorno de scanf(), que você não testou em lugar nenhum. Mas fgets() retorna o endereço de linha, ou NULL. Usando como eu mostrei resolve o problema.

 

3 horas atrás, MATHEUSCDN disse:

A parte da comparação eu entendi que se o valor de P for nulo e a comparação entre linha e final for diferente de 0 ele entra na condição

 

Entendeu errado. 

 

A condição: 
 

    while ( (p != NULL) && (strcmp(linha,final) != 0) )

 

Se o valor de p não for nulo então leu algo. E aí, e somente aí, faz a segunda parte e vê se o que leu não é o final. E isso é o AND, &&

 

E se der verdadeiro então calcula o DV e lê o próximo ISBN.

 

Como eu expliquei no parágrafo acima, se não ler nada fgets() não muda nada em linha e por isso não deve usar linha nos testes.

 

E se não ler nada não pode comparar porque vai ter o mesmo valor de antes, o ISBN anterior.

 

Ninguém garante que tem um "000000000" na entrada, afinal.

 

 

Entendi, obrigado por ter tirado minhas dúvidas !

Link para o comentário
Compartilhar em outros sites

7 horas atrás, MATHEUSCDN disse:

Foi exatamennte isso que aconteceu, como não tinha um arquivo de entrada ele leu as informações que digitei

 

Não, não foi isso que aconteceu. O que eu te expliquei e vou repetir agora é que SEMPRE tem esses 3 arquivos abertos: stdin, stdout e stderr. SEMPRE.

 

Não é que não tinha um arquivo de entrada

 

O programa que eu escrevi para te mostrar sempre lê do arquivo entrada. Se vier um argumento ao iniciar o programa ele deve ser o nome do tal arquivo, e será usado no fopen()

 

Se não vier nada então o programa faz entrada = stdin e continua. Sem fopen. Porque? Porque como eu já disse umas vezes stdin já está aberto. Leia os exemplos.

 

E tire aquele include a mais. E mude a extensão para C.

 

 

 

 

 

 

Link para o comentário
Compartilhar em outros sites

1 hora atrás, arfneto disse:
8 horas atrás, MATHEUSCDN disse:

Foi exatamennte isso que aconteceu, como não tinha um arquivo de entrada ele leu as informações que digitei

 

Não, não foi isso que aconteceu. O que eu te expliquei e vou repetir agora é que SEMPRE tem esses 3 arquivos abertos: stdin, stdout e stderr. SEMPRE.

 

Não é que não tinha um arquivo de entrada

 

O programa que eu escrevi para te mostrar sempre lê do arquivo entrada. Se vier um argumento ao iniciar o programa ele deve ser o nome do tal arquivo, e será usado no fopen()

 

Se não vier nada então o programa faz entrada = stdin e continua. Sem fopen. Porque? Porque como eu já disse umas vezes stdin já está aberto. Leia os exemplos.

 

E tire aquele include a mais. E mude a extensão para C.

 

Entendi ! Eu só tenho mais uma dúvida a qual eu não tinha prestado atenção antes 

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

 

O que acontece nessa parte do for ? Onde tem s1+= isbn[i] - '0', s2+=s1 ?

 

Ele faz a soma parcial entre s1 e s2 e subtrai por 0 ?

Link para o comentário
Compartilhar em outros sites

2 minutos atrás, MATHEUSCDN disse:

O que acontece nessa parte do for ? Onde tem s1+= isbn[i] - '0', s2+=s1 ?

 

Isso é o que está escrito na tabela do enunciado. 

 

A função recebe 9 char, letrinhas assumidas como números entre '0' e '9' . Só que você quer somar pelo valor decimal, de 0 a 9. Então subtrai o '0' do valor porque vai te dar o número em decimal para somar.

 

Escreva um programa e mostre na tela. São umas 5 linhas só.

 

 

Link para o comentário
Compartilhar em outros sites

16 minutos atrás, arfneto disse:

A função recebe 9 char, letrinhas assumidas como números entre '0' e '9' . Só que você quer somar pelo valor decimal, de 0 a 9. Então subtrai o '0' do valor porque vai te dar o número em decimal para somar.

 

E essa vírgula depois do '0' ? Porque ela está ali e o que acontece depois dela ?

17 minutos atrás, arfneto disse:

Escreva um programa e mostre na tela. São umas 5 linhas só.

Quer que eu escreva um programa aleatório ou escreva esse que estou falando aqui ? Não entendi . Porque se for ele eu já coloquei ele completo ali em cima

Link para o comentário
Compartilhar em outros sites

1 hora atrás, arfneto disse:

A função recebe 9 char, letrinhas assumidas como números entre '0' e '9' . Só que você quer somar pelo valor decimal, de 0 a 9. Então subtrai o '0' do valor porque vai te dar o número em decimal para somar.

 

Escreva um programa e mostre na tela. São umas 5 linhas só

 

@MATHEUSCDN Ao citar um texto sugiro copiar um mínimo do contexto para que outros possam entender. O forum não é assim suporte individualizado: é para ser útil a outros

 

1 hora atrás, MATHEUSCDN disse:

Quer que eu escreva um programa aleatório ou escreva esse que estou falando aqui ? Não entendi . Porque se for ele eu já coloquei ele completo ali em cima

 

Que seria um programa aleatório? Tem um contexto aqui. Estou me referindo ao simples:

 

#include <stdio.h>
int main(void)
{
    char       v = '8';
    printf("\
char v = %c\tv-'0' = %d decimal\n\
v + v = %d\t(v-'0') + (v-'0') = %d\n",
        v, (v-'0'), v+v, (v-'0')+(v-'0')
        );
};

 

Que mostra

 

char v = 8      v-'0' = 8 decimal
v + v = 112     (v-'0') + (v-'0') = 16

 

Quando tem uma dúvida assim simplesmente escreva um programa e veja o que acontece. Vai aprender muito mais assim. E nem sempre vai ter alguém disposto a responder suas perguntas. Mas o computador nunca diz não ;) 

 

1 hora atrás, MATHEUSCDN disse:

E essa vírgula depois do '0' ? Porque ela está ali e o que acontece depois dela ?

 

Aqui também sugiro que poste o contexto para ajudar a outros que estejam lendo só isso....

 

    for (i = 0; i < 9; i++) s1 += isbn[i] - '0', s2 += s1;

 

Isso é um comando de uma linha. e sintetiza o que está aqui:

image.png.4b3c3262b5bceb0c5df90e5b23472a3c.png

 

é muito mais legível que usar 

 

    for (i = 0; i < 9; i++)
    {
        s1 += isbn[i] - '0';
        s2 += s1;
    }

 

A vírgula é um operador. Faz com que os dois comandos sejam tratados como um só, a tradução do que está na tabela.

 

Tabela que não é a melhor maneira de calcular o DV, como eu mostrei antes. E que sequer faz sentido nesse contexto, já que o objetivo é calcular o DV e a tabela tem 10 dígitos sendo que o DV só tem 9...

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...

 

GRÁTIS: ebook Redes Wi-Fi – 2ª Edição

EBOOK GRÁTIS!

CLIQUE AQUI E BAIXE AGORA MESMO!