Pergunta

Está usando fseek às operações de caráter backtrack fscanf confiável?

Como por exemplo, se eu tenho apenas ed-fscanf 10 caracteres, mas eu gostaria de recuar os 10 caracteres posso apenas fseek(infile, -10, SEEK_CUR)?

Para a maioria das situações ele funciona, mas me parece ter problemas com o ^M personagem. Aparentemente registros fseek-lo como um caractere, mas fscanf não registrá-lo, assim, no meu exemplo anterior de um bloco 10 de char contendo uma ^M exigiria fseek(infile, -11, SEEK_CUR) vez. fseek(infile, -10, SEEK_CUR) faria trazê-lo curto por 1 personagem.

Por que isso acontece?

Edit: eu estava usando fopen em modo texto

Foi útil?

Solução

Você está vendo a diferença entre um "texto" e um arquivo "binário". Quando um arquivo é aberto no modo de texto (sem 'b' no segundo argumento fopen), a biblioteca stdio pode (na verdade, must) interpretar o conteúdo do arquivo de acordo com as convenções do sistema operacional para arquivos de texto. Por exemplo, no Windows, a extremidades de linha com \ r \ n, e isso é traduzido para uma única \ n por stdio, uma vez que é a convenção C. Ao escrever para um arquivo de texto, um único \ n recebe saída como \ r \ n.

Isto torna mais fácil escrever programas portáteis C que arquivos de texto alça. Alguns detalhes tornam-se complicadas, no entanto, e fseeking é um deles. Devido a isso, o padrão C define apenas fseek em arquivos de texto em alguns casos: ao início, até o fim, para a posição atual e para uma posição anterior, que foi recuperado com ftell. Em outras palavras, você não pode calcular um local para procurar por arquivos de texto. Ou você pode, mas você tem que tomar cuidado com os todos os detalhes específicos de plataforma si mesmo.

Como alternativa, você pode usar arquivos binários e fazer as transformações de delimitação de linhas si mesmo. Mais uma vez, sofre de portabilidade.

No seu caso, se você só quer voltar para onde você última fez fscancf, o mais fácil seria usar ftell pouco antes de fscanf.

Outras dicas

Isto é porque trabalhos fseek com bytes, enquanto fscanf inteligentemente alças que o símbolo de retorno e de avanço de linha são dois bytes, e engole como um carvão animal.

fseek não tem compreensão do conteúdo do arquivo e apenas move o filepointer 10 caracteres de volta.

fscanf dependendo do sistema operacional, pode interpretar novas linhas de forma diferente; pode até ser para que fscanf irá inserir o ^ M se você estiver em DOS e do ^ M não aparece no arquivo. Verifique o manual que veio com o seu compilador C

Apenas tentei isso com VS2008 e descobriu que fscanf e fseek tratados os caracteres CR e LF, da mesma forma (como um único caractere).

Assim, com dois arquivos:

0000000: 3132 3334 3554 3738 3930 3132 3334 3536 12345X7890123456

e

0000000: 3132 3334 350d 0a37 3839 3031 3233 3435 12345..789012345

Se eu ler 15 caracteres eu chegar ao segundo '5', em seguida, procurar para trás 10 caracteres, a minha próxima leitura personagem é o 'X' no primeiro caso e o CRLF no segundo.

Este parece ser um problema específico muito OS / compilador.

Você testar o valor de retorno de fscanf? Postar algum código.

Dê uma olhada ungetc . Você pode ter que executar um loop sobre ele.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top