Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Открытие и чтение файлов в С++

20K
06 декабря 2006 года
Студeнт
14 / / 06.12.2006
Взялся делать лабораторную по сабжу, но что-то не получается открыть файл, вот пример кода:

Код:
#include <iostream.h>
#include <fstream.h>
#include <conio.h>

void main()
{
    char ch;
    ifstream in("C:\read.txt", ios::in);
    if (!in)
    {
        cout << "Can't open file!\n";
    }
    while (in)
       {
        in.get(ch);
        if(in) cout << ch;
    }
    in.close();
    getch();
}


Как вы догадались, на консоли появилось - "Can't open file!" =)
В чем ошибка? Смотрел в учебнике, так и не понял, что я делаю неправильно ...

А вообще, если у кого-то есть время и желание, вот все задание (можно взять любой вариант):

"Входной файл содержит произвольную синтаксически верную программу на С++. Необходимо выполнить один из следующих вариантов задания:

Вариант 1. В выходной файл записать все комментарии содержащиеся во входном файле на С++. Комментарии могут объявляться как знаками /*…..*/ так и //……. .

Вариант 2. В выходной файл записать все объявленные в программе переменные типа int в следующем формате:

Переменные типа int : a,b,c.

Указание: в этом варианте выходной файл должен содержать только одну строку.

Вариант 3. В выходной файл записать все циклы for вместе с их содержимым (в соответствие с синтаксисом цикла for). Циклы разделять пустой строкой."


Жду ответов )
21K
06 декабря 2006 года
KiskaZ
15 / / 01.12.2006
твоя ошибка в написании пути к файлу.
нужно писать два слеша... например c:\\my.txt
20K
06 декабря 2006 года
Студeнт
14 / / 06.12.2006
Цитата:
нужно писать два слеша... например c:\\my.txt



Спасибо, киска ) я даже не подозревал, что нужно 2 слеша.
Может кто-нибудь поможет дальше дописать программу? =)

6.4K
07 декабря 2006 года
Host
122 / / 22.09.2005
Цитата: Студeнт
Смотрел в учебнике, так и не понял, что я делаю неправильно ...



Не внимательно смотрел - открываеш файл для записи и пытаешся из него читать.

20K
07 декабря 2006 года
Студeнт
14 / / 06.12.2006
Цитата:
Не внимательно смотрел - открываеш файл для записи и пытаешся из него читать.



Я все правильно открывал. Читай внимательней - проблема была в двойном слеше.
+ я уже немного продвинулся, могу находить нужные символы =)

21K
07 декабря 2006 года
KiskaZ
15 / / 01.12.2006
А что у тебя сейчас не получается?
533
07 декабря 2006 года
Visualex
254 / / 07.01.2005
Вот посмотри, когдато писал, может поможет. два текстовых файла, копирует посимвольно один в другой и заодним считает и в конец файла записывает сколько символов скопировано.
Код:
#include <iostream>
#include <fstream>
using namespace std;
int main(int argc, char *argv[])
{
    if(argc!=3)
    {
        cout<<"input file name"<<endl;
        return 1;
    }
    ifstream f_in(argv[1]);
    if(!f_in)
    {
        cout<<"File is not open"<<endl;
        return 1;
    }
    ofstream f_out(argv[2]);
    if(!f_out)
    {
        cout<<"File destination is not open"<<endl;
        return 1;
    }

    char ch;
    int size=0;
    f_in.unsetf(ios::skipws);
    while(!f_in.eof())
    {
        f_in>>ch;
        if(!f_out.eof())f_out<<ch;
        size++;
    }

    f_in.close();
    f_out<<endl<<"Quantity of symbols in file is: "<<size;
    f_out.close();
    return 0;
}
20K
07 декабря 2006 года
Студeнт
14 / / 06.12.2006
to Visualex
Цитата:
Вот посмотри, когдато писал, может поможет. два текстовых файла, копирует посимвольно один в другой и заодним считает и в конец файла записывает сколько символов скопировано.



