2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




Начать новую тему Ответить на тему
 
 C++: запись и чтение файла в текстовом редакторе
Сообщение20.01.2016, 11:28 


29/12/14
28
Здравствуйте, я осваиваю "С++" по книге Страуструпа "Программирование. принципы и практика использования С++". Я внес изменения в пример книги, чтобы программа - текстовой редактор записывала текст на диск и читала с него, - программа создаёт файл но не записывает в него ничего. Не могли бы Вы подсказать что я неправильно сделал.
Вот код:
код: [ скачать ] [ спрятать ]
Используется синтаксис C++
//
// This is example code from Chapter 20.6.1 "Lines" of
// "Programming -- Principles and Practice Using C++" by Bjarne Stroustrup
//

#include "std_lib_facilities.h"

//------------------------------------------------------------------------------
typedef vector<char> Line;    // a line is a vector of characters

//------------------------------------------------------------------------------

struct Document {
    list<Line> line;    // a document is a list of lines
    Document() { line.push_back(Line()); }
};

//------------------------------------------------------------------------------


ofstream& operator<<(ofstream& ost, Document& d)
{
    char ch(0);
    while (ost<<ch)
                ost.put(ch);    // add the character
       
   
    return ost<<d
                ;
}



//istream& operator>>(istream& is, Document& d)
//{
  //  char ch;
   // while (is>>ch) {
     //   d.line.back().push_back(ch);    // add the character
       // if (ch=='\n') {
         //   d.line.push_back(Line());   // add another line
        //}
    //}
    //return is;
//}

istream& operator>>(istream& cin, Document& d)
{
    char ch;
    while (cin>>ch) {
        d.line.back().push_back(ch);    // add the character
        if (ch=='\n') {
            d.line.push_back(Line());   // add another line
        }
    }
    return cin;
}

//------------------------------------------------------------------------------

int main()
{
    Document d;
    {
       
        std::ofstream ost("Dokument", ios_base::app);
        cin >> d;
        if(!ost)
        cerr<<"File error";
        else
        {
                while (cin!=0) {ost<<d<<endl<<"proba";} ost.close();}
};
}

//------------------------------------------------------------------------------
 

 Профиль  
                  
 
 Re: Текстовый редактор
Сообщение20.01.2016, 13:36 
Заслуженный участник
Аватара пользователя


19/12/10
1546
Поясните, пожалуйста, что должна делать функция:
Используется синтаксис C++
ofstream& operator<<(ofstream& ost, Document& d)
{
    char ch(0);
    while (ost<<ch)
                ost.put(ch);    // add the character
       
   
    return ost<<d
                ;
}
:?:
И что она делает на самом деле? В частности, что делает цикл while (ost<<ch) ost.put(ch);? И чем отличается ost<<ch от ost.put(ch)? И что выполняет инструкция return ost<<d?

Также, пожалуйста, поясните при каких условиях происходит выход из функции:
Используется синтаксис C++
istream& operator>>(istream& cin, Document& d)
{
    char ch;
    while (cin>>ch) {
        d.line.back().push_back(ch);    // add the character
        if (ch=='\n') {
            d.line.push_back(Line());   // add another line
        }
    }
    return cin;
}
:?:
Конкретно, выход из цикла while (cin>>ch) {. . .} при каких условиях происходит?

-- 20 янв 2016, 13:42 --

(непонятка)

И какой был смысл в изменении оригинального имени переменной is на cin? Это, по меньшей мере, некрасиво и чревато тонкими ошибками.

В чём смысл цикла while (cin!=0) {ost<<d<<endl<<"proba";}? Он, вообще, сработает?

 Профиль  
                  
 
 Re: Текстовый редактор
Сообщение20.01.2016, 16:32 


29/12/14
28
Функция ofstream& operator<<(ofstream& ost, Document& d) это переопределение оператора вывода "<<" для типа Document.
while (ost<<ch) ost.put(ch) - означает, выводить символы, пока они есть в наличии;
"ost<<ch" - это запись логического выражения, которое истинно, пока есть в потоке символы, а ost.put(ch) - это операция добавления символов в поток стандартный вывода, т. е. то, ради чего и происходило переопределение стандартного оператора вывода "<<" для типа Document ("С++" не знает как вывести тип Document и ему это "объясняется" при переопределении).
В функции istream& operator>>(istream& cin, Document& d) выход происходит, когда в потоке ввода заканчиваются символы.
Цикл while (cin!=0) {ost<<d<<endl<<"proba";} был введен в программу Страуструпом и модифицирован мной в целях поиска ошибки, - когда была обнаружена проблема - незапись данных в файл и был попыткой проверить, выводится ли в файл хоть что то, в данном случае - слово "proba". Он не сработал и это даёт некоторую подсказку, вероятно, почему то как раз cin=0 и никогда не становилось ненулевым.

 Профиль  
                  
 
 Re: Текстовый редактор
