Ir ao conteúdo

C++ funções e matrizes ISBN


Ir à solução Resolvido por arfneto,

Posts recomendados

Postado
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?

 

 

 

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

 

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

Postado
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

 

Postado

Tendo que fazer a mesma atividade aqui, tentei abrir uma pergunta em outro fórum mas o código da galera é cheio de biblioteca que nunca vi na vida...

Postado

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

 

 

Postado
25 minutos atrás, arfneto disse:

note que você disse que tinha rodado em sua máquina...

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 

Postado
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?

Postado
47 minutos atrás, arfneto disse:

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

Por enquanto estou tentando rodar seu código e no vscode mostrou isso 

image.thumb.png.7b8fcc69bc7aac0efba425efcc2d5354.png

Vou baixar um IDE de apenas C e tentar rodar

 

Deu o mesmo problema...

 

  • Solução
Postado

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>

 

Postado

 

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;

 

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

 

 

 

 

Postado
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 !

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

 

 

 

 

 

 

Postado
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 ?

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

 

 

Postado
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

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

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!