DUVIDAS EP_04

DUVIDAS EP_04

por ARTUR SCAVONE -
Número de respostas: 45
Aviso importante sobre estouro de memória no Windows.

Eu tive um problema de compilação com o EP4 e falei com o Reverbel. O alerta é para quem estiver usando DEV C++ na configuração padrão com Windows XP. Poderá haver um estouro de memória quando se declarar um array dentro de uma função com valor de 512. Veja o pedaço de código abaixo:

/* --------------------------------*/
#define MAX 512 /* dimensao maxima */
int main() {
int m, n, maxval;
int a[MAX][MAX];
(...)
/* --------------------------------*/


Isto dá um BAITA erro no Windows. A solução (depois o prof explica direito) é colocar um STATIC conforme abaixo ou diminuir o máximo até que não ocorra o estouro:


/* --------------------------------*/
#define MAX 512 /* dimensao maxima */
int main() {
int m, n, maxval;
static int a[MAX][MAX];
(...)
/* --------------------------------*/

Em resposta à ARTUR SCAVONE

Re: DUVIDAS EP_04

por Daniel Amorim de Oliveira -
professor na função read_pgm que o EP4 manda eu escreve tem os seguintes atributos:

/* ----------------------------------------------
Funcao que le um arquivo no formato PGM.
fname : nome do arquivo PGM
M : matriz correspondente a imagem lida
*m : numero de linhas da matriz
*n : numero de colunas da matriz
*maxval : maior valor na matriz
---------------------------------------------- */
int read_pgm(char fname[], int M[][MAX], int *m, int *n, int *maxval);


eu gostaria de saber porque eu tenho q tratar o m, n e maxval como ponteiros se eu naum vou mudar o seu valor ao longo do programa????
Em resposta à Daniel Amorim de Oliveira

Re: DUVIDAS EP_04

por Rodrigo Cordeiro Godoy -
Daniel, você precisa tratá-los como ponteiros nesta função porque você quer que o main consiga o m e o n da figura (chamando a função usando como argumentos &m e &n) para poder mandá-los para outras funções, como a write_pgm ou qualquer outra que você crie.

Certo?
Em resposta à Rodrigo Cordeiro Godoy

Re: DUVIDAS EP_04

por Daniel Amorim de Oliveira -
ah sim entendi, na verdade eu pensei nisso ha uma meia hora atras^^ ehee

é q eu pensava q eu teria q colocar no main o mesmo q ta escrito como exemplo no enunciado do ep....

entaum quer dizer q eu posso fazer uma função pra ler do jeito que eu quiser (seguindo o exemplo), mas naum preciso ter exatamente ele no main???

Em resposta à Daniel Amorim de Oliveira

Re: DUVIDAS EP_04

por Daniel Amorim de Oliveira -
eu acabei o ep e ele funcionou muito bem, menos na foto kid, naum sei porque a saida ficou zuada (to mandando ela em anexo)...
isso é normal??
Em resposta à Daniel Amorim de Oliveira

Re: DUVIDAS EP_04

por ARTUR SCAVONE -
Outra coisa: eu coloquei, como no exemplo a linha:

fprintf(arq, "# imagem sem ruido\n");

Mas se a gente tenta abrir a imagem que já fizemos o tratamento, nosso programa não trata esse tipo de linha. É pra tratar?

Artur
Em resposta à Daniel Amorim de Oliveira

Re: DUVIDAS EP_04

por ARTUR SCAVONE -
Outra coisa: eu coloquei, como no exemplo a linha:

fprintf(arq, "# imagem sem ruido\n");

Mas se a gente tenta abrir a imagem que já fizemos o tratamento, nosso programa não trata esse tipo de linha. É pra tratar?

Artur
Em resposta à ARTUR SCAVONE

Re: DUVIDAS EP_04

por Rebeca Bayeh -

Já que o Artur comentou...

devemos considerar que o arquivo pgm de entrada contenha algum comentario, a ser ignorado na leitura? ou parte-se do pressuposto que há apenas o P2, a dimensao, o valor maximo e a matriz?

(tenho q impressao que estou fazendo a mesma pergunta que ele...)

Em resposta à ARTUR SCAVONE

Re: DUVIDAS EP_04

por Francisco Reverbel -
Vou considerar o tratamento de comentários como opcional. Quem fizer, terá um bônus de 1 ponto na nota do EP4. (O bônus não fará a nota passar de 10, mas ele poderá compensar algum ponto que tenha sido perdido por outro motivo.)

O que complica um pouco o tratamento de comentários é que eles podem aparecer em qualquer lugar, não necessariamente no início de uma linha. Um comentário começa com o caractere '#' e acaba no próximo new line. Todos os caracteres desde o '#' até o new line seguinte (inclusive esse new line) devem ser ignorados. Ou seja, dá na mesma escrever

12# comentario no meio de um numero!!!
34

ou escrever

1234

É mais fácil pensar no tratamento de comentários se a gente supõe que eles aparecem sempre no início de linha, ou pelo menos que eles não aparecem no meio de um número ou de uma palavra (poderia haver um comentário no meio do "P2"). Mas não é muito difícil aceitar comentários em qualquer lugar! Dica para quem quiser tratar comentários:
olhem a função ungetc, definida em <stdio.h>. Essa função facilita bastante o tratamento de comentários em qualquer lugar.
Em resposta à Daniel Amorim de Oliveira

Re: DUVIDAS EP_04

por ARTUR SCAVONE -
Eu estive fazendo testes. Com todas as imagens (mesmo qdo não são matrizes quadradas) o programa funciona. Com o kid.pgm não funciona. Eu abri com o textpad.exe, um programa de edição de textos. O kid.pgm, apesar de informar uma matriz de 320 x 240, tem só uma coluna! Não sei como que o Photoshop lê assim mesmo. Mas é por isso que o nosso programa dá erro.

Artur
Em resposta à Daniel Amorim de Oliveira

Re: DUVIDAS EP_04

por Francisco Reverbel -
Dei uma olhada no arquivo que o Daniel anexou. Tem algo errado no seu programa, Daniel... Será que ele está funcionando só para imagens quadradas? Naquele diretório com imagens sujas, o arquivo kid.pgm é o único com uma imagem que não é quadrada.
Em resposta à Francisco Reverbel

Re: DUVIDAS EP_04

por Francisco Reverbel -
Só agora vi a mensagem que o Artur mandou às 22:55. De fato os elementos da matriz aparecem todos um em baixo do outro no arquivo kid.pgm. Nos outros arquivos eles aparecem organizados como uma matriz. Entretanto isso não deveria ser um problema! O que interessa é a ordem em que os elementos da matriz aparecem no arquivo pgm. A disposição desses elementos em linhas e colunas é irrelevante. Para deixar a coisa mais concreta, considere este arquivo pgm que apareceu como exemplo no enunciado:
P2
5 4
16
9  4  5  0  8
10 3  2  1  7
9  1  6  3  15
1  16 9  12 7

O seguinte arquivo pgm é equivalente ao arquivo acima:
P2
5 4
16
9
4
5
0
8
10
3
2
1
7
9
1
6
3
15
1
16
9
12
7

O que interessa é que depois das linhas
P2
5 4
16
vem uma lista com 5 * 4 = 20 números, que são os elementos da matriz. Os primeiros cinco números dessa lista formam a primeira linha da matriz, os próximos cinco números formam a segunda linha, e assim por diante. A lista de 20 números poderia aparecer toda na mesma linha, ou com um número por linha (formando uma só coluna), ou em qualquer outra disposição. Claro que é interessante dispor essa lista como uma matriz (afinal ela é a lista dos elementos de uma matriz 4x5), mas isso não é obrigatório!

Talvez o seu programa esteja exigindo que a lista venha disposta como matriz. Note que é mais fácil ler a lista de números sem exigir que ela venha arranjada de modo matricial! Basta usar um "%d" para ler cada número, em vez de fazer alguma coisa mais complicada que leve em conta a presença de caracteres new line e a posição desses caracteres no arquivo de entrada.
Em resposta à Francisco Reverbel

Re: DUVIDAS EP_04

por ARTUR SCAVONE -
Ainda não descobri o problema. Mas tem a ver com a matriz ser ou não quadrada. Qdo peço vizinhança p = q = 1, a foto vem correta. Eu acho que o erro está no calculo da mediana. Mas ainda tem que analisar com calma. Não é problema de new line.

Artur
Em resposta à Francisco Reverbel

Re: DUVIDAS EP_04

por Felippe Alves Pereira -
af... eu estou com o mesmo problema...a imagem kid.pgm fica zuada. Eu criei uma imagem 30x20 para testar o funcionamento para imagens não quadradas e meu ep funcionou.
Prof, tem algum site bom para baixar mais exemplos de pgm's sujas?

vou anexar a imagem que eu fiz.
Em resposta à Daniel Amorim de Oliveira

Re: DUVIDAS EP_04

por Rebeca Bayeh -

Então é isso mesmo?

toda a parte de conferir o arquivo de entrada pode ser colocado na função read_pgm?

caso não, porque o cabeçalho inclui a string com o nome do arquivo e não um ponteiro para o próprio arquivo?

outra coisa... o enunciado pede para imprimir na tela a matriz caso a imagem seja menor que 16x16... mas o que é considerado "menor" que isso?

Em resposta à Rebeca Bayeh

Re: DUVIDAS EP_04

por Francisco Reverbel -
Sim, toda a verificação do arquivo de entrada (se ele existe, se ele é mesmo um arquivo PGM) pode e deve ser feita dentro da função read_pgm. Essa função deve abrir o arquivo (via fopen), ler as informações do arquivo e fechar o arquivo (com fclose).

Quanto à outra coisa... (O que é considerado "menor" que 16x16?) Boa pergunta! Vamos considerar "menores" que 16x16 as imagens que tem as duas dimensões menores ou iguais a 16. Assim, 10x15 e 16x16 são "menores" que 16x16, mas 4x17 não é.


Em resposta à Francisco Reverbel

Re: DUVIDAS EP_04

por Bruno Del Papa -

O programa deve exibir erro caso o usuario digite um "p" ou "q" par, ou podemos considerar um usuario ideal?

Em resposta à Bruno Del Papa

Re: DUVIDAS EP_04

por Francisco Reverbel -
Uma solução é apresentar uma mensagem de erro. Outra, mais simples, é verificar se p e q são ímpares e, caso algum seja par, silenciosamente incrementar o valor que não for par, convertendo-o em ímpar. Isso não dá trabalho nenhum e me parece melhor do que considerar que o usuário é ideal. (Com essa precaução você pode escrever o resto do programa supondo que p e q são ambos ímpares, que essa hipótese certamente estará satisfeita.)
Em resposta à Francisco Reverbel

Re: DUVIDAS EP_04

por Bruno Del Papa -
Ah, mais uma coisa: qual o "p" e "q" maximo que o programa deve aceitar? Se o usuario digitar p>m ou q>n, o programa deve exibir um erro?
Em resposta à Bruno Del Papa

Re: DUVIDAS EP_04

por cristine calil kores -

Oi. É..... talvez eu esteja enganada, tenha me confundido com alguma coisa.... mas, no enunciado do ep, diz que a matriz A tem M linhas e N colunas. Na explicaçao da leitura do arquivo de entrada, diz que os dois numeros que aparecem sao respectivamente o numero de colunas e de linhas e portanto N e M. Entretanto, no exemplo de leitura do arquivo de entrada, esses dois numeros sao armazenasdos em M e N, nesta ordem, e portanto, linhas e colunas.

É isso. Creio que alguma coisa esta trocada e estou meio confusa por causa disso.

Em resposta à cristine calil kores

Re: DUVIDAS EP_04

por ARTUR SCAVONE -
Voce acaba de matar uma charada que nos deixou atrapalhados. O erro que estávamos tendo com a imagem KID.PGM e com qq imagem que não fosse quadrada era esse. O primeiro número é LARGURA e o segundo COMPRIMENTO, portanto COLUNAS e LINHAS. Eu troquei e a figura KID.PGM deu certinho. O exemplo está errado na leitura do arquivo.

Artur
Em resposta à ARTUR SCAVONE

Re: DUVIDAS EP_04

por Daniel Amorim de Oliveira -
eu não entendi a mudança q vc fez pra dar certo....
sera q vc poderia explicar melhor???

Em resposta à Daniel Amorim de Oliveira

Re: DUVIDAS EP_04

por Daniel Amorim de Oliveira -
hahah ja descobri^^
pra contornar esse problema, na leitura temos q alterar para:

aux = fscanf(arq, "%d %d %d", &*n, &*m, &*maxval);
if (aux != 3) {
printf("Formato incorreto\n");
fclose(arq);
exit(1);
}

e na escrita, para

fprintf(saida, "P2\n%d %d\n%d\n", n, m, maxval);
Em resposta à cristine calil kores

Re: DUVIDAS EP_04

por Francisco Reverbel -
Sim, Cristine, você achou um problema no enunciado. Não é propriamente um erro, mas é um uso inconsistente das variáveis m e n que (pelo jeito) atrapalhou muita gente!

No arquivo PGM o número de colunas é o que aparece primeiro, depois vem o de linhas. Você não pode mudar isso, mas você tem toda liberdade de, no seu programa, chamar esses dois números de n (colunas) e m (linhas), ou de m (colunas) e n (linhas), ou outra coisa.

Infelizmente o enunciado não está usando os nomes m e n de forma consistente. A seção 1 usa m para linhas e n para colunas. Os protótipos das funções read_pgm e write_pgm também usam m para linhas e n para colunas. Mas o programa-exemplo, na seção 4, saiu com m para colunas e n para linhas... Por consistência com o resto do enunciado, teria sido melhor usar m para linhas e n para colunas também no programa-exemplo. Do jeito que está não é errado, mas o enunciado fica menos claro e induz a erros.
Em resposta à Bruno Del Papa

Re: DUVIDAS EP_04

por Francisco Reverbel -
Respondendo esta questão do Bruno: "Se o usuario digitar p>m ou q>n, o programa deve exibir um erro?"

Duas possibilidades, ambas aceitáveis:
  1. apresentar uma mensagem de erro, ou
  2. silenciosamente converter em m um valor de p que seja maior que m e converter em n um valor de q que seja maior que n.
Em resposta à Francisco Reverbel

Re: DUVIDAS EP_04

por Juliana Pereira de Souza -
Meu EP sempre afirma q o formato esta incorreto e naum sei mais o q fazer, nesse pedaço o codigo esta assim:

aux = fscanf(arq, "%d %d %d", &*n, &*m, &*maxval);
if (aux != 3)
{
printf("Formato incorreto\n");
fclose(arq);
return 0;
}
mas ele sempre mostra incorreto, alguem pode me ajudar?
Em resposta à Juliana Pereira de Souza

Re: DUVIDAS EP_04

por Juliana Pereira de Souza -
vi que meu problema eh na hora de ler os valores de m, n e maxval, mas não encontro problemas no codigo e ele me devolve m=0, n=0, e maxval=0. o meu problema esta no pedaço do codigo baseado no enunciado:

/*função que le um arquivo, no formato PGM*/
int read_pgm(char fname[], int M[] [MAX], int *m, int *n, int *maxval)
{
FILE *arq;
char key[128];
int aux, i, j;


/* abre arquivo para leitura */
arq = fopen(fname, "r");
if (arq == NULL) {
printf("Erro na abertura do arquivo %s\n", fname);
exit(1);
}

/* le dados do cabecalho */
aux = fscanf(arq, "%s", key);
if (aux != 1) {
printf("Erro na leitura do arquivo %s\n", fname);
fclose(arq);
exit(1);
}
if (strcmp(key, "P2") != 0) {
printf("Formato desconhecido\n");
fclose(arq);
exit(1);
}
aux = fscanf(arq, "%d %d %d", &*n, &*m, &*maxval);
if (aux != 3) {
printf("Formato incorreto\n");
fclose(arq);
exit(1);
}
........(neste ponto existe a leitura da matriz, mas eu omiti para colocar no forum)

fclose(arq);
return 0;
}
Em resposta à Juliana Pereira de Souza

Re: DUVIDAS EP_04

por Rodrigo Cordeiro Godoy -
Juliana, sugiro que você, depois de pegar as 3 variáveis (m, n e maxval), imprima-as no terminal, para descobrir se você está pegando certo elas (também imprima a aux, para você saber qual o valor dela.
As funções fscanf, scanf e sscanf devolvem o valor total de items que combinam com o que você coloca entre aspas dentro dela.
Os espaços que você colocou ali têm que bater com o que está no arquivo de leitura.
Em resposta à Rodrigo Cordeiro Godoy

Re: DUVIDAS EP_04

por Juliana Pereira de Souza -
Godoy eu fiz isso, e a função me devolve valores estranhos. quanto aos espaços, inicialmente estavam como o do enunciado e agora fiz da seguinte maneira, mas não resolveu:

/* le dados do cabecalho */
aux = fscanf(arq, "%s ", key);/*.............aqui ele le o nome P2 e me devolve corretamente, depois tem um espaço para pular a linha, jah tentei sem o espaço tambem..................*/
if (aux != 1) {
printf("Erro na leitura do arquivo %s\n", fname);
fclose(arq);
return 0;
}
if (strcmp(key, "P2") != 0) {
printf("Formato desconhecido\n");
fclose(arq);
return 0;
}
aux = fscanf(arq, "%d %d %d", &*n, &*m, &*maxval);/*.......aqui são lidos, m, n e maxval, mas os valores devolvidos não são corretos............*/
printf("m=%d, n=%d, mv=%d, aux= %d, key=%s", *m, *n, *maxval, aux, key);
/*......aqui me devolve na tela os valores tenho:


Digite o nome do arquivo de entrada: cameraman.pgm
m=16, n=2303112, mv=2294120, aux= 0, key=P2(<<<que esta correto)Formato incorreto

Digite o tamanho da vizinhanca (p q):


...........*/


if (aux != 3) {
printf("Formato incorreto\n");
fclose(arq);
return 0;
}

Em resposta à Juliana Pereira de Souza

Re: DUVIDAS EP_04

por Rodrigo Cordeiro Godoy -
Juliana, como eu disse, quando você digita entre as aspas do fscanf algo como "%d %d" ele não vai só procurar dois inteiros no stream do arquivo, ele vai procurar um número, um espaço e só então outro número.

No arquivo que você está usando como entrada, provavelmente não há espaços entre o m, o n, e o maxval.

Para evitar estes tipos de problemas você poderia escanear os %ds separados, usando apenas "%d", deste jeito o fscanf sairá procurando um inteiro para pegar no stream do arquivo, não importando se há espaços, \ns ou, cuidado, comentários entre eles.
Em resposta à Rodrigo Cordeiro Godoy

Re: DUVIDAS EP_04

por Nancy Falcao -

Eu praticamente ja tava com o ep todo pronto (as fotos tavam ficam legal) qdo resolvi testar com o exemplo q ta no ep...

9 4 5 0 8
10 3 2 1 7
9 1 6 3 15
0 3 8 10 1
1 16 9 12 7

onde a  mediana dava:

0 0 0 0 0
0 5 3 5 0
0 3 3 6 0
0 6 8 8 0
0 0 0 0 0

soh q eu nao consigo de forma alguma entender como a vizinhança

10 3 2
9 1 6
0 3 8

consegue ter como mediana o numero 3? Q conta foi usada?

falta tlvz soh isso preu poder ver o q falta corrigir ou nao no ep

Grata

Em resposta à ARTUR SCAVONE

Re: DUVIDAS EP_04

por ARTUR SCAVONE -
Rodrigo, ainda uma questão: hoje é o último dia pra entregar o EP. Eu resolvi fazer o tratamento de comentários criando um arquivo temporário onde eu gravo o original devidamente limpo. Mas agora me ocorreu uma preocupação: eu não tenho o Linux, e não sei se o SO do Linux aceita arquivos do jeito que eu montei. Eu tomo o nome original e acrescento um ".tmp" e, no fim do programa, apago o cara porque não serve pra mais nada. No meu ambiente funciona direitinho. Mas vai que o Linux não aceita algo como kid.pgm.tmp ! Aí eu tomo um zero... Kcilda...
Em resposta à ARTUR SCAVONE

Re: DUVIDAS EP_04

por Rodrigo Cordeiro Godoy -
A crianção de arquivos (escrever e abrir) em C depende do OS em que ele roda, por isso exatamente que existe um compilador para linux e outro para windows. Eles precisam ser diferentes, mas eles consertam esse tipo de coisa.

Fique sossegado, (provavelmente!) funcionará!
Em resposta à Rodrigo Cordeiro Godoy

Re: DUVIDAS EP_04

por Nancy Falcao -

Achei q fazer o programa ler figuras com comentarios dava um extrinha de ponto..

Pq apesar do warning q nao apareceu aqui no dev (warning exatamente pq quis fazer ler figuras com comentarios) funciona perfeitamente..

Em resposta à Nancy Falcao

Re: DUVIDAS EP_04

por Nancy Falcao -

Alias, alem de ninguem testar o dev pra ver os warnings q o povo ta reclamando q tao descontando e nao ocorrem.. (e continuam a descontar.. ) como o monitor pode descontar um ponto de algo q ele mesmo erra?

Ele me descontou por nao estar com a biblioteca "ctype" por causa do atoi.. sendo q pelo proprio site que vcs passaram:

http://www.cplusplus.com/reference/clibrary/cstdlib/

ele pertence a bilbioteca "stdlib"?

Retirei o stdlib qdo retirei o system("pause") e testei novamente e funcionou... ta na hora de vcs darem uma olhadinha no q ta acontecendo com o dev.. no meu caso nao vai ter problema.. mas pode ter aluno q nao ta indo tao bem nos eps por causa de warnings q o programa indicado nao esta dando..

Desculpem, mas fico pensando nos alunos q podem estar precisando dos minimos de pontos descontados por causa de warnings inexistentes..

Em resposta à Nancy Falcao

Re: DUVIDAS EP_04

por Rodrigo Cordeiro Godoy -
Realmente eu errei ao dizer que era no ctype (eu tive que ir checar em qual biblioteca que estava o atoi), mas no seu caso eu na verdade dei include nas duas bibliotecas para ter certeza que não teria problema e acabei mencionando na correção que a certa era a outra. Meu erro mesmo.
Em resposta à Nancy Falcao

Re: DUVIDAS EP_04

por Rodrigo Cordeiro Godoy -
O ponto extra de comentário foi dado para quem contornou o problema dos comentários totalmente. Eu criei um arquivo para os testes e quem não passou eu não dei o ponto extra (algumas pessoas funcionava só quando eu tirava os comentários de UM dos lugares e eu dei meio ponto extra).

Quem eu tive que tirar dois ou mais lugares eu não dei o ponto extra.
Em resposta à Rodrigo Cordeiro Godoy

Re: DUVIDAS EP_04

por Nancy Falcao -

Mas no meu caso eu testei colocando 4 comentarios diferentes e ele leu normalmente..

E nao tive nem meio ponto extra..

Em resposta à Nancy Falcao

Re: DUVIDAS EP_04

por Rodrigo Cordeiro Godoy -

Nancy, estou colocando anexado a este post a imagem que eu usei como teste.

No seu caso ele não reconhecia a extensão da imagem sem retirar o primeiro comentário, e depois de retirá-lo, o programa entrava em loop infinito para ler a imagem.

Para constar: ela abre normalmente no "eog", eye of gnome, um visualizador de imagens para o linux, e também no "irfanview" um visualizador de imagens para windows.
Em resposta à Rodrigo Cordeiro Godoy

Re: DUVIDAS EP_04

por ARTUR SCAVONE -
Eu entendi a burrada. Qdo eu retiro o \n posso juntar linhas e textos que não seriam juntados. Mas aí tem uma contradição que eu não consegui resolver: se um pilantra fizer um comentário assim:

________________________
P2#
15#so para atrapalhar
15
70
...
________________________

eu preciso eliminar o comentario e NAO juntar o 15 com o 15. Ou seja, tenho que trocar o \n por um branco.

Por outro lado, é possível ter um comentário no MEIO de uma informação? Assim, por exemplo?
________________________
P2#
1#esse é pra detonar
5 15
70
...
________________________

Aí eu não posso colocar o branco e tenho que eliminar TODO o comentario, inclusive o new line.

A rigor, pelo que entendi, um sujeito pode colocar um comentário no meio dos dados da imagem...

Tem uma dica de como usar o ungetc? Eu tentei fazer por aí, mas pelo que entendi ele trabalha com o buffer da memória, e voce consegue trocar o caracter referenciado por outro. Mas não consegui imaginar como usar isso.


Como fazer?
Artur



Em resposta à ARTUR SCAVONE

Re: DUVIDAS EP_04

por Rodrigo Cordeiro Godoy -
Artur, uma solução poderia ser você ter colocado um espaço no lugar do \n que sinaliza o final do comentário. Deste modo você não sofreria com números sendo juntados.

Na especificação do arquivo tipo pgm a única anotação sobre \n's são com respeito aos comentários. Eles sinalizam um final de comentário.

Estou colocando uma versão do feep.pgm anexado a este post que lhe mostra como um arquivo.pgm também pode ser escrito (sem perder informações sobre a imagem). Abra ele em um editor de texto para ver a diferença que não faz diferença.


Em relação ao ungetc ele serve para você devolver para o stream do arquivo algum byte (char). Deste modo se você encontrasse um número, pegando char por char e quisesse saber onde ele termina, você poderia pegar um por um e quando encontrasse algo que não fosse número, e você tiver certeza que o número terminou ali, então devolver tudo para o stream (os números, como se estivesse desempilhando-os) e pegar de uma vez um %d.

Mas eu acho que o que o professor quis dizer e que se você passasse pelo FILE todo, retirando ele os comentários (usando ungetc - você pode colocar um byte diferente do que realmente estava lá inicialmente-, sem precisar reescrever em outro lugar, como você fez) e daí passar pelo arquivo como você faria normalmente com um arquivo sem comentários.