Спасибо, конечно, но мне это не пригодится. Посимвольное чтение и запись я уже сам могу организовать ))
Кстати на счет количества символов - по моему лучше использовать функцию gcount(), хотя хз - я не шарю :D

to KiskaZ

Цитата:
А что у тебя сейчас не получается?



Представь себе, во время того, когда я писал тебе ответ - у меня очень продвинулась работа ). Теперь прога успешно находит символы "//" и отображает комментарии! Вот она:

Код:
#include <iostream.h>
#include <fstream.h>
#include <conio.h>
#define n 100

void main()
{
    char b[2], str[n];
    ifstream in("C:\\read.txt", ios::in, ios::binary);
    if (!in)
        cout << "Can't open file!\n";
    while (in)
    {
        in.read((char *) b, sizeof b);
        if(b[0] == '/' && b[1] == '/')
        {
            in.getline(str,n);
            cout << b[0] << b[1] << str <<"\n";
            for (int i=0; i<n;i++)
                str = 0;
        }
    }
    in.close();
    getch();
}

Но как всегда есть одно НО - если комментариев очень много, приходится очищать массив под каждую строку. Это правильно? И все равно почему-то некоторые строки не отображаются.
Вобщем потестите кому не лень на исходниках, и скажите чего можно исправить\дописать...
21K
07 декабря 2006 года
KiskaZ
15 / / 01.12.2006
Цитата: Студeнт

Но как всегда есть одно НО - если комментариев очень много, приходится очищать массив под каждую строку. Это правильно? И все равно почему-то некоторые строки не отображаются.
Вобщем потестите кому не лень на исходниках, и скажите чего можно исправить\дописать...




ты можешь не чистить каждый раз массив, если будешь использовать указатели
т.е. вместо
char b[2], str[n];
написать
char *b,*str;

а далее выделять под массив необходимую память

например b=(char *)malloc(2); --здесь под переменную в выделяется 2 байта.
в общем смысл в том, что в такой указатель записывается строка как есть, а остальное не используется.

и как я поняла тебе надо искать в строке коментарии (и они начинаются с символа //), тогда лучше ситать не по символьно, а построчно и искать в строке символ при помощи функции strstr. например ptr=strstr(ptr,"////");

в общем я делала вот так

Код:
char *str;
         str=(char*)malloc(255);
         do{
            fgets(s,LINESZ,inf);
            strcpy(str,s);
          char *ptr=strstr (s,"имя_АРМ");
            if (ptr != NULL )
            {
               int sk=strlen(s);
               int pk=strlen(ptr);
               int n;
               n=sk-pk;
               strcpy(str,"");
               strncat(str,s,n);
               //добавляем имя компьютера
               strcat(str,nameARM);
               ptr=strstr(ptr,"\\");
               strcat(str,ptr);
            }
            //имя_сервера
            ptr=strstr (s,"имя_сервера");
            if (ptr != NULL )
            {
                int sk=strlen(s);
               int pk=strlen(ptr);
               int n;
               n=sk-pk;
               strcpy(str,"");
               strncat(str,s,n);
               char *pt=strtok(nameServer,"\\");
               if (pt != NULL)
               {
               strcat(str,pt);
               }
               ptr=strstr(ptr,"\\");
               strcat(str,ptr);
            }
            fputs(str,outf);
         }while(!feof(inf));
20K
07 декабря 2006 года
Студeнт
14 / / 06.12.2006
Цитата:
ты можешь не чистить каждый раз массив, если будешь использовать указатели
т.е. вместо
char b[2], str[n];
написать
char *b,*str;

а далее выделять под массив необходимую память

например b=(char *)malloc(2); --здесь под переменную в выделяется 2 байта.
в общем смысл в том, что в такой указатель записывается строка как есть, а остальное не используется.


ака динамическое выделение памяти, я это уже встречал. Попробовал использовать указатель на b - не работает (да и зачем, чето не понял...). С str вроде все нормально.
А на счет того, что "читать не по символьно, а построчно и искать в строке символ при помощи функции strstr" - не прокатит, ибо мне нужно искать также и МНОГОСТРОЧНЫЕ комментарии (см.первый пост). (хотя это можно применить ко второму варианту - поиск значений типа "int")
Кстати я понял почему у меня прога не все комментарии находит - просто я считываю в буфер размером 2 байта, поэтому 2 рядом стоящих слеша могут оказаться в разных буферах, и поэтому не смогут интерпретироваться как "//". То бишь нужно что-то с этим сделать =) Как думаешь?

