LINUX.ORG.RU

Странное поведение при чтении файла, C++

 , fileio, , ,


0

3

Уже в течение 5 дней пытаюсь разобраться с необычным поведением куска программы, который должен читать файлы. Вот он:

//Вот инклуды, вообще они в файле map.h

#include <ncurses.h>
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <fstream>
#include "mapfield.h"



int Map::loadMap ( )
        {
                std::ifstream fin ( "test_map.map" );
                fin.unsetf ( std::ios_base::skipws );

                if ( !fin.is_open ( ) )
                    exit ( -1 );


                std::ofstream fout ( "test_map_log.map" ); //лог файл для отладки, выводит то, что читается в buf

                int i = 0;


                fin >> mCameraX >> mCameraY; 
                fout << mCameraX << mCameraY;
                
                char buf = 'a';

               for ( i = 0; i < mWholeMapSizeX * mWholeMapSizeY; i++ )  
               //while ( !fin.eof ( ) )
                        {
                               fin >> buf;
                               fout << buf;

                               MapField *mapfield = new MapField ( buf );
                               mapFields.push_back ( *mapfield );
                               delete mapfield;
                               
                        }
                return 0;
        }

Файл с картой лежит в той же директории, что и исполняемый файл. Ошибок открытия нет (проверка открытия проходит успешно). Gdb показывает, что данные из файла как бы читаются (все операторы выполняются, без ошибок), но при этом в buf ничего не записывается. Если в качестве условия поставить закомментированное while ( !fin.eof ( ) ), цикл уходит в бесконечный. А теперь самое забавное. Я решил попробовать написать отдельную программку, чтобы попробовать на ней различные варианты решения проблемы. Она работает. Код практически идентичен.

#include <fstream>
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <string>
        

int main ( void )
    {
        std::ifstream fin ( "test.txt" );
        fin.unsetf( std::ios_base::skipws );
        
         if ( !fin.is_open ( ) ) 
            exit ( -1 ); 
  

        std::ofstream fout ( "test_log.txt" );

        char buf = 'a';
        
        while (  !fin.eof ( ) )
                {
                    
                      fin >> buf;
                      std::cout << buf;
                      fout << buf;

                }

        std::cout << std::endl << "That's all" << std::endl;
        system ( "sleep 2" );

        return 0;
    }
Помогите решить проблему, пожалуйста) Заранее спасибо за отзывчивость.



Последнее исправление: Policeman (всего исправлений: 1)

Понатыкай assert(!cin.fail()); после каждого чтения из fin, убедись, что открыл файл на чтение в правильном режиме.

PS. Буфер из одного символа — это сильно.

theNamelessOne ★★★★★
()
Ответ на: комментарий от theNamelessOne

Надо считывать карту для рогалика, хотел попробовать потренироваться на небольшом (относительно), но достаточно серьезном проекте. И да, это первый вариант, оптимизации я буду делать, когда самое простое заработает.

Policeman
() автор топика
Ответ на: комментарий от theNamelessOne

Действительно, assert аварийно завершил программу.

Policeman
() автор топика
Ответ на: комментарий от Policeman

Хотел отредактировать сообщение, но ты уже на него ответил: assert делай не для cin, а для fin, конечно же.

Надо считывать карту для рогалика

Можешь закинуть пример карты на какой-нибудь хостинг?

theNamelessOne ★★★★★
()
Ответ на: комментарий от theNamelessOne

Попробовал отдельно поставить флаг std::ios_base::in и установить позицию в начало, но результат это не поменяло, т.е. с флагами все корректно.

Policeman
() автор топика

смотри strace и сразу всё станет понятно (скорее всего, обломился open() и там сразу будет видно, с каким errno)

DELIRIUM ☆☆☆☆☆
()
Ответ на: комментарий от DELIRIUM

Цифры после «=» — это возвращаемое значение?

open("test_map.map", O_RDONLY)          = 3
open("test_map_log.map", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 4
read(3, "1 1\n                            "..., 8191) = 2029
write(2, "game: /home/daniil/myprojects/ro"..., 118) = 118
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f431f2a3000
rt_sigprocmask(SIG_UNBLOCK, [ABRT], NULL, 8) = 0
gettid()                                = 1904
tgkill(1904, 1904, SIGABRT)             = 0
--- SIGABRT (Aborted) @ 0 (0) ---
+++ killed by SIGABRT +++
Policeman
() автор топика
Ответ на: комментарий от Policeman

КМК, это может зависеть от кода, который ты не показал.

theNamelessOne ★★★★★
()

«Потоки» - это, ИМХО, самая кривая и неюзабельная часть плюсового STL. Мало того, что обработку ошибок там можно делать более чем двумя разными способами (установка флагов + исключения, в любых комбинациях), так ещё и «состояния» там выставляются по весьма упоротой логике.

http://www.cplusplus.com/reference/ios/ios/fail/
http://www.cplusplus.com/reference/ios/ios/exceptions/

Deleted
()

Вместо

fin >> mCameraX >> mCameraY
сделай чтение всего файла в буфер, и уже содержимое буфера разбирай прочими средствами stl или ещё чем-нить.

one_more_hokum ★★★
()
Последнее исправление: one_more_hokum (всего исправлений: 1)
Ответ на: комментарий от anonymous

Плюсую. fin в состоянии ошибки после попытки чтения двух чисел из-за кривых флагов (skipws).

anonymous
()
Ответ на: комментарий от Deleted

«Потоки» - это, ИМХО, самая кривая и неюзабельная часть плюсового STL.

соглашусь

asaw ★★★★★
()
Ответ на: комментарий от anonymous

Этот флаг позволяет читать без пробелов.

А в этом и была разгадка. Надо было пробел между цифрами куда-нибудь деть, а я его загонял в

mCameraY
, который типа
int
. Поэтому ошибка и мусор на экране. В общем сам дурак.

Policeman
() автор топика

Итак, для тех, кто сюда зайдет за решением проблемы, если таковая возникнет, если вы сбрасываете флаг

std::ios_base::skipws
, не забудьте девать пробелы в /dev/null, или устанавливать этот флаг при чтении чисел/слов и прочего в переменные в вашей программе. А я не подумал, и поэтому сам дурак.

Policeman
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.