Ir ao conteúdo

Posts recomendados

Postado

Crie um programa em C que leia o arquivo seqinteiros.dat, contendo uma sequência de 20 números inteiros. Ao final o programa deve criar o arquivo piramidif.dat contendo 19 linhas. Sendo que a primeira linha deve conter 19 números inteiros, onde cada número representa a diferença entre cada dois números consecutivos da sequência lida originalmente. A segunda linha deve conter 18 números inteiros, onde cada número representa a diferença entre cada dois números consecutivos da primeira linha. A terceira linha deve conter 17 números inteiros, onde cada número representa a diferença entre cada dois números consecutivos da segunda linha. E assim por diante, cada linha deve ter um número a menos que a anterior e o valor de cada número deve representar a diferença entre cada dois números consecutivos da linha anterior. A última linha do arquivo terá apenas um número.

  • Triste 1
Postado

@arfneto a sequência seria: 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765

Como criar uma matriz seguindo o que foi pedido no exercício proposto e um laço for para realizar? Ou existe formas mais fáceis?

Postado

Como se pode imaginar, a entrada é o inverso do que precisa na saída :) 

 

O enunciado é bem vago sobre o arquivo de entrada, então pode escrever como achar mais fácil: uma sequência de 20 x 4 dígitos com os números todos, uma série de 20 linhas para ficar mais fácil, os números todos separados por vírgula não seria nada estranho, pra poder usar fscanf() e ler um por um ;) . Tanto faz.

 

E a saída pode ser a mesma coisa, mas ao contrário. Pra ficar mais fácil de testar pode ler e escrever em linhas, assim pode usar o editor do IDE pra escrever... Ou pode escrever 19x4 dígitos.

 

Pode também criar o arquivo de entrada no próprio programa, pra não ter que ficar digitando, ou simplesmente copiar do texto aqui mesmo: :D 

 

1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765

 

Qual a dificuldade maior agora em escrever isso?

 

2 horas atrás, Vandin Campos disse:

Como criar uma matriz seguindo o que foi pedido no exercício proposto

 

Isso pode estar dificultando... Pra que uma matriz? onde o enunciado fala em matriz? 

 

Só existe um par de int e um resultado. E dois arquivos.

Postado

@arfneto eu imaginei uma matriz pelo fato de ter o início 19 números formando 19 colunas e até o restante sendo apenas 1 dígito na última linha, poderia me mostrar mais como ficaria as contas e uma forma de fazê-las de um jeito que as contas fiquem menor

Postado
12 minutos atrás, Vandin Campos disse:

@arfneto eu imaginei uma matriz pelo fato de ter o início 19 números formando 19 colunas e até o restante sendo apenas 1 dígito na última linha, poderia me mostrar mais como ficaria as contas e uma forma de fazê-las de um jeito que as contas fiquem menor

 

Entendo. Pode escrever assim para não ter que ler a entrada de novo, usando um vetor de 19 para começar o loop e gerando as linhas na saída.

 

8 minutos atrás, JorgeGus disse:

O enunciado não diz se a diferença entre n1 e n2 seria n1 - n2 ou n2 - n1.

 

2 horas atrás, Vandin Campos disse:

a sequência seria: 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765


@JorgeGus não faz diferença :D o trocadilho foi de propósito :D mas a julgar pela entrada proposta é mais bonitinho subtrair o primeiro do segundo...

 

Um pouco de código, pra ajudar

 

Imaginando o  arquivo seqinteiros.dat assim
 

   1    1    2    3    5 
   8   13   21   34   55

  89  144  233  377
   
   610

 987 1597 2584 4181 6765


 

Um programa pra começar poderia mostrar os números para dar uma segurança...
 

Vai abrir "seqinteiros.dat"
1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765
Lidos 20 numeros de "seqinteiros.dat"

 

Eis um programa desses, e que lê qualquer arquivo bastando passar o nome dele:

 

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