21K
07 декабря 2006 года
KiskaZ
15 / / 01.12.2006
Цитата: Студeнт
А на счет того, что "читать не по символьно, а построчно и искать в строке символ при помощи функции strstr" - не прокатит, ибо мне нужно искать также и МНОГОСТРОЧНЫЕ комментарии (см.первый пост). (хотя это можно применить ко второму варианту - поиск значений типа "int")



это же не проблема, для многострочных коментариев используется '/*' сделай условие если находишь этот символ то следуящая строка проверяется на '*/' и помещается целиком если не нашел его, а нашел, только до этого символа...

Цитата: Студeнт
ака динамическое выделение памяти, я это уже встречал.



в общем динамическое выделение памяти как раз и спасает тебя от 2-х рядом стоящих слеша оказываются в разных буферах...
Динамическое выделение памяти позволяет более рационально использовать память и ты можешь использовать не все выделенное пространство памяти... и главное очень подходит для строковых массивов не определенной длины

Цитата: Студeнт
Кстати я понял почему у меня прога не все комментарии находит - просто я считываю в буфер размером 2 байта, поэтому 2 рядом стоящих слеша могут оказаться в разных буферах, и поэтому не смогут интерпретироваться как "//". То бишь нужно что-то с этим сделать =) Как думаешь?



вот поэтому и говорю что нужно использовать построчное чтение и искать сразу '//' а не один....

Цитата: Студeнт
Попробовал использовать указатель на b - не работает



что конкретно не работает?

20K
07 декабря 2006 года
Студeнт
14 / / 06.12.2006
Цитата:
это же не проблема, для многострочных коментариев используется '/*' сделай условие если находишь этот символ то следуящая строка проверяется на '*/' и помещается целиком если не нашел его, а нашел, только до этого символа...


в том то и дело, что проблема - я не знаю как сделать переход на др. строку, и как взять все символы ДО */

На счет указателей. Я сделал, но комментарии почему-то выводятся в строчку. Вот мой код:

Код:
#include <iostream.h>
#include <fstream.h>
#include <conio.h>
#define n 100

void main()
{
    char *str, *b;
    str = (char *)malloc(50);
    b = (char *)malloc(2);
    ifstream in("C:\\read.txt", ios::in, ios::binary);
    if (!in)
        cout << "Can't open file!\n";
    while (in)
    {
        in.read((char *) b, sizeof b);
        if(*b == '/' && *(b++) == '/')
        {
            in.getline(str,*str);
            cout << *b << *(b++)<< str <<"\n";
        }
    }
    in.close();
    getch();
}


Так чтоли надо было делать? Выводит что-то типо этого "/ wqerty /// uiop[]'/.;l,mkjnbhgvc //fdxzsa" (в одну строку)
21K
07 декабря 2006 года
KiskaZ
15 / / 01.12.2006
А ты мою программу смотрел?
20K
07 декабря 2006 года
Студeнт
14 / / 06.12.2006
Смотрел, но не очень-то понял.
Можешь выложить код еще раз, но с комментариями?
3
07 декабря 2006 года
Green
4.8K / / 20.01.2000
Давай посмотрим твой код:
Код:
#include <iostream.h>
#include <fstream.h>
#include <conio.h>
#define n 100

