Помощь - Поиск - Пользователи - Календарь
Полная версия: Работа со строками
Форум «Всё о Паскале» > Современный Паскаль и другие языки > Ада и другие языки
Neonig
Прошу Вас изучить программу. Далее задание.
Проблем собственно в том, что стоит создать файл тысячи на 2 - 3 сток, как программа перестает функционировать, но и это пол беды, основная заключается в том, что на примере 1000 строк время выполнение ужасно долгое...в остальном она функционирует, т.е. на маленьких файлах все отличняком, а вот на таких тестах обваливается - прошу помочь.... очень надо


Задание

Определите две реализации класса String. Требования:
Первая реализация. Каждый экземпляр класса содержит свой динамический буфер для хранения данных
Вторая реализация (использование механизма "copy on write"). Экземпляры классов, содержащие одинаковые данные (такие экземпляры можно получить, например, при операции присваивания либо через конструктор копирования), содержат ссылку на один и тот же буфер с данными.
Основные операторы, которые должны быть реализованы в классе String:

· String& operator = (const String& src)

· String& operator += (const String& right)

· String& operator += (const char* right)

· String operator + (const String& left, const String& right)

· String operator + (const String& left, const char * right)

· String operator + (const char* left, const String& right)

· bool operator == (const String& left, const String& right)

· bool operator != (const String& left, const String& right)
Для сравнения производительности этих двух реализаций напишите тестовую программу.
Код

test.c


// время выводится в тактах!!!

#include <time.h>
#include <iostream>
#include <fstream>
#include <stdio.h>
#include "strin.h"
#include "cont.h"
#include "copywrite.h"
using namespace std;
long long TimeValue=0;
long long time_RDTSC()
{
//asm("rdtsc");
    _asm rdtsc
}
void time_start() { TimeValue=time_RDTSC(); }
long long time_stop()
{ return time_RDTSC()-TimeValue; }
int main()
{
    int i,j;
    char namefile[50];
    char buf[1000];
    //char* buf = (char*)malloc(sizeof(char)*2048);
    int N,len;
    ofstream outfile;
    ifstream infile;
    cout << "Vvedite name of file\n";
    cin >> namefile;
    cout << "Vvedite kolvo strok\n";
    cin >> N;
    cout << "Vvedite max dliny stroki\n";
    cin >> len;
    // создание файла
    outfile.open(namefile);
    if (!outfile)
    {
        cout << "Oshibka pri chtenii faila\n";
        return 0;
    }
    else
    {
     char * str = new char[len*100000];
    for(i=0; i<N; i++)
    {
        for(j = 0;j<len;j++)
        {
            str[j] = rand()%('z'-'a'+1)+'a';
        }
        str[len] = '\0';
        outfile << str << "\n";
    }
    delete []str;
    outfile.close();
    }
    // заполнение обоих контейнеров
    Container <Strings> cont1;
    Container <copywrite> cont2;
    infile.open(namefile);
    if (!infile)
        cout << "Oshibka\n";
    else
    {
      while(!infile.eof())
      {

        infile.getline(buf,len+1);
        if (N<20)
        cout << buf << "\n";
        Strings s1(buf);
        copywrite s2(buf);
        cont1.cont_add(s1);
        cont2.cont_add(s2);
      }
     infile.close();
    }
// сортировка классической строки
    time_start();
         sort(cont1,0,cont1.cont_size()-1);
     cout << "Vremya sortirovki klassicheskoi stroki! " << time_stop() << "\n";
     if (N<20)
     {
     for (i=0; i<cont1.cont_size(); i++)
         cont1[i].print();
     }
     // сортировка строки copy on write
    time_start();
         sort(cont2,0,cont2.cont_size()-1);
     cout << "Vremya sortirovki copy on write stroki! " << time_stop()/100 << "\n";
     if (N<20)
     {
      for (i=0; i<cont2.cont_size(); i++)
          cont2[i].print();
     }
     getchar();
     getchar();
    
    return (0);
}

