1

Тема: Робота програми з внутрішніми і зовнішніми данними.

Програма повинна зчитувати строку, яку вписує користувач, знаходити слова з непарною кількістю літер і подвоювати в них середню.

Виникло питання, як переробити цю програму так, щоб вона непрацювала з зовнішніми данними, (input.txt та output.txt), а вписувати слово в консолі і отримувати результат. Буду вдячний за конструктивну відповідь і за приклад.

З.І Прошу вибачення за російську в коді.


    #include <fstream> // Библиотека для работы с файлами
    #include <iostream> // Библиотека ввода-вывода
    #include <string.h> // Библиотека для работы со строками
     
    using namespace std;
     
    char word[30]; // Сюда будет сохраняться по одному слову
    char buffer[500000]={NULL}; // Сюда вводится текст
    char new_buffer[500000]={NULL}; // Сюда сохраняется новый текст, по ходу выполнения программы
    int i; // Счетчик для текущего буфера
    int n; // Счетчик для нового буфера
    int j; // Счетчик длины слова
    int flag=0; // Флаг для проверки
     
    void find_word(void) // Функция, которая ищет одно слово среди пробелов, запятых и прочих знаков
    {
        int count_func=0;
        while((buffer[i]>=65 && buffer[i]<=90) || (buffer[i]>=97 && buffer[i]<=122)) // Условие основывается на кодах ASCII
        {
            word[count_func]=buffer[i];
            ++count_func; ++i; ++j;
        }
    }
    void insert_space(void) // Функция, которая восполняет все пробелы и прочие знаки, которые были введены
    {
        while((buffer[i]<65) || (buffer[i]>=91 && buffer[i]<=96) || (buffer[i]>=123 && buffer[i]<=190))
        {
            new_buffer[n]=buffer[i];
            ++n; ++i;
            if(buffer[i]=='\0')
                return;
        }
    }
     
    void double_letter(void) // Функция, которая удваивает букву по центру
    {
        int y=(j-1)/2;
        int f=0;
        if((j>4)&&(j%2!=0))
        {
            for(f=0; f<=y; f++,++n)
            {
                new_buffer[n]=word[f];
            }
            new_buffer[n]=word[f-1];
            while(f<j)
            {
                new_buffer[n+1]=word[f];
                ++n; ++f;
            }
            ++n;
        }
        if((j<4)&&(j%2!=0))
        {
            if(j==1)
            {
                new_buffer[n]=word[f];
                ++n;
                new_buffer[n]=word[f];
                ++n; ++f;
            }
            if(j==3)
            {
                new_buffer[n]=word[f];
                ++n; ++f;
                new_buffer[n]=word[f];
                ++n;
                new_buffer[n]=word[f];
                ++n; ++f;
                new_buffer[n]=word[f];
                ++n; ++f;
            }
        }
        if(j%2==0)
            for(int v=0; v<j; v++, n++)
            {
                new_buffer[n]=word[v];
            }
    }
     
    void end(void) // Функция, которая проверяет закончился ли текст или нет
    {
        for(int k=0; k<10; k++)
        {
            if((buffer[i+k]>=65 && buffer[i+k]<=90) || (buffer[i+k]>=97 && buffer[i+k]<=122))
            {
                flag=1;
                return;
            }
        }
    }
     
    int main(int argc, const char * argv[])
    {
        ifstream in;
            ofstream out;
        in.open("input.txt"); // Привязка файла инпут
            out.open("output.txt"); // Привязка файла отпут
        in.getline(buffer, 500000, EOF); // Функция считывания из файла инпут
        while(buffer[i+1]!=EOF)
        {
            insert_space();
            find_word();
            double_letter();
            insert_space();
            end();
            if(flag==0)
            {
                break;
            }
            j=0; flag=0;
        }
        for(int f=0; f<=n; f++)
            out << new_buffer[f];
        return 0;
    }

2

Re: Робота програми з внутрішніми і зовнішніми данними.

Порада на майбутнє. Пишіть отак:

        ifstream cin("input.txt");
        ofstream cout("output.txt");

І буде вам щастя.
А якщо ці рядки закоментувати чи видалити, то одразу працюватимете із консоллю (зверніть увагу на назви змінних).

Подякували: G-roma1

3

Re: Робота програми з внутрішніми і зовнішніми данними.

koala написав:

Порада на майбутнє. Пишіть отак:

        ifstream cin("input.txt");
        ofstream cout("output.txt");

І буде вам щастя.
А якщо ці рядки закоментувати чи видалити, то одразу працюватимете із консоллю (зверніть увагу на назви змінних).

Негнучко: виходить - або вручну, або з файлу.
Та при тому, що покажчик на istream поліморфічно зводиться до ifstream, можна викрутитися саме цим шляхом:

istream *input = &cin;
ostream *output = &cout;
//...
input = new ifstream("test.txt", std::ifstream::in);
//...
delete input;

4

Re: Робота програми з внутрішніми і зовнішніми данними.

Bartash написав:

Негнучко: виходить - або вручну, або з файлу.

Гнучності цілком достатньо, як на мене.

Bartash написав:

Та при тому, що покажчик на istream поліморфічно зводиться до ifstream,

Не зводиться. Нащадок є предком, але предок не є нащадком.

Bartash написав:

можна викрутитися саме цим шляхом:

istream *input = &cin;
ostream *output = &cout;
//...
input = new ifstream("test.txt", std::ifstream::in);
//...
delete input;

А потім писати всюди *input, ще й (помилково) системний cin видалити? Красно дякую.

Мені здається, треба писати невеликий FAQ про різницю між ООП і АТД, і де що потрібно...

5

Re: Робота програми з внутрішніми і зовнішніми данними.