int main(int argc, char** argv)
{
    int         numero = 0;
    const char* padrão = "seqinteiros.dat";
    char        arquivo[80];
    if (argc > 1)
        strcpy(arquivo, argv[1]);
    else
        strcpy(arquivo, padrão);

    printf("Vai abrir \"%s\"\n", arquivo);
    FILE* E = fopen(arquivo, "r");
    if (E == 0) return -1; // nao abriu

    const char* mascara = "%d"; // para scanf()
    int         res = res = fscanf(E, mascara, &numero);
    if (res != 1) return -2; // bobagem: nao veio o primeiro numero
    unsigned    lidas = 1;
    while (!feof(E))
    {
        printf("%d ", numero);
        res = fscanf(E, mascara, &numero);
        if (res != 1) break; // acabou?
        lidas += 1;
    };  // while()
    printf("\n");
    fclose(E);
    printf("Lidos %d numeros de \"%s\"\n",
        lidas, arquivo);
    return 0;
}

 

Se outros.dat fosse
 

29 04 2021

 

E chamasse o programa com esse arquivo mostraria
 

Vai abrir "outros.dat"
29 4 2021
Lidos 3 numeros de "outros.dat"

 

Devido à natureza insistente de scanf() e família não faz diferença como os valores estão alinhados na entrada. E por isso deixei o exemplo meio "torto". A função vai tentar ativamente consumir a entrada enquanto tiver algo lá, e achar lá dentro o que foi pedido.

 

Se você pegar um vetor de 19 int e for colocando os valores lá dentro já terá a primeira linha: salva o primeiro valor e começa a subtrair, deixando os resultados no vetor...

 

Tentou no papel como eu perguntei?

 

 

  • Obrigado 1
Postado

Não tenho certeza, mas acho que a parte lógica seria isso:

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

int main() {
    int n[20] = {32, 3, 41, 22, 96, 19, 7, 69, 82, 1, 4, 12, 8, 56, 25, 94, 65, 5, 20, 73};
    for (int c1 = 18; c1 >= 0; c1--) {
        for (int c2 = 0; c2 <= c1; c2++) {
            n[c2] = n[c2] - n[c2 + 1];
            printf("%d ",n[c2]);
        }
        printf("\n");
    }
    return 0;
}

Mudando n1 - n2 para n2 - n1 os sinais se invertem.

Então, se for o caso basta mudar

n[c2] = n[c2] - n[c2 + 1];

para

n[c2] = n[c2 + 1] - n[c2];

Postado

@arfneto Eu consegui abrir o arquivo, e armazeno, minha dúvida seria só a parte da conta, não faço ideia de como começar. 

Minha leitura ficou assim: 

#include <stdio.h>

 

int main(void) {

int inteiros[20];

int i, j, aux=0;

FILE *arq;

 

arq = fopen("seqinteiros.dat","r");

for(i = 0; i<20; i++) {

fscanf(arq,"%d", &inteiros[i]);

}

fclose(arq);

 

arq = fopen("piramidif.dat","w");

for(i = 0; i<20; i++) {

printf(" %d",inteiros[i]);

}

 

fclose(arq);

 

return 0;

}

E funcionou, mas agora seria as contas... Me salva!!!

Postado

Sei que é a terceira vez que eu  pergunto, mas fez isso num papel?

 

Para os primeiros 5 de sua sequência, por exemplo:
 

   1    1    2    3    5
   0    1    1    2
   1    0    1
  -1    1
   2

 

É só um loop. A cada passo some o primeiro porque a primeira conta é (segundo-primeiro) ou o contrário, tanto faz.

 

Imagine uma função assim

 

int         mostra_serie(int N, int* V, const char* mensagem)
{
    if (mensagem != NULL) printf("%s\n", mensagem);
    printf("\n[%d]\t",N);
    for (int i = 0; i < N; i += 1)
        printf("%d ", V[i]);
    printf("\n");
    return N;
}

 

para mostrar os caras, porque é óbvio que precisa disso pra testar...

 

Pode usar assim
 

    mostra_serie(lidas, serie, "testando");

 

para a série original e ver na tela

 

testando
[20]    1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765

 

Conveniente, certo?

 

E se tivesse uma função assim:

 

int         encolhe_serie(int N, int* serie);

 