void main()
{
    char *str, *b;
    str = (char *)[color=red]malloc[/color](50);    // malloc странно выглядит в программе на C++
    b = (char *)[color=red]malloc[/color](2);
    ifstream in("C:\\read.txt", [color=red]ios::in, ios::binary[/color]);    // ios::in - не надо, ios::bin - почему?
    if (!in)
        cout << "Can't open file!\n";
    while ([color=red]in[/color])    // надо while ( !in.eof() )
    {
        in.read((char *) b, [color=red]sizeof b[/color]);    // sizeof b = 4, читаешь 4 байта? В буфер размером 2 байта?
        if(*b == '/' && *([color=red]b++[/color]) == '/')    // Инкрементируешь указатель? Ты понимаешь куда он после этого указывает?
        {
            in.getline(str,[color=red]*str[/color]);    // А это что значит?
            cout << *b << [color=red]*(b++)[/color]<< str <<"\n";    // Читаешь данные за пределами массива?
        }
    }
    in.close();
    getch();
}


Резюме:
1. Тебе необходимо разобраться, что такое инкремент (++).
2. Тебе необходимо разобраться с указателями.
3. Тебе необходимо разобраться с тем, что такое sizeof.
4. Тебе необходимо разобраться с методом ifstream::getline, и какие аргументы в него передаются. Кстати, есть более удобная функция std::getline.
5. Не пользуйся в программах на C++ функцией malloc, используй new, а ещё лучше научись использовать подходящие классы, например std::string.

А теперь маленький примерчик,- информация к размышлению:
Код:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;

/*
comments
*/

int main()
{
    ifstream is("1.cpp");
    if(!is) return -1;

    string str;
    getline(is, str, '/');
    getline(is, str, '/');

    cout << str;

    return 0;
}
533
07 декабря 2006 года
Visualex
254 / / 07.01.2005
2Green
 
Код:
...
is.close();
...
20K
07 декабря 2006 года
Студeнт
14 / / 06.12.2006
Во-первых: На счет указателей - я их вообще не хотел использовать, это меня kiska взбаламутила. Посмотри, например, предыдущий код.

Во-вторых: То, что malloc из си - это не важно.

В-третьих: "ios::in - не надо, ios::bin - почему?" - это я тренировался :)

В-четвертых: "надо while ( !in.eof() )" почему это while(in) не катит??? Имхо тоже самое, Г. Шилдт, например, во всех примерах так пишет.

В-пятых: "sizeof b = 4, читаешь 4 байта? В буфер размером 2 байта?" Я тебя не понимаю, где ты 4 байта взял? Вроде читаю 2, в буфер из 2-х байт.

В-шестых: "Инкрементируешь указатель? Ты понимаешь куда он после этого указывает?" Здесь я конечно ступил - надо: (*b)++

В-седьмых: "in.getline(str,*str); // А это что значит?" Как я понял, это значит, что мы помещаем строку в str а *str как я понял - показывает сколько байт из строки мы возьмем. Хз, но я другого не придумал.

В-восьмых: Про std::getline я ничего не знаю.

В-девятых: std::string - тоже не знаю.

В-десятых: Я вообще мало чего знаю в С/С++ (+ это моя третья программа на С :)

В-одиннадцатых: Не понял я твой пример. Расскажи подробней про getline(is, str, '/');
3
07 декабря 2006 года
Green
4.8K / / 20.01.2000
Цитата: Visualex
2Green
 
Код:
...
is.close();
...


Нет необходимости. Это работа деструктора.

3
07 декабря 2006 года
Green
4.8K / / 20.01.2000
Цитата: Студeнт
Во-первых: На счет указателей - я их вообще не хотел использовать, это меня kiska взбаламутила. Посмотри, например, предыдущий код.


А придется, если будешь использовать C/C++.

Цитата: Студeнт

