C stream get unget не nop?

#c #io

#c #io

Вопрос:

У меня есть следующая программа на C , и я запустил ее с помощью Visual Studio 2008 в Windows 7. Я получаю, а затем удаляю символ. После этого позиция файла изменится. Почему? Как мне обойти эту проблему?


test.txt (ссылка для скачивания ниже, если вы хотите)

 /* Comment 1 */

/* Comment 2 */
  

 #include <fstream>

int main (int argc, char ** argv) {
    char const * file = "test.txt";
    std::fstream fs(file, std::ios::in);
    std::streampos const before = fs.tellg();

    // replacing the following two lines with
    // char c = fs.peek(); results in the same problem
    char const c = fs.get();
    fs.unget();

    std::streampos const after = fs.tellg();
    fs.seekg(after);
    char const c2 = fs.get();
    fs.close();
    return 0;
}
  

  • c: 47 '/' char
  • c2: -1 'ÿ' char
  • before: {_Myoff=0 _Fpos=0 _Mystate=0 } std::fpos<int>
  • after: {_Myoff=0 _Fpos=-3 _Mystate=0 } std::fpos<int>

Добавление | std::fstream::binary в конструктор, похоже, решает проблему. Возможно, это связано с новыми строками в файле? Если да, то почему это влияет на код, который даже не приближается к чтению новой строки?

Обновлено с поиском в позиции after и получением другого символа.

Кажется, что сохранение через блокнот против Vim имеет значение. Сохранение через блокнот позволяет потоку работать нормально.

Я загрузил файл в Google docs, если вы хотите его удалить:

https://docs.google.com/leaf?id=0B8Ufd7Rk6dvHZmYyZjgwYmItMTI3MC00MDljLWJjYTctMWMxYWM0ODk1MTE2amp;hl=en_US

Комментарии:

1. Кстати, вы можете использовать std::ios::in , fstream наследует от ios .

2. Обновил мой ответ ниже.

Ответ №1:

Хорошо, используя ваш входной файл, я вижу то же поведение, что и вы. После некоторых экспериментов, похоже, что файл был в формате Unix, затем были отредактированы символы ^M (по крайней мере, так я смог его воспроизвести).

Чтобы исправить это, я отредактировал файл в Vim, выполнил «:set ff = dos», затем добавил и удалил символ, чтобы испортить файл, а затем сохранил его.

Комментарии:

1. Что касается почему, я могу только предположить, что это связано с тем, как std::streams обрабатывает символы EOL. Я просмотрел двоичные представления обоих файлов, и символы EOL и EOF — единственные различия, которые я заметил.

2. Ха-ха, теперь у вас неприятный компьютерный вирус!

Ответ №2:

Позиция файла ведет себя так, как ожидалось:

 // unget.cpp
#include <fstream>
#include <iostream>
int main ()
{
    char const * file = "test.txt";
    std::fstream fs(file, std::fstream::in);

    std::cout << fs.tellg() << std::endl; // 0
    char c = fs.get();
    std::cout << fs.tellg() << std::endl; // 1
    fs.unget();
    std::cout << fs.tellg() << std::endl; // 0

    fs.close();
    return 0;
}
  

Сборка и запуск:

 $ clang   unget.cpp 
$ ./a.out 
0
1
0
  

Или я не понимаю, в чем проблема.