Que você chama e ela reduz a série usando ela mesma, já que vai sumir um cara a cada loop? Aí pra testar podia escrever
 

    mostra_serie(lidas, serie, "testando");
    encolhe_serie(lidas, serie);
    mostra_serie(19, serie, "com um a menos...");

 

e talvez ler

 

testando
[20]    1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765
com um a menos...
[19]    0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584

 

Ai podia conferir um por um... 🤔 E se passar um NULL só vai ver as séries...

 

E como reduzir a série?

 

Esse é um paradigma comum e está em C++ e java e javascript por exemplo, chamado reduce. Em C tem que programar mesmo. Nesse exemplo a operação é a subtração mesmo. Podia ser algo assim

 

int encolhe_serie(int N, int* S)
{
    for (int i = 0; i < N; i += 1) S[i] = S[i+1] - S[i];
    return N-1;
}

 

E aí pode usar o retorno para diminuir o tamanho :D bem conveniente... Veja:
 

testando
[20]    1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765
com um a menos...
[19]    0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584
com um a menos...
[18]    1 0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987

 

Para 

 

    mostra_serie(lidas, serie, "testando");
    lidas = encolhe_serie(lidas, serie);
    mostra_serie(lidas, serie, "com um a menos...");
    lidas = encolhe_serie(lidas, serie);
    mostra_serie(lidas, serie, "com um a menos...");

 

Se usasse NULL para a mensagem assim
 

    mostra_serie(lidas, serie, NULL);
    lidas = encolhe_serie(lidas, serie);
    mostra_serie(lidas, serie, NULL);
    lidas = encolhe_serie(lidas, serie);
    mostra_serie(lidas, serie, NULL);

 

teria

 

[  20]  1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765
[  19]  0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584
[  18]  1 0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987

 

Mais perto do que precisa a final...

 

E é claro que basta gravar a série em disco antes de encolher e terá a pirâmide. E se quer mudar o algoritmo de reduce já sabe onde...

 

Como seria isso?

Uma linha:
 

    while ((lidas = encolhe_serie(lidas, serie)) >= 1) mostra_serie(lidas, serie, NULL);

 

Gravar em disco é claro a mesma coisa.

  • Curtir 1
Postado
18 minutos atrás, Vandin Campos disse:

@arfneto Como esse código ficaria por completo? Tudo junto.

 

Pode usar control-c control-v direto do que tem acima ;) aí fica junto...
 

#include <stdio.h>
  
int encolhe_serie(int N, int* S)
{
    for (int i = 0; i < N; i += 1) S[i] = S[i+1] - S[i];
    return N-1;
}
 
int         mostra_serie(int N, int* V, const char* mensagem)
{
    if (mensagem != NULL) printf("%s\n", mensagem);
    printf("\n[%d]\t",N);
    for (int i = 0; i < N; i += 1)
        printf("%d ", V[i]);
    printf("\n");
    return N;
}

int main(void)
{
  return 0;
}

 

Você entendeu o que eu te expliquei antes?

 

 

 

 

Postado
1 minuto atrás, Vandin Campos disse:

Comecei a parte de função semana passada, por isso acompanhei por partes, por que deveria criar uma função de imprimir na tela separado e um laço para chamar assim que diminuir um do valor

 

Não entendi nadinha. Isso seria uma pergunta?

 

Você cria uma função porque é MUITO mais fácil e pode chamar várias vezes conforme diminui a série. E eu te mostrei DUAS prontas.

 

Qual a sua dúvida maior agora?

Postado

@arfneto Eu entendi as chamadas, mas agora no main como desenvolver as chamadas das linhas que ainda tenho dúvidas, para você ter ideia eu fiz sem o menu, para rodar a linha 19, ficando assim:

#include <stdio.h>

#include <stdlib.h>

 

int main(void) {

int inteiros[20] = {1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765};

int i, j;

FILE *arq;

 

arq = fopen("seqinteiros.dat","r");

for(i = 0; i<20; i++) {

fscanf(arq,"%d", &inteiros[i]);

}

fclose(arq);

 

arq = fopen("piramidif.dat","w");

for (i = 0; i < 19; i += 1) {

inteiros[i] = inteiros[i+1] - inteiros[i];

printf("%d ",inteiros[i]);

}

printf("\n");

 

fclose(arq);

 

return 0;

}