________________________________________


string.h


#include <string.h>
class Strings
{
private:
    char* str;
public:
    Strings()
    {
        str = new char;
        *str = '\0';
    }
    Strings(Strings &b)
    {
      int i=0;
        while (b.str[i]!='\0')
            i++;
        str=new char[i+1];
        i=0;
        while (b.str[i]!='\0')
        {
         str[i]=b.str[i];
         i++;
        }
        str[i]='\0';
    }
    Strings(const char* str1)
    {
        int i=0;
    while(str1[i]!='\0')
        i++;
    str=new char[i+1];
    i=0;
        while (str1[i]!='\0')
        {
            str[i]=str1[i];
            i++;
        }
        str[i]='\0';
    }
    int dlinstr() const;  // длина строки
    int sravstr(const Strings& str1); // функция сравнения: 0 - равны
                                                       //1- больше, -1 - меньше
    bool operator<(const Strings& str1);
    Strings& operator=(const Strings& str1);  // оператор копирования
    void catstr(const Strings& str1); // оператор конкатенации
    void print(); // вывод строки
    ~Strings()
    {
        delete []str;
    }
};

_______________________________________________________________________________

strin.cpp


#include <string.h>
#include <iostream>
#include "strin.h"
using namespace std;
int Strings:: dlinstr() const
{
    int i=0;
    int n=0;
    while (str[i]!='\0')
    {
        n++;
        i++;
    }
    return(n);
}
bool Strings:: operator<(const Strings& str1)
{
    if (strcmp(str1.str,str)>0)
        return (true);
    else
     return (false);
}
Strings& Strings:: operator=(const Strings & str1)
{
    delete []str;
    str = new char[str1.dlinstr()+1];
    int i=0;
    while (str1.str[i]!='\0')
    {
    str[i]=str1.str[i];
    i++;
    }
    str[i]='\0';
    return (*this);
}

void Strings:: catstr(const Strings & str1)
{
    char * tmp = new char[dlinstr() + str1.dlinstr() + 1];
    
    int i=0;
    int j=0;
    while (str[i]!='\0')
    {
        tmp[i]=str[i];
        i++;
    }
    while (str1.str[j]!='\0')
    {
        tmp[i]=str1.str[j];
        i++;
        j++;
    }
    tmp[i]='\0';

    delete []str;
    str = tmp;
}
void Strings::print()
{
    cout << str << "\n";
}

_________________________________________________________


copywrite.h

class copywrite;
class block
{
private:
    char * str;
    int usecount;
public:
    block()
    {
        str=new char;
        str='\0';
        usecount=0;
    }
    block(const char * str1);
    block (block &b)
    {
        int i=0;
        while (b.str[i]!='\0')
            i++;
        str=new char[i+1];
        i=0;
        while (b.str[i]!='\0')
        {
         str[i]=b.str[i];
         i++;
        }
        str[i]='\0';
        usecount=b.usecount;
    }
         void add_count(); // добавляем указатель
         void del_count();  // удаляем указатель
         int bllen() const;
         int blsrav(const block &str1);
         block& operator=(const block& str1);
         block operator+(const block& str1);
         void prin();
         ~block();
         friend class copywrite;
};


class copywrite
{
private:
    
    block *s; // указатель на блок
    copywrite(block * b); // просто конструктор
public:
    
    copywrite()
    {
        s=new block("");
        s->add_count();
    }
    copywrite(const char* );
    copywrite(const copywrite& str1); // конструктор копирования
    int cwlen(); // длина строки
    int cwsrav(const copywrite& str1); // сравнение строк
    bool operator<(const copywrite& str1);
    copywrite& operator=(const copywrite& str1); // присваивание строк
    copywrite& operator+=(const copywrite& str1); // конкатенация строк
    void print();
    ~copywrite(); // деструктор
    friend class block;
};


_____________________________________________________________


copywrite.cpp

