LINUX.ORG.RU

Файлы с С++


0

0

Чуваки, не понимаю такую фишку:
Из main вызываю подпрограмму в которой:

-Открываю файл с помощью fopen
-Считываю данные из него
-Закрываю с помощью fclose

После этого возвращаюсь в main и снова вызываю эту подпрограмму а fopen возвращает 0.
Значит ошибка.

Что за фигня?!! Никто не знает в чем дело?

Ответ на: комментарий от grustnoe

Главная функция:

int main(){
   ...
   newgame();
   ...
   newgame();
   return 0;
}


Вызываемая функция

int newgame(){
   clrscr();
   char pf[200];
   strcat(path, "base.inf");

   FILE *f;
   if ((f=fopen(path, "r"))==0){
      cout << "Ошибка чтения файла \"base.inf\".";
      getch();
      menu();
      return 0;
   }
   const int n=80;
   char s[n], hint[n];
   int g=0;
   while (feof(f)==0){
      fgets(s, n, f);
      fgets(s, n, f);
      g++;
   }
   g=(rand() % g) + 1;
   fclose(f);
   return 0;
   ...
}

Кстати, К примеру в Паскале я связал переменную с файлом (assign()), открыл для чтения(reset()) пороботал с ним, и вдруг мне потребовалось вернуться к началу.
Я просто снова пишу reset. А в С++ как это делается. Пока мне приходиться закрывать и снова открывать файл. Но это не рационально...
Есть ли другие способы. Аналог reset?

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

Не везет тебе ;-).
int newgame(){
   clrscr();
   char pf[200];
   strcat(path, "base.inf");
/*Где у тебя переменная path определена и где она инициализируется?*/
/*судя по всему она глобальная (что уже само по себе сакс)*/
/*но ты скорее всего ее загаживаешь :-)*/
/*кроме того в этом месте у тебя возможно переполнение (догадайся почему? ;-)) (hint! strncat)*/

   FILE *f;
   if ((f=fopen(path, "r"))==0){
      cout << "Ошибка чтения файла \"base.inf\".";
      getch();
      menu();
      return 0;
   }
// а кто будет errno смотреть? ;-) man fopen man strerror ;-)
   const int n=80;
   char s[n], hint[n];
   int g=0;
   while (feof(f)==0){
      fgets(s, n, f);
      fgets(s, n, f);
      g++;
   }
   g=(rand() % g) + 1;
   fclose(f);
   return 0;
   ...
}

// и вообще раз уж ты пишешь на плюсах пользуйся std::string
// для работы с файлами можно пользоваться стримами, но тут у 
// некоторых религия...

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

Я просто недавно начал изучать. В Паскале все просто...
А здесь один результат разными способами получить можно...

Path у меня глобальгая помоему... На я ее трогаю один раз: через параметры main узнаю путь к файлу. Так что с этим проблем нет. А еслиб и были, то в первый бы раз заглючило. А глючит только со второго, третьего и т.д.

А зачем мне errno? Об ошибке я узнаю если fopen возвращает ноль.

И переполнение отчего? Объясните новичку...

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

Потому что переменная path -- глобальная. И при втором вызове функции в ней уже лежит "base.inf". И strcat добавит в конец ещё раз тоже самое. И получится "base.infbase.inf". Которого нет. Ещё вопросы будут?

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

Вот блин, спасибо!!!
Какой я не внимательный...

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

Reset

> Кстати, К примеру в Паскале я связал переменную с файлом (assign()), открыл для чтения(reset()) пороботал с ним, и вдруг мне потребовалось вернуться к началу. Я просто снова пишу reset. А в С++ как это делается. Пока мне приходиться закрывать и снова открывать файл. Но это не рационально... Есть ли другие способы. Аналог reset?

fseek

На самом деле это не аналог reset, fseek позволяет встать на произвольную позицию в файле, в том числе и на начало.

Сейчас уже не помню, но по моему в Паскале (борландовском) что-то подобное тоже есть.

DKorolkov
()
Ответ на: комментарий от DARKTUX

>И переполнение отчего? Объясните новичку...
смотри...
ты имеешь некоторого размера переменную типа char* выделил под нее память, потом делаешь в нее strcat(path,"base.inf"); например размер path у тебя 11 байт (char path[11]), в нем у тебя содержится путь: "/home/user\0", теперь ты сделал к нему strcat(path,"base.inf"); получилась следующая строчка "/home/user/base.inf\0" размер у которой 20 байт, а выделено у тебя всего 11 байт, под досом ты можешь не заметить косяка (твоя программа просто перепишет кусок памяти, который лежит за твоей строчкой) и в программе будут появлятся иногда интересные значения в других переменных... например так
char path[11];
int length;
int id;
у тебя будет испорчено значение переменной length, а может быть и id...

Вывод:
1. Выбрасывай Borland C компилятор.
2. Выбрасывай Dos
3. Используй strncat и проверяй границы всегда внимательно если ты пишешь на C
4. ИСПОЛЬЗУЙ std::string (#include <string>) для C++ кода. и сцепляй строчки знаком "+" :-).
5. Купи книжку по C++.

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

правильно будет вот так (с учетом предположения что path 11 байт):
if(strlen(path)+8<11){
    strcat(path, "base.inf");
}

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

Гы... раз уж мне не ймется ;-)

int newgame(){
// clrscr(); нафиг не надо.
// char pf[200]; вообще не понял зачем
std::string p = std::string(path) + "base.inf";
FILE *f;
if ((f=::fopen(p.c_str(), "r"))==0){

========================================
............

>А зачем мне errno? Об ошибке я узнаю если fopen возвращает ноль.
А прочитать мануал? Открыть документацию и так вдуууумчиво? :-).
std::cout << strerror(errno) << std::endl;

eXOR ★★★★★
()
Ответ на: Reset от DKorolkov

> Я просто снова пишу reset. А в С++ как это делается.
В C++ нет функции fopen. Вообще. Это не шутка.

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

Книжка по С++ у меня есть - Павловская. Это препод нашего универа. По паскалю книга у нее хорошая вышла. А вот по с++ говорят не очень...
Посоветуйте литературу. Что б серьезно выучить с.

PS Серьезно потому что для некоторых это хобби. Для меня будущая профессия. Не пугайтесь;) Мы пока на 1 курсе;)

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

Б. Страуструп "Язык C++"
"C++ for real programmers"
"More effective C++"

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