@arfneto Vou fazer e te envio a partir do menu, eu li novamente acho que desenvolvo algo aqui, você foi excelente para as minhas dúvidas, já já retorno!

Postado
2 minutos atrás, Vandin Campos disse:

Eu entendi as chamadas, mas agora no main como desenvolver as chamadas das linhas que ainda tenho dúvidas, para você ter ideia eu fiz sem o menu, para rodar a linha 19, ficando assim

 

Não consigo entender. Que seria um "menu"?

 

Você está lendo uns números para um vetor mas colocou antes OS MESMOS números que se imaginam estar no arquivo?

 

Rodou o programa que te mostrei, que lê e mostra o arquivo? Entendeu isso? 

 

 

TESTE sempre o retorno de scanf(). Você tem um livro? uma apostila? Onde aprendeu sobre essa função?

Postado
12 minutos atrás, Vandin Campos disse:

@arfneto Menu seria isso que você fez, pelo menos é o que o professor ensinou, aí fazemos suas chamadas dentro do menu principal (main)

 

Não faz sentido. menu é, digamos, um menu. Uma lista de opções e o cara escolhe uma.

 

main() é uma função, como outra qualquer. Apenas é diferente porque ao rodar um programa o sistema procura por essa pra rodar primeiro.

 

Se o que eu "fiz" é um menu porque o que você fez não é um menu?

  • Curtir 1
Postado

Acho que fica mais fácil se armazenar os números do arquivo em um vetor int e depois efetuar os cálculos, para armazenar ficaria algo assim,

 

int main(){
    FILE *arquivo = fopen("seqinteiros.dat","r");
    char linha[255];
    char *proximo;
    int vetor[20];
    int i = 0;
    
    fgets(linha, 255, arquivo);
    proximo = strtok(linha, " ");
    
    while(proximo != NULL){
        vetor[i] = atoi(proximo); 
        proximo = strtok(NULL, " ");
        i += 1;
    }
    fclose(arquivo);
    return 0;
}

 

Aí no loop será feito o cálculo com os elementos do vetor,

int n = vetor[i] - vetor[i - 1];

 

  • Curtir 1
Postado

@Midori Considere que ler os números assim
 

    fgets(linha, 255, arquivo);
    proximo = strtok(linha, " ");
    
    while(proximo != NULL){
        vetor[i] = atoi(proximo); 
        proximo = strtok(NULL, " ");
        i += 1;
    }
    fclose(arquivo);

 