#include "copywrite.h"
#include <iostream>
using namespace std;
// для работы с блоком
block::block(const char *str1)
{  
    int i=0;
    while(str1[i]!='\0')
        i++;
    str=new char[i+1];
    i=0;
    while (str1[i]!='\0')
    {
        str[i]=str1[i];
        i++;
    }
    str[i]='\0';
    usecount=0;
}
block& block:: operator=(const block& str1)
{
    str=str1.str;
    usecount=str1.usecount;
    return(*this);
}
void block:: add_count()
{
    usecount++;
}
void block::del_count()
{
    usecount--;
    if (usecount==0)
    {
        delete []str;
    }
}
int block:: bllen() const
{
    int i=0;
    while(str[i]!='\0')
    i++;
    return (i);
}
int block::blsrav(const block& str1)
{
    return strcmp(str1.str,str);

}
block block:: operator+(const block& str1)
{
int i=0;
    int j=0;
    char* str2=new char[bllen()+str1.bllen()+1];

    while (str[i]!='\0')
    {
        str2[i]=str[i];
        i++;
    }
    while (str1.str[j]!='\0')
    {
        str2[i]=str1.str[j];
        i++;
        j++;
    }
    str2[i]='\0';
    block bl(str2);
    delete []str2;
    return bl;
}
block::~block()
{
    delete []str;
}
// для работы со строкой
copywrite::copywrite(block * b)
{
    s=b;
    s->add_count();
    
}
copywrite::copywrite(const char *str1)
{
  s=new block(str1);
  s->add_count();

}
copywrite::copywrite(const copywrite& str1)
{
    s=str1.s;
    s->add_count();
}
int copywrite::cwlen()
{
  int i;
  i=s->bllen();
  return (i);
}
int copywrite:: cwsrav(const copywrite& str1)
{
    int j;
    j=s->blsrav(*(str1.s));
    return (j);
}
bool copywrite:: operator<(const copywrite& str1)
{
  if (s->blsrav((*str1.s))>0)
      return (true);
  else
  return (false);
}
copywrite& copywrite:: operator=(const copywrite& str1) // присваивание строк
{
     block *b=s;
     s=str1.s;
     s->add_count();
     b->del_count();
     return (*this);
}
copywrite& copywrite:: operator+=(const copywrite& str1) // конкатенация строк
{
block * b = new block(*s);
(*b)=(*s)+(*str1.s);

b->add_count();
s->del_count();
s=b;
return(*this);
}
copywrite::~copywrite()
{
    s->del_count();
}
void block::prin()
{
    cout << str << "\n";
}
void copywrite::print()
{
    s->prin();
}
______________________________________________________________


cont.h