Во-вторых: То, что malloc из си - это не важно.


Если хочешь научиться грамотно использовать C++, то важно

Цитата: Студeнт

В-четвертых: "надо while ( !in.eof() )" почему это while(in) не катит??? Имхо тоже самое, Г. Шилдт, например, во всех примерах так пишет.


К сожалению, не помню, что пишет Г.Шилдт, но это некрасиво по двум причинам:
1) запись while ( !in.eof() ) более информативна - "читаем до конца";
2) while ( !in.eof() ) - работает до тех пор, пока не достигли конца, а while(in) - работает до достижения конца, потом производится попытка чтения уже из завершившегося файла, получаем ошибку и только после этого выходим.

Цитата: Студeнт

В-пятых: "sizeof b = 4, читаешь 4 байта? В буфер размером 2 байта?" Я тебя не понимаю, где ты 4 байта взял? Вроде читаю 2, в буфер из 2-х байт.


Поэтому я и советовал изучить указатели и sizeof.
sizeof указателя - это 4 байта в 32 разрядных системах

Цитата: Студeнт

В-шестых: "Инкрементируешь указатель? Ты понимаешь куда он после этого указывает?" Здесь я конечно ступил - надо: (*b)++


Нет. Ещё раз советую изучать указатели и инкремент.

Цитата: Студeнт

В-седьмых: "in.getline(str,*str); // А это что значит?" Как я понял, это значит, что мы помещаем строку в str а *str как я понял - показывает сколько байт из строки мы возьмем. Хз, но я другого не придумал.


Ну так сколько возьмем? :)

Цитата: Студeнт

В-восьмых: Про std::getline я ничего не знаю.

В-девятых: std::string - тоже не знаю.

В-десятых: Я вообще мало чего знаю в С/С++ (+ это моя третья программа на С :)

В-одиннадцатых: Не понял я твой пример. Расскажи подробней про getline(is, str, '/');


Учись, направление задано.

20K
07 декабря 2006 года
Студeнт
14 / / 06.12.2006
Я сейчас быстро отвечу, а то времени нет, дальше завтра поговорим.

Цитата:
sizeof указателя - это 4 байта в 32 разрядных системах

Ты меня совсем запутал... Дык указатель-то на тип char где же там 4 байта?

[COLOR="Red"](*b)++ ПРАВИЛЬНО[/COLOR]

ибо...Цитирую Шилдта:

Цитата:
Чтобы инкрементировать или декрементировать значение, расположенное в области памяти, адресуемой указателем, можно использовать инструкцию, подобную следующей:

(*p)++;


могу скан дать :D

3
07 декабря 2006 года
Green
4.8K / / 20.01.2000
Цитата: Студeнт

Ты меня совсем запутал... Дык указатель-то на тип char где же там 4 байта?


Читай про указатели и sizeof.

Цитата: Студeнт

[COLOR="Red"](*b)++ ПРАВИЛЬНО[/COLOR]

ибо...Цитирую Шилдта:

могу скан дать :D


А зачем тебе инкрементировать содержимое?
Допустим, по этому адресу лежит символ 'A', в результате ты сделаешь так, что там будет лежать 'B'. Ты этого добивался?

 
Код:
char str[] = "ABC";
cout << (*str)++ << endl;  // вывод "A"
cout << str << endl;  // вывод "BBC"

В результате (*str)++ измениться содержимое массива, вместо 'A' будет лежать 'B'.
Поэтому вместо "ABC", в массиве будет "BBC".
20K
07 декабря 2006 года
Студeнт
14 / / 06.12.2006
Цитата:
Ты этого добивался?


Я хотел перейти на следующий байт в буфере. Вот и все.
Ладно, пошел я спать - время-то у меня не московское :)

3
07 декабря 2006 года
Green
4.8K / / 20.01.2000
Значит Шилдт был прав, а ты нет.
Утро вечера мудренее. :)
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог