Como salvar frases em um arquivo e depois listar todas elas

Recentemente comecei a estudar um pouco de C na minha faculdade, onde recebi o seguinte exercício:

Faça um programa, em linguagem C, que lê 5 frases, informadas pelo o usuário, de, no máximo, 50 caracteres cada uma e armazene-as em um arquivo. Mas, antes de gravar cada frase no arquivo, é necessário converter todas as suas letras para maiúsculas.-
-O nome do arquivo será fornecido, via teclado, pelo usuário.
-A seguir, feche o arquivo.
-Reabra o arquivo, para leitura, exibindo na tela todas as frases convertidas.
Dicas:
1.A função que converte minúscula para maiúscula é o toupper().
2.Como cada texto pode ter tamanho diferente, será necessário gravar antes de cada frase o tamanho do texto a ser lido. Logo serão necessários dois comandos de gravação e leitura (um para o número inteiro que indica a quantidade de caracteres da frase e outro para a frase com o tamanho lido).

O que eu fiz até agora:

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

int main()
{
FILE *arquivo;
int i, j, num = 0;
char texto[50], maiuscula[50], nomeArquivo[20], c;

printf("Digite o nome do arquivo a ser criado: ");
scanf_s("%s", &nomeArquivo, 20);
scanf_s("%c", &c, 1);
fflush(stdin);

for (i = 1; i <= 5; i++) {
    fopen_s(&arquivo, nomeArquivo, "a");

    if (arquivo == NULL) {
        fprintf(stderr, "Erro ao abrir o arquivo.\n");
        exit(EXIT_FAILURE);
    }
    else { 
        printf("Digite a frase numero %i: ", i);
        gets_s(texto, 50);
        fflush(stdin);
        j = 0;

        while (texto[j] != '\0' && j < 49) {
            maiuscula[j] = toupper(texto[j]);
            j++;
        }

        maiuscula[j] = '\0';

        fwrite(&num, sizeof(int), 1, arquivo);
        fwrite(maiuscula, sizeof(char), num, arquivo);
        fclose(arquivo);
    }
}

fopen_s(&arquivo, nomeArquivo, "r");

if (arquivo == NULL) {
    fprintf(stderr, "Erro ao abrir o arquivo.\n");
    exit(EXIT_FAILURE);
}

fread(&num, sizeof(int), 1, arquivo);
fread(texto, sizeof(char), num, arquivo);

while (!feof(arquivo)) {
    printf("\nTexto Lido: %s", texto);
    memset(texto, '\0', 50);
    fread(&num, sizeof(int), 1, arquivo);
    fread(texto, sizeof(char), num, arquivo);
}

fclose(arquivo);

}

Porém o resultado é:

Alguém pode me ajudar e dizer onde estou errando?

Bem, vc tem várias funções específicas do compilador da Microsoft e está fazendo algumas coisas do jeito errado ou que não deveriam ser feitas, por exemplo, invocar fflush. Vou reescrever do jeito que deveria ser no C padronizado.

1 curtida

Você abre o arquivo toda vez que entra no for, teria que fechar antes de terminar a iteração seguindo a ideia tua de usar “a” (append) para abrir o arquivo. Basta abrir uma vez com “w”, fazer tudo o que precisa e fechar. Se a quantidade máxima de cada c-string é de 50 caracteres, vc precisa declarar os arrays com 51 posições, pois o caractere nulo vai ocupar a posição 51 caso a string tenha 50 caracteres. Segue uma versão em C padrão.

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

int main() {

    FILE *arquivo;
    int i, j, num = 0;
    char texto[51], maiuscula[51], nomeArquivo[21], c;

    printf( "Digite o nome do arquivo a ser criado: ");
    fgets( nomeArquivo, 20, stdin );
    nomeArquivo[strlen(nomeArquivo)-1] = '\0';

    // abrindo para sobrescrever, tem que abrir fora do for
    arquivo = fopen( nomeArquivo, "w" );

    for (i = 1; i <= 5; i++) {

        if (arquivo == NULL) {
            fprintf( stderr, "Erro ao abrir o arquivo.\n");
            exit(EXIT_FAILURE);
        } else {

            printf("Digite a frase numero %i: ", i);
            fgets( texto, 50, stdin );
            texto[strlen(texto)-1] = '\0';

            j = 0;
            while ( texto[j] != '\0') {
                maiuscula[j] = toupper(texto[j]);
                j++;
            }
            maiuscula[j] = '\0';

            // evita pulo de linha após última linha do arquivo
            if ( i != 1 ) {
                fprintf( arquivo, "\n" );
            }
            fprintf( arquivo, "%s", maiuscula );

        }

    }

    // fechando o arquivo, vc não tem no seu código
    fclose(arquivo);

    arquivo = fopen( nomeArquivo, "r" );

    if (arquivo == NULL) {
        fprintf(stderr, "Erro ao abrir o arquivo.\n");
        exit(EXIT_FAILURE);
    }

    while ( !feof(arquivo) ) {
        fgets( texto, 50, arquivo );
        printf( "Texto Lido: %s", texto );
    }

    fclose(arquivo);

}
1 curtida

Boa noite!

Para funcionar no Visual Studio, eu apenas tive que mudar a forma de escrita do fopen, porque o resto ficou perfeito e deu super certo.

Apenas uma dúvida, vi tanta coisa sobre o fflush que cada vez entendo menos, porque não devo usa-lo?

Muito obrigado pela ajuda!!!

Sim, o compilador da Microsoft é padronizado, mas tem coisas a mais. O fflush descarrega o que estiver em um stream, então para jogar fora o pulo de linha que fica “sobrando” no stdin depois de uma leitura, alguns ensinam a fazer um fflush(stdin). O problema é que o funcionamento dele não é garantido em todas as plataformas. Claro, nesse seu programa não há problema nenhum usar, pq afinal de contas é só um exercício, mas em um programa de verdade, escrito em C e que deveria rodar em várias plataformas depois de recompilado, isso seria um problema. Se não me engano, no SO da Apple o fflush não faz nada.

1 curtida