ao invés de ler assim como eu mostrei antes ( eu postei um programa completo no tópico #7)
 

    int         res = res = fscanf(E, mascara, &numero);
    if (res != 1) return -2; // bobagem: nao veio o primeiro numero
    unsigned    lidas = 1;
    while (!feof(E))
    {
        printf("%d ", numero);
        res = fscanf(E, mascara, &numero);
        if (res != 1) break; // acabou?
        lidas += 1;
    };  // while()
    printf("\n");
    fclose(E);
    printf("Lidos %d numeros de \"%s\"\n",
        lidas, arquivo);

 

é bem mais complicado e menos flexível.

 

Explicando a diferença:

  • Do modo como escreveu tem que ler TODOS os valores na mesma linha e isso é chato pra digitar se forem muitos, e do modo como eu expliquei pode ler de qualquer jeito, todos na mesma linha, um por linha ou tudo z0@d0, como eu mostrei nesse exemplo de arquivo para os mesmos números
     
       1    1    2    3    5 
       8   13   21   34   55
    
      89  144  233  377
       
       610
    
     987 1597 2584 4181 6765

     

  • strtok() é uma função problemática e obscura porque zoa a string de entrada. E muitas vezes a entrada vem como constante porque é muito mais prático e seguro. Ninguém usa isso, pelo risco de coisas como por exemplo 
     

    		exporta_serie("\
    1, 1, 2, 3, 5,\
    8, 13, 21, 34, 55,\
    89, 144, 233, 377, 610,\
    987, 1597, 2584, 4181, 6765");

    que podia ter sido usado para passar a série para testar a pirâmide antes de ler do arquivo. Sabe o que aconteceria se usasse strtok() nesse caso, certo? Iria abortar o programa....
     

  • usando fscanf() elimina a chamada a atoi() para converter cada valor para inteiro e tudo roda mais rápido
     

  • em resumo: pode ser feito como escreveu, mas usando o tradicional scanf() para ler entrada formatada  é mais simples porque essa função foi escrita para isso. Evitando o uso dela eis o que você usou:
     

    • fgets() para ler um bloco todo.
       

    • strtok() para dividir o bloco um a um (e perder a entrada).
       

    • atoi() para converter um a um e que não precisaria, já que bastaria usar '%d' no especificador de fscanf()
       

    • você vai ter que digitar TODOS os valores na mesma string, o que também não era preciso e pode ser incomodo em relação a coisas simples como digitar um por um no IDE ou usar algo assim
       

         1    1    2    3    5 
         8   13   21   34   55
        89  144  233  377 610
       987 1597 2584 4181 6765


      que facilita contar a quantidade de 4x5 elementos.

Sugiro fazer o simples e escrever em torno dos dados e com as funções que foram escritas para tal. Entrada formada: scanf(). Texto em linhas: fgets(). strtok(): a verificar. Nunca vi uma situação em que isso você útil, pela razão (conhecida) que expliquei.

  • Curtir 1
Postado

@Vandin Campos

Este é um resultado? Sim OU Não.

Outra pergunta, esta sequência tem nome? É Fibonnaci.

1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765

 

Resumindo o enunciado a "diferença movel", qualquer par de valores com diferença é o valor posterior ao par, como em fibonnaci

21 - 13= 8 ..., 2584 - 1597 = 987. Fica ainda mais óbvio na primeira linha, mas eu só notei depois que rodei teu programa.

 

image.thumb.png.6a15dd396c01c11b6049e3297789902b.png

Postado

@arfneto Com fscanf é melhor e mais simples mesmo como explicou. Usei strtok que era forma que eu conhecia para para ter algo como um split e delimitador, já que os números que postaram estavam organizados numa linha e separados por espaço. O código ficou assim,

 

int main(){
    FILE *arquivo = fopen("seqinteiros.dat","r");
    int vetor[20];
    int i = 0;
    
    while(!feof(arquivo)){
        int numero;
        if(fscanf(arquivo, "%d", &numero) != 1){
            break;
        }
        vetor[i] = numero;
        i += 1;
    }
    fclose(arquivo);
    return 0;
}

 

Postado

cheguei ate aqui, nao to conseguindo fazer as contas

 

#include <stdio.h>

#include <stdlib.h>

 

int main(void) {

FILE *arqInteiros, *piramide;

int vetor[20];

int i;

 

arqInteiros = fopen("seqInteiros.dat", "r");

 

for(i = 0; i < 20; i++)

fscanf(arqInteiros, "%d", &vetor[i]);

 

fclose(arqInteiros);

 

piramide = fopen("piramide.dat", "w");

 

for(i = 0; i < 20; i++)

fprintf(piramide, "%d\n", vetor[i]);

}

Postado
2 horas atrás, Midori disse:

Com fscanf é melhor e mais simples mesmo como explicou. Usei strtok que era forma que eu conhecia para para ter algo como um split e delimitador, já que os números que postaram estavam organizados numa linha e separados por espaço. O código ficou assim

 

:) bem melhor assim. E deve ser como 10 ou 20x mais rápido por não envolver tantas chamadas de função.

@Midori
O problema mesmo de strtok() e a razão para não usar, ou quase nunca usar, é o fato de zoar o valor da entrada. Isso limita muito as coisas. Sugiro sempre escrever outra no contexto do programa que estiver fazendo, usando por exemplo char* e retornando as strings...

 

Por outro lado fscanf() é muito insistente em relação à leitura e tolera multi-coluna, multi-linha e tal... Quando não é você que prepara os dados quanto mais tolerante a função for melhor. ;) 

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

LANÇAMENTO!

eletronica2025-popup.jpg


CLIQUE AQUI E BAIXE AGORA MESMO!