#include <memory.h>
#include <iostream>
#include <exception>
using namespace std;
template <class mytype>
class Container
{
private:
    mytype *m;
    int size;
public:
    Container();
    class Range {};  // класс исключений      
void  cont_add(mytype data); // добавляет элемент в конец контейнера
void  cont_insert(mytype data, int pos); //вставляет элемент в позицию pos
int   cont_size() const; // размер контейнера
mytype cont_get(int pos) const; //возвращает данные из позиции pos
mytype cont_replace(mytype data, int pos); // заменяет данные в позиции pos. возвращает старые данные
mytype cont_remove(int pos); // удаляет данные из позиции pos
mytype operator[](int pos) const; // что-то типа итератора
mytype & operator[](int pos); // что-то типа итератора

~Container()
{
    delete []m;
}
};
template <class mytype>
Container <mytype>:: Container()
{
    size=0;
}
template <class mytype>
void Container<mytype>:: cont_add(mytype data) // Добавляет элемент в конец контейнера
{    
    int i;
    mytype *n;
    n=m;
    m=new mytype[sizeof(mytype)*(size+1)];
    if(n!=NULL)
    {
        for (i=0; i<size; i++)
            m[i]=n[i];
    }
    m[size]=data;
    size++;
//    delete []n;
}
template <class mytype>
void Container<mytype>:: cont_insert(mytype data, int pos){    // Вставляет злемент в позицию pos
    mytype *n=m;
    m=new mytype[sizeof(mytype)*(size+1)];
    if(pos>size)
    {
        pos = size;
    }
    if(n!=NULL)
    {
        memcpy(m,n,sizeof(mytype)*pos);
    }
    m[pos]=data;
    if (n!=NULL)
    {
        memcpy(&(m[pos+1]),&(n[pos]),sizeof(mytype)*(size-pos));
    }
    size++;
    delete []n;
}
template <class mytype>
int Container<mytype>:: cont_size()    const                // Возвращает размер контейнера
{    
    return (size);
}
template <class mytype>
mytype Container<mytype>:: cont_get(int pos) const                // Возвращает данные в позиции pos
{
if (pos>=size)
{
    throw Range();
}
return (m[pos]);
}
template <class mytype>
mytype Container<mytype>:: cont_replace(mytype data, int pos)    // Заменяет данные в позиции pos. Возвращает старые данные.
{
if(pos>=size)
{
     pos = size-1;
}
mytype d = m[pos];
m[pos] = data;
return d;
}
template <class mytype>
mytype Container<mytype>:: cont_remove(int pos)            // Удаляет данные из позиции pos. Возвращает удаленные данные.
{
if(pos>=size)
{
    throw Range();
}
mytype *n=m;
mytype p=m[pos];
if (size<=0)
{
    throw Range();
}
m=new mytype[sizeof(mytype)*(size-1)];
if (size>1)
{
    memcpy(m,n,sizeof(mytype)*pos);
    memcpy(&(m[pos]),&(n[pos+1]),sizeof(mytype)*(size-pos-1));
}
else{
    m = NULL;
}

delete []n;
size--;
return p;
}
template <class mytype>
mytype Container<mytype>::operator[](int pos) const
{
    if ((pos>=0) && (pos<size))
    return (m[pos]);
    else{throw std::out_of_range("Error position");}
}
template <class mytype>
mytype & Container<mytype>::operator[](int pos)
{
    if ((pos>=0) && (pos<size))
    return (m[pos]);
    else{throw std::out_of_range("Error position");}
}
// сортировка
template <class mytype>
void sort(Container<mytype> &cont,int l, int r)

{

    mytype x,w;

    int i,j;

    i=l; j=r;

    x=cont[(l+r)/2];

    do{

        while(cont[i]<x) i++;

        while (x<cont[j]) j--;

        if(i<=j){

            w=cont[i]; cont[i]=cont[j];

            cont[j]=w; i++; j--;

        }

    }

    while (i<j);

    if(l<j)
        sort(cont,l,j);

    if(r>i)
        sort(cont,i,r);

}

volvo
Ты бы выложил программу в архиве что-ли, а то я собрать это не могу.. В частности по причине:

Цитата
copywrite.cpp:124: error: no matching function for call to `block::block(block)'
copywrite.h:16: note: candidates are: block::block(block&)
copywrite.cpp:6: note: block::block(const char*)
И компилятор укажи, заодно...
Neonig
Вот адресок на архив с проектом....
volvo
Neonig, объясни мне вот какую вещь: у тебя задание в чем заключается? Написать класс Strings, так? Зачем ты придумываешь что-то другое еще? Есть же std::vector, если его использовать вместо твоего класса Container, то программа летает как на 1000 строк, так и на 2000. Только тебе понадобится исправить

Strings(Strings &b)
// на
Strings(const Strings &b)
иначе vector не поймет тебя...
Neonig
На производительность влияло именно это?
volvo
На производительность влиял именно написанный тобой самокат (ибо по сравнению со стандартными STL-евскими контейнерами его даже велосипедом назвать трудно)...

При использовании вектора файл из 5000 строк обрабатывается в течении секунды...
Neonig
Не мог бы ты скинуть подправленые тобой файлы?
volvo
Файл test.cpp выглядит вот так: Нажмите для просмотра прикрепленного файла

А в файле strin.h надо добавить одно слово const туда, куда я показал в посте №4...
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.