@koala
Пропозиції в студію.
Задача - максимально уніфікований інтерфейс для файлових потоків та стандартних І/О. :)

6 Востаннє редагувалося koala (15.05.2013 11:24:13)

Re: Робота програми з внутрішніми і зовнішніми данними.

Bartash написав:

@koala
Пропозиції в студію.
Задача - максимально уніфікований інтерфейс для файлових потоків та стандартних І/О. :)

a <input.txt >output.txt

Нє? :lol:

Ну а якщо серйозно, то

ifstream in;
if(...)
  in.ios::rdbuf(cin.rdbuf());
else in.open(...);
ofstream out;
if(...)
  out.ios::rdbuf(cout.rdbuf());
else out.open(...);

7

Re: Робота програми з внутрішніми і зовнішніми данними.

@G-roma: а взагалі програма страшна. Але то таке. Якщо працює - здавай. Кінець вводу зі стандартного вводу позначається Ctrl+Z.

8

Re: Робота програми з внутрішніми і зовнішніми данними.

koala написав:
Bartash написав:

@koala
Пропозиції в студію.
Задача - максимально уніфікований інтерфейс для файлових потоків та стандартних І/О. :)

a <input.txt >output.txt

Нє? :lol:

Ну а якщо серйозно, то

ifstream in;
if(...)
  in.ios::rdbuf(cin.rdbuf());
else in.open(...);
ofstream out;
if(...)
  out.ios::rdbuf(cout.rdbuf());
else out.open(...);

Дяку, буде мені досвід. :)

9

Re: Робота програми з внутрішніми і зовнішніми данними.

Мені це рішення не подобається, але воно дійсно універсальне.
Та все ж рекомендую для навчальної мети ті два рядки.

10

Re: Робота програми з внутрішніми і зовнішніми данними.

нє, ну ви хлопці тут все накрутили так...) я радий що вийша гарна дискусія, але, будь ласка, вкажіть мені на місц, які потрібно змінити, щоб досягти моєї цілі. Ващ рівень програмування набагато перевищує мій і я мало що зрозумів з вище написаного. Прошу, напишіть для тих "хто в бронепотязі" що потрібно зробити.

11

Re: Робота програми з внутрішніми і зовнішніми данними.

G-roma написав:

нє, ну ви хлопці тут все накрутили так...) я радий що вийша гарна дискусія, але, будь ласка, вкажіть мені на місц, які потрібно змінити, щоб досягти моєї цілі. Ващ рівень програмування набагато перевищує мій і я мало що зрозумів з вище написаного. Прошу, напишіть для тих "хто в бронепотязі" що потрібно зробити.

Та ж koala вказав шлях першим же постом.

//Якщо треба працювати з консоллю, закоментуйте два наступні рядки.
ifstream cin("input.txt"); 
ofstream cout("output.txt"); 
cin.getline(buffer, 500000, EOF);
//...etc

12

Re: Робота програми з внутрішніми і зовнішніми данними.

@koala

А як щодо такого:

#include <iostream>
#include <fstream>

using namespace std;

int main()
{
    ofstream cout("D:\\aa.txt");
    char c;
    cin>>c;
    cout<<c;
    ::cout<<c<<endl;
//etc
    return 0;
}

:)

13

Re: Робота програми з внутрішніми і зовнішніми данними.

@Bartash

Задача - максимально уніфікований інтерфейс для файлових потоків та стандартних І/О.

cout<<c;
::cout<<c<<endl;

В чому уніфікація, якщо використовуються різні об'єкти для доступу - cout і ::cout?

А взагалі, склав маленький список, чим мені не подобається стандартний вивід в стилі C++:
1. Перевантажені оператори зсуву мають виконувати зсув, а не ввід-вивід.
Так, всі вже звикли, але це принципово неправильно. Н.м.д.
2. Немає простого оператора вводу, який би повертав прочитане значення.
Іноді дуже хочеться зробити щось типу Calculate(cin>>value); звісно, не проблема створити шаблон

Прихований текст
template <typename T>
T read(istream is)
{
  T t;
  is>>t;
  return t;
}

але якось дивно.
3. Не можна спрямувати дані з одного потоку в інший.
Якщо вже оператор >> означає передачу значення, то чому я не можу зробити щось типу

Прихований текст
stringstream ss;
string s;
int i;
cin>>s>>ss>>i;

4. Не можна дублювати вивід в два потоки одночасно.
Знову ж таки, ніхто не забороняє визначати свої функції, але "з коробки" було б зручно.

Ну і звісно, я розумію, що C++ - не долар, щоб усім подобатися, а багатофункціональний інструмент, тому й кривості і недоформулювання стандартних засобів неминучі... але хотілося б :)

14 Востаннє редагувалося koala (15.05.2013 16:31:49)

Re: Робота програми з внутрішніми і зовнішніми данними.

А, так, ще хотів викласти ось це, хай полежить тут... Трохи порушує умови, але ж і складність трохи... гм...

Прихований текст
//#include <fstream>
#include <string>
#include <iostream>

using namespace std;

int main()
{
  //ifstream cin ( "input.txt"  );
  //ofstream cout( "output.txt" );
  string s;
  while( cin>>s )
  {
    if( s.length() % 2 )
      s.insert( s.begin() + s.length() / 2, s[ s.length() / 2 ] );
    cout<<s<<" ";
  }
}

15

Re: Робота програми з внутрішніми і зовнішніми данними.

В чому уніфікація, якщо використовуються різні об'єкти для доступу - cout і ::cout?

То я як альтернативу коментуванню локальних потоків навів. :)

16

Re: Робота програми з внутрішніми і зовнішніми данними.

А щодо недолугості/особливостей стандарту - можемо розвинути тему, якщо окремо її створите у цім розділі, бо потроху бажання розвитку цпп перетворилося на оффтоп. :)