Ir ao conteúdo

Posts recomendados

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

/*Programa que receba do usuário um arquivo texto e um caracter. 
Mostre na tela quantas vezes aquele caractere ocorre dentro do arquivo.*/
int main(){

char txt[100];//string p/ armazenar todo o txt q está no arq
int conta = 0, j;//conta qtas vezes aparece a letra no arq
char i;

FILE *arq;
arq = fopen("arquivo1.txt", "r");


if(arq == NULL)
printf("Erro ao tentar abrir o arquivo.\n");
else{
  while(fgets(txt,100,arq) != EOF){
    for(i = 'A'; i <= 'Z'; i++)
    {
      for(j = 0; txt[j] != '\0'; j++)
      {
        if(txt[j]==i || txt[j] == tolower(i))
        {
        ++conta;
        }
    }
    if(conta != 0)
    {
      printf("%c - %d vezes\n", i, conta);
    }
    conta = 0;
    }
    }
}
return 0;
}
Citação

O programa anexado está contando as letras do alfabeto, mas não para de contar...entra num loop infinito...alguém pode ajudar?

 

  • Obrigado 1
  • 2 anos depois...
Postado
Em 16/08/2019 às 23:18, devair1010 disse:

o delimitador de final de arquivo usando fgets é o NULL

 

@devair1010Não, não é. Está trocando o efeito pela causa.

 

Antes de tudo fim de arquivo não tem delimitador. EOF é uma constante retornada por funções como fread() ou feof(). Não é um delimitador. 

 

Em geral EOF é -1 o popular menos um.

 

Porque? veja mais ao final

 

De volta ao programa

 

Em 16/08/2019 às 09:56, nigolino disse:

O programa anexado está contando as letras do alfabeto, mas não para de contar...entra num loop infinito...alguém pode ajudar?

 

Habilite SEMPRE todos os avisos de seu compilador. -Wall se usa gcc ou clang, /W3 ou /W4 se usa o compilador da Microsoft.

 

Eis o que teria visto:

 

x.c: In function 'main':
x.c:20:28: warning: comparison between pointer and integer
   20 |   while(fgets(txt,100,arq) != EOF){
      |                            ^~

 

Pois é. Não tenho um compilador com mensagens em português aqui, mas acho que dá pra entender a mensagem: na linha 20 está comparando um ponteiro com um inteiro e provavelmente não era isso que queria.

 

Agora veja um IDE configurado para português:

 

 

Citação

E seu programa entrou em loop. então acho que não era mesmo isso que você queria: comparar um inteiro com um ponteiro ;) 

 

Mais ainda, em um IDE configurado para português:

 

trecho.png.22f90bb266be59ef9449d40d1522b637.png

 

Aí está a linha 20. E EOF vale -1, como eu disse, nessa plataforma (Windows, gcc). Esse é o inteiro. E o ponteiro?

 

image.png.d746fc8fdc7a757722ef47306db7510d.png

 

 

Nunca foi tão fácil ler o manual: é só parar o cursor em cima da função e ficar olhando"a definição da função acende bem acima da chamada na tela. Você tem um livro? Seu curso adota um?

 

A mensagem diz que fgets() retorna char*, o popular ponteiro para char. __cdecl não é importante aqui. É a convenção de chamada e pode ignorar.

 

Então porque entra em loop afinal?

 

Eu já escrevi aqui muitas vezes sobre isso. Todos os dias programas de iniciantes e profissionais entram em loop por causa disso. fgets() lê uma string, e retorna um ponteiro para ela. E esse é o valor que se deve usar no programa. NUNCA a própria string que passou como parâmetro, e nunca comparar o ponteiro com EOF

 

No seu caso txt, que é char[100]:
 

  while(fgets(txt,100,arq) != EOF){

 

Se der erro por exemplo, ou fim de arquivo, fgets() não mexe em txt, afinal não leu p. nenhuma. Mas sempre retorna um ponteiro para a string lida, ou NULL.

 

Como você ficou testando o retorno comparando com EOF nunca vai parar mesmo. NULL é zero, um ponteiro qualquer não vai ser zero porque é um endereço, e EOF é negativo.

 

EOF é negativo porque afinal?

 

fread()

 

por exemplo é claro a função que lê. E ela retorna o que? size_t, está no manual. Pode ser 0, mas não pode ser negativo.

 

É claro que fread() retornar zero não é um erro. Muitas vezes, como num game, é preciso ler mas não pode parar o programa. Você tenta ler pra ver se o cara digitou algo, como o botão de tiro. Se o cara digitou algo e foi o botão de tiro o game gera um tiro. se foi uma seta move algo, mas se não leu nada continua com a animação.

 

Não vai ficar esperando o cara digitar o número de tiros e teclar ENTER, certo? 

 

Mas negativo nunca vai retornar. E por isso fread() retorna EOF, negativo, se deu erro ou fim de arquivo.

 

feof()

 

Essa  é a função que diz se o arquivo acabou. Como? 

 

Em C 0 é falso, qualquer outro valor é verdadeiro. Então feof() retorna zero se o arquivo NÃO terminou. E se terminou podia retornar qualquer outra coisa. 400, 42, 300, tanto faz. Desde que não seja zero. E faz sentido retornar EOF, que é negativo.

 

Sobre seu programa, @nigolino considere que

 

só precisa contar as letras. Pra que ler uma string, armazenar em uma variável de 100 char e depois ficar lendo e contando? Não está bom. Não precisa de nada disso. E claro que devia aceitar os DOIS únicos parâmetros que seu programa usa, direto na linha de comando. É muito chato ficar parado esperando o programa perguntar o que você sabe que ele vai perguntar e ficar teclando enter e enter...

 

 

 

 

 

 

 

 

 

 

 

 

Ainda sobre EOF fgets() e erro, se fgets retornar NULL pode ou não ser EOF do arquivo, e se não for pode saber que erro deu usando perror(), o clássico.

Ainda sobre EOF fgets() e erro, se fgets retornar NULL pode ou não ser EOF do arquivo, e se não for pode saber que erro deu usando perror(), o clássico.

 

@nigolino seu programa diz que devia fazer uma coisa e faz outra: ele contaria as letras que tem no arquivo, mas nos comentários diz que era para contar quantas vezes uma certa letra aparece no arquivo...

  • Obrigado 1
Postado
51 minutos atrás, devair1010 disse:

@arfneto     não é um delimitador , e sim o retorno de fgets ,  mas com esse NULL  vai funcionar .

 

Sim. Como eu disse, você estava trocando causa por consequência. O erro é aquele que o compilador mostra: comparar ponteiro com inteiro. fgets() retorna um ponteiro. EOF não é um delimitador. Não há delimitador de fim de arquivo. Apenas tem uma variável dentro da estrutura do arquivo, que diz se chegou até o final, SEEK_END :) 

  • Obrigado 1

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!