Ir ao conteúdo
  • Cadastre-se

C erro ao abrir arquivo txt


glaukito

Posts recomendados

fala gente boa!

estou com esse probleminha, consigo salvar um arquivo .txt com valores, porém, não consigo abrir esse .txt na sequência. Alguma dica para resolver esse problema?

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

main() {
		char nome[10];
			int quantidade, i;
    		
			FILE *arquivo;
	
			
			printf("Digite o nome do arquivo:");
			scanf("%s", nome);
			
			printf("Digite a quantidade de números:");
			scanf("%d", &quantidade);
	
			arquivo = fopen(nome, "w");

			if (arquivo==NULL) {
				printf("Falha ao criar o arquivo.");
					exit (0);
			}
			
			else {
				for (i=1;i<=quantidade;i++) 
				fprintf(arquivo, "%d\n", rand()%100);
			}
				printf("arquivo criado com sucesso.");
				
	
	arquivo = fopen("teste.txt", "r");
 		if(arquivo == NULL){
	
     printf("Erro, não foi possivel abrir o arquivo\n");
     getchar();
     exit(0);
    }
  
  	int vetor [100];
		while(fgetc(vetor, 100, arquivo) =! NULL){
     		printf("%d", vetor);
     	}
  
	fclose(arquivo);
			
}

 

Link para o comentário
Compartilhar em outros sites

Não entendi... você quer abrir o mesmo aquivo?
Ok, mas se é pra abrir o mesmo aquivo, porque outro fopen se ele ainda está aberto?
você quer abrir o arquivo, de novo, o correto seria dar close nele antes de fazer isso de novo.

Se não fechar o arquivo, depois de escrever no arquivo, você precisa reposicionar o cursor, novamente, no ponto onde começou  agravar, se quiser recuperar os dados já escritos no arquivo com um fget... 
o comando pra reposicionar o cursor é fseek

Link para o comentário
Compartilhar em outros sites

3 horas atrás, glaukito disse:
	arquivo = fopen("teste.txt", "r");

 

Feche o arquivo antes de reabrir...

Teste sempre o retorno de scanf()

 

Se você mesmo vai usar esse programa, acho que iria preferir muito entrar com o nome de arquivo e o total de números na linha de comando. O normal em C. Evite sempre programas interativos.

 

 

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

@arfneto fiz modificações e ainda não funciona, realmente não entendi a lógica disso.

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

int main() {
	 	
	int opcao;

    printf ("1 - cria arquivo\n");
    printf ("2 - abre arquivo\n");
    printf ("qual a opcao? ");
    scanf ("%d", &opcao);

	switch (opcao){
	
	    case 1:
	    	FILE *arquivo;
			
			char nome[10];
			int quantidade, i;
		
			printf("Digite o nome do arquivo:");
			scanf("%s", nome);
		
			printf("Digite a quantidade de números:");
			scanf("%d", &quantidade);
		
			arquivo = fopen(nome, "w");
			if (arquivo==NULL) {
			
				printf("Falha ao criar o arquivo.");
				exit(1);
			}
			else {
				for (i=1;i<=quantidade;i++) 
					fprintf(arquivo, "%d\n", rand()%100);
			}
			fclose(arquivo);
			return 0;
	    break;
	    
	    case 2:
			arquivo = fopen("teste.txt", "r");
			while (fscanf(arquivo, "%d", &i) == 1)
	
			printf("%d\n", i);
			fclose(arquivo);
		break;
	    default:
	        break;
	}
}

 

Link para o comentário
Compartilhar em outros sites

16 minutos atrás, glaukito disse:

fiz modificações e ainda não funciona, realmente não entendi a lógica disso.

O senhor está estudando da forma errada.
Quando a gente quer estudar algo, a gente deve começar pelo inicio...
Quero dizer, pelo que entendi, que o senhor quer criar um aquivo e escrever nele alguns dados. Depois, quer abrir ele novamente e ler esses dados. Mas você não sabe usar um case ainda.
O básico é começar assim:
saber e declarar tipos de variaveis como int, char, Ponteiros como *char...
Depois saber como ler o conteudo dessas variaiveis e imprimir.
depois saber condicionais... fazer um if, if-else, e else if... switch-case
Depois saber como realizar um loops como for, do-while, while...
Structs, unions, ...
funções, como chamar funções, como passar parametros...
Acho que por ai já é um bom começo pra depois tentar entender como trabalhar com arquivos.
É possivel que eu esteja esquecendo alguma outra precedencia, mas não se preocupe. Pesquisando comando por comando e tentando executar cada um deles, separadamente, você vai consequir aprender.
 

Link para o comentário
Compartilhar em outros sites

5 horas atrás, arfneto disse:

Feche o arquivo antes de reabrir...

Teste sempre o retorno de scanf()

 

Se você mesmo vai usar esse programa, acho que iria preferir muito entrar com o nome de arquivo e o total de números na linha de comando. O normal em C. Evite sempre programas interativos

 

Leu essa parte: ;) 

 

Foi tudo que eu escrevi e você mudou o programa para ainda mais longe do que eu expliquei. E vai ter mais trabalho. E ele não funcionou.

 

  • programas interativos não ensinam nada. Não servem de nada.
  • teste o retorno de scanf()
  • não faça um programa que vai ficar perguntando coisas que você sabe que ele vai perguntar, em especial enquanto está testando. Isso foi resolvido em C nos anos '70, no Unix. Use a linha de comando.

A lógica disso:

 

Escreva em torno dos dados.

 

Seu programa tem 2 fases

  • abre e cria um arquivo com umas linhas de texto
  • abre esse arquivo e mostra as linhas que gravou

 

Qual o arquivo?

Quantas linhas?

 

Faz diferença antes do programa estar funcionando? Não. Tem outras coisas para aprender.

 

Precisa escrever um programa só? Não.

 

Precisa de um menu? NUNCA. Fuja disso.

 

Aprenda a usar funções. São um bloco de código com um nominho, mas C não serve pra nada sem isso.

 

Note que main() é uma função.

 

Como criar um arquivo?

 

Arquivos em C são absolutamente triviais e muito mais simples que ler do infeliz do teclado. Usando arquivos você passa o problema para outros: pode digitar os arquivos usando um editor de texto que alguém já escreveu e testou, por exemplo o mesmo que usa para criar seu programa....

 

Se você não tem, arrume um livro ou dois e um site de referência. Se usa Linux, que um dia foi Linux, entenda que C foi criada para escrever o Unix, no final dos '60, e no Linux tem o manual de tudo.

 

Windows tem Linux dentro há anos. Pode habilitar e usar em minutos. 

 

Não sabe usar fopen() por exemplo? 

 

Veja: 

 

image.png.f94303bc7e1f50cb484f37888ac7b359.png

 

Isso num tal Ubuntu em Linux no Windows na máquina que estou usando agora. Sim, podia ser em português, mas nessa máquina não tem. E não precisa de internet, de navegador, nada. Naquela época praticamente todo usuário era programador :) e o computador não era uma coisa pessoal.

 

Então você vai criar um arquivo que tem umas linhas, e lá tem um número por linha. Que números são esses?

 

	fprintf(arquivo, "%d\n", rand() % 100);

 

Veja que já usou uma outra função aí, essa rand()

 

image.png.097836db0232eb38dc40f0cc157decb3.png

 

 

Veja o manual no terminal, sem stress

 

 

 

 

De volta ao programa

 

Então vai ter um número entre 0 e 99 em cada linha.

 

E não se sabe ao certo quantas linhas tem, na hora de ler.

 

Então basta ler até o fim.... A máquina sabe quando acabou.

 

Eis um arquivo

 

42
17
0
99

 

que seja um.txt

 

Tem um milhão de maneiras de fazer qualquer coisa em C ou outras linguagens. Você só precisa de uma, nem precisa ser boa, nem precisa ser a melhor. Mas não deve ser ingênua. Deve ter um plano, porque não vai perder dias para aprender cada coisa e quer lógico usar um programa pra fazer o próximo.

 

Um código

 