Сообщение20.01.2016, 17:33 
Заслуженный участник
Аватара пользователя


19/12/10
1546
Vjatcheslav1 в сообщении #1092613 писал(а):
Функция ofstream& operator<<(ofstream& ost, Document& d) это переопределение оператора вывода "<<" для типа Document.
А что она делает на самом деле?

Vjatcheslav1 в сообщении #1092613 писал(а):
while (ost<<ch) ost.put(ch) - означает, выводить символы, пока они есть в наличии;
Нет, это означает — попытаться вывести символ ch в поток ost и если получилось, то снова вывести его в поток, затем вернуться в начало цикла. Думаю это не то, что вы хотели.

Vjatcheslav1 в сообщении #1092613 писал(а):
"ost<<ch" - это запись логического выражения, которое истинно, пока есть в потоке символы
Это вставка символа ch в поток ost, кроме того это выражение возвращает состояние поток ost, которое равно true если операция вставки выполнима.

Vjatcheslav1 в сообщении #1092613 писал(а):
ost.put(ch) - это операция добавления символов в поток стандартный вывода
Фактически это синоним ost<<ch (ну почти синоним), так что вы дважды вставляете один символ в поток.

А чтобы ваша функция работала так как вы хотите её можно, например, определить так:
Используется синтаксис C++
ostream& operator<<(ostream& ost, Document& d){
        for(list<Line>::iterator p = d.line.begin(); p != d.line.end(); p++)
                for(Line::iterator q = p->begin(); q != p->end(); q++)
                        ost.put(*q);
        return ost;
}

Vjatcheslav1 в сообщении #1092613 писал(а):
В функции istream& operator>>(istream& cin, Document& d) выход происходит, когда в потоке ввода заканчиваются символы.
Поток ввода cin получает значение false при вводе специального символа Ctrl+Z в новой строке (либо нажатии функциональной клавиши F6), ибо в потоке cin символы сами по себе никогда не заканчиваются.

Vjatcheslav1 в сообщении #1092613 писал(а):
Цикл while (cin!=0) {ost<<d<<endl<<"proba";} был введен в программу Страуструпом и модифицирован мной в целях поиска ошибки, - когда была обнаружена проблема - незапись данных в файл и был попыткой проверить, выводится ли в файл хоть что то, в данном случае - слово "proba". Он не сработал и это даёт некоторую подсказку, вероятно, почему то как раз cin=0 и никогда не становилось ненулевым
Видимо вы очень вольно модифицировали код Струструпа. Это очень грубая ошибка. Лучше напишите так, например:
Используется синтаксис C++
int main(){
    ofstream ost("Dokument.txt", ios::app);
    if(!ost) cerr << "File error\n";
    else{
        Document d;
        cin >> d;
        ost << d << endl;
    }
}

 Профиль  
                  
 
 Re: Текстовый редактор
Сообщение21.01.2016, 09:06 


29/12/14
28
Спасибо за помощь, - следуя этим советам я еще раз попытаюсь исправить ошибки. Если не получится, - вновь напишу в тему.
Я подумал ещё и мне пришла вот такая мысль: символы не попадают в выходной поток потому что я не доработал функцию ofstream& operator<<(ofstream& ost, Document& d).
Вот её код в моей версии:
Используется синтаксис C++
ofstream& operator<<(ofstream& ost, Document& d)
{
    char ch(0);
    while (ost<<ch)
                ost.put(ch);    // add the character
       
   
    return ost<<d
                ;
}


Здесь видно, что символы из d никак не попадают в переменную ch и, значит, не могут попасть в выходной поток и из него - файл. Попробую её доработать.
Для сравнения, вот здесь запись символа из потока в переменную прописана:
Используется синтаксис C++
istream& operator>>(istream& cin, Document& d)
{
    char ch;
    while (cin>>ch) {
        d.line.back().push_back(ch);    // add the character
        if (ch=='\n') {
            d.line.push_back(Line());   // add another line
        }
    }
    return cin;
}

 Профиль  
                  
 
 Re: Текстовый редактор
Сообщение21.01.2016, 10:29 
Заслуженный участник
Аватара пользователя


19/12/10
1546

(бурчание под нос)

И всё же я считаю, что изменение имени формального параметра is на cin было плохой идеей. Да и is.get(ch) лучше было оставить, а не менять на cin>>ch. Впрочем, и с вашими изменениями функция istream& operator>>(istream& cin, Document& d) будет работать.

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

 Профиль  
                  
 
 Re: C++: запись и чтение файла в текстовом редакторе
Сообщение22.01.2016, 01:23 
Админ форума
Аватара пользователя


19/03/10
8952
 i  Отделено от темы «Текстовый редактор»

 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 7 ] 

Модераторы: Karan, Toucan, PAV, maxal, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group