#include <stdio.h>
int main(void)
{
    const char arquivo[] = "um.txt";
    FILE*      f         = fopen(arquivo, "r");
    if (f == NULL) return -1;

 

Pois é:  precisa de stdio por causa de fopen() e printf()

 

Aí está o nome do arquivo numa variável. Uma variável constante, que você não pode mudar. Aprenda a declarar como tal. Assim o compilador trabalha por você e se tentar mudar por engano em um programa grande não vai precisar se preocupar. Programação defensiva. E não ponha o nome fixo dentro do fopen() porque logo mais vai querer mudar.

 

Um arquivo em C é um ponteiro para uma estrutura. E não importa o que tem lá. 

 

Importante: essencial: TODO programa em C tem 3 arquivos abertos sempre: a entrada, a saída e a saída de erro, e eles tem nome: stdin, stdout e stderr. Inicialmente associados ao teclado e à tela. Qual o tipo deles? 

FILE*. Um ponteiro para arquivo. Assim como f aí no exemplo.

 

De volta a fopen() a função associa a um ponteiro um arquivo com o nome e o modo de abertura especificados. "r" é para leitura. Um arquivo é apenas uma série de bytes. Em Unix/Linux TUDO é um arquivo. esse modo "r" é orientado a texto e aqui é mais conveniente. Um outro modo comum seria "rb" que supõe a leitura em registros de tamanho fixo. Só que o tal tamanho pode ser 1 e assim não faz diferença. Não existe tipo de arquivo em C. Tudo é arquivo. Mas tem uma série de funções orientadas a linha, e a linha tem um tamanho variável, Uma outra série de funções é orientada a bloco, que pode ser de 1 byte só. E só a realidade da aplicação vai dizer como é melhor usar um arquivo.

 

Se não conseguir abrir o arquivo fopen retorna NULL, e de pouco serve: você vai querer saber porque deu erro e para isso existe uma função, perror() e uma variável, errno em errno.h. Agora só queremos o lado bom: se não abriu encerra

 

    // le algo
    int n   = 0; // um lugar pra guardar o numero
    int res = fscanf(f, "%d", &n); 

 

Pois é: scanf() não aloca memória. Então precisa passar o endereço de algo que já exista. Nesse caso declaramos n para receber o valor.

 

a função retorna um int que vai de -1 até o total de especificadores na string de formato.

 

        res = fscanf(f, "%d %c %f %d %f %d", ... // le umas coisas

 

nesse caso tem 6 coisas então pode retornar de -1 a 6. E se você não testar você vai ter um longo caminho para escrever programas....

 

    while (res == 1)
    { 
        printf("%d\n", n); // mostra um numero
        res = fscanf(f, "%d", &n); // le outro numero
    }
    fclose(f);
    return 0;

 

E de volta ao programa, um loop:

 

Enquanto ler algo mostra na tela. Quando parar de ler deve ser porque acabou o arquivo. A ambição deve ser pequena em programas de estudante. É claro que não quer dizer necessariamente que acabou o arquivo, mas é o mais provável.

 

Então o programa f0

 

#include <stdio.h>
int main(void)
{
    const char arquivo[] = "um.txt";
    FILE*      f         = fopen(arquivo, "r");
    if (f == NULL) return -1;

    // le algo
    int n   = 0; // um lugar pra guardar o numero
    int res = fscanf(f, "%d", &n); 
    while (res == 1)
    { 
        printf("%d\n", n); // mostra um numero
        res = fscanf(f, "%d", &n); // le outro numero
    }
    fclose(f);
    return 0;
}

 

rodando na mesma pasta que tem o tal arquivo acima mostra 
 

CH> f0
42
17
0
99

 

E já dá uma boa sensação. :D 

 

E se fosse pra criar o arquivo? Claro que vamos escrever outro programa a partir desse. Não há razão pra perder tempo misturando as coisas.

 

Recortar e Colar

 

    const char arquivo[] = "outro.txt";
    FILE*      f         = fopen(arquivo, "w");
    if (f == NULL) return -1;

 

Mudou o modo de abertura, agora é "w". Sim, tem outros, claro. Mas não vamos escrever nenhum livro agora
 

    int n   = 1 + rand() % 10; // ate 10 linhas
    fprintf(stderr, "Vai gravar %d linhas em \"%s\"\n", n, arquivo);

 

Então vamos gravar n linhas. Como vai criar um arquivo e pode sair algo errado, faz sentido mostrar quantas linhas vai gravar onde, já que é grátis...
 

Vai gravar 4 linhas em "outro.txt"

 

Não é mal colocar as strings entre aspas porque se estiver em branco pelo menos tem as aspas pra você saber...
 

    for (int i = 0; i < n; i += 1) fprintf(f, "%d\n", rand() % 100);
    fclose(f);
    return 0;

 

E o loop grava as linhas. Depois fecha o arquivo e termina o programa, copiado do primeiro...

 

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

int main(void)
{
    srand(210913);
    const char arquivo[] = "outro.txt";
    FILE*      f         = fopen(arquivo, "w");
    if (f == NULL) return -1;
    int n   = 1 + rand() % 10; // ate 10 linhas
    fprintf(stderr, "Vai gravar %d linhas em \"%s\"\n", n, arquivo);
    for (int i = 0; i < n; i += 1) fprintf(f, "%d\n", rand() % 100);
    fclose(f);
    return 0;
}

 

Esse include novo é porque rand() reside em stdlib. E a chamada a srand() é uma coisa com a qual deve se acostumar: o s de rand() é de semente --- seed no caso --- e usando uma semente conhecida pode testar programas muito complicados usando a MESMA série. É o esperto. O ingênuo é usar um outro include e pegar uma fação da hora e criar sequências que não pode repetir se está testando.

 

Em geral programadores C são maníacos por controle.

 

E o programa gerou
 

79
22
15
69

 

da primeira vez.

 

Agora você cola um no outro. . .

 

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

int main(void)
{  // grava
    srand(210913);
    const char arquivo[] = "outro.txt";
    FILE*      f         = fopen(arquivo, "w");
    if (f == NULL) return -1;
    int n = 1 + rand() % 10;  // ate 10 linhas
    fprintf(stderr, "Vai gravar %d linhas em \"%s\"\n", n, arquivo);
    for (int i = 0; i < n; i += 1) fprintf(f, "%d\n", rand() % 100);
    fclose(f);
    // agora le
    fprintf(stderr, "Vai ler os numeros em \"%s\"\n", arquivo);
    f = fopen(arquivo, "r");
    if (f == NULL) return -1;

    // le algo
    n       = 0;  // um lugar pra guardar o numero
    int res = fscanf(f, "%d", &n);
    while (res == 1)
    {
        printf("%d\n", n);          // mostra um numero
        res = fscanf(f, "%d", &n);  // le outro numero
    }
    fclose(f);
    return 0;
}

 

E a chance de dar certo é bem grande...

 

Vai gravar 4 linhas em "outro.txt"
Vai ler os numeros em "outro.txt"
79
22
15
69

 

E deu certinho.

 

Mas o nome do arquivo está fixo, e o número de linhas aleatório. Seia melhor poder escrever
 

	pgm novo.txt 10

 

E o programa entender de uma vez que é pra criar novo.txt com 10 linhas. Ou será que é melhor ficar parado esperando um menu, para responder as mesmas perguntas, e depois digitar o número de linhas? Não, não é.

 

Recortar e colar

 

int main(int argc,char** argv)
{ 
    if (argc != 3)
    {
        printf("Use: pgm arquivo nnn\n");
        return -1;
    }
    unsigned n = atoi(argv[2]);
    if(n > 30) n = 30;
    printf("Criando \"%s\" com %u linhas\n", argv[1], n);

 

Pronto: o programa espera os parâmetros. O parâmetro 0 sempre é o nome do programa, e o sistema SEMPRE monta isso, em C, em java, em C++... Basta usar
 

CH> pgm
Use: pgm arquivo nnn

CH> pgm novo.txt 8
Criando "novo.txt" com 8 linhas
Vai gravar 8 linhas em "novo.txt"
Vai ler os numeros em "novo.txt"
63
79
22
15
69
43
0
45

 

E o programa?

 

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

int main(int argc,char** argv)
{ 
    if (argc != 3)
    {
        printf("Use: pgm arquivo nnn\n");
        return -1;
    }
    unsigned n = atoi(argv[2]);
    if(n > 30) n = 30;
    printf("Criando \"%s\" com %u linhas\n", argv[1], n);

    srand(210913);
    FILE*      f         = fopen(argv[1], "w");
    if (f == NULL) return -1;
    fprintf(stderr, "Vai gravar %d linhas em \"%s\"\n", n, argv[1]);
    for (unsigned i = 0; i < n; i += 1) fprintf(f, "%d\n", rand() % 100);
    fclose(f);
    // agora le
    fprintf(stderr, "Vai ler os numeros em \"%s\"\n", argv[1]);
    f = fopen(argv[1], "r");
    if (f == NULL) return -1;

    // le algo
    n       = 0;  // um lugar pra guardar o numero
    int res = fscanf(f, "%d", &n);
    while (res == 1)
    {
        printf("%d\n", n);          // mostra um numero
        res = fscanf(f, "%d", &n);  // le outro numero
    }
    fclose(f);
    return 0;
}

 

Uma última nota sobre 

 

    fprintf(stderr, "Vai ler os numeros em \"%s\"\n", argv[1]);

 

stderr é um arquivo separado. Então se as mensagens que são para teste forem escritas em stderr ao invés do normal, stdout, é possível ao rodar o programa separar essas coisas. Na console do Windows por exemplo

 

CH> pgm novo.txt 3
Criando "novo.txt" com 3 linhas
Vai gravar 3 linhas em "novo.txt"
Vai ler os numeros em "novo.txt"
63
79
22

CH> pgm novo.txt 3 2>NUL
Criando "novo.txt" com 3 linhas
63
79
22

 

NUL é o null device do Windows, como o /dev/null do Unix  e derivados. Mas podia ser o nome de um arquivo. 2 é stderr. 0 é stdio, 1 é stdout. Os números dos arquivos em C, como eram em FORTRAN nos '70

 

 

Eu escrevi tudo isso como um exemplo pra você entender a lógica de escrever passo a passo em torno dos dados e pensando no programa seguinte: recortar e colar.

 

 

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

Aprenda a ler resistores e capacitores

EBOOK GRÁTIS!

CLIQUE AQUI E BAIXE AGORA MESMO!