Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Расширенный поиск в структуре стрингов


Автор: plastiv 7.6.2007, 22:23
Помогите разобраться как организовывается поиск в структуре стрингов. Когда я провожу не точную проверку на наличие таких символов, а смогу вводить часть фамилии (оценки или группы)и по этому запросу выводить всю строчку структуры. Попутно возник вопрос: как сортировать стринги по возрастанию, алфавиту? 

Код

typedef struct student {
    string name; 
    string group;
    string mark;
}
stud;

Автор: zkv 7.6.2007, 22:31
plastiv, самый важный вопрос, что можно использовать? 
Если юзать STL, то задача решается быстро и просто. Если изобретать велосипеды, то... подольше будет... smile  

Автор: plastiv 7.6.2007, 22:37
Да, STL нужно

Автор: zkv 8.6.2007, 00:15
для примера:
Код

#include <iostream>
#include <list>
#include <string>
#include <algorithm>

struct STUDENT
{
    std::string name; 
    std::string group;
    std::string mark;
}    g_SampleInit[] = 
    {
        { "Petrov",  "2121", "ud"    },
        { "Ivanov",  "1212", "neud"    },
        { "Sidorova", "3211","ud" },
        { "sidorova", "3211","ud" },
        { "Sidorov", "3211", "neud" }
    };

int g_iSampleSize = sizeof( g_SampleInit ) / sizeof( g_SampleInit[0] ); 

void PrintStudent( const STUDENT &stud );
bool LessName( const STUDENT &stud1, const STUDENT &stud2 );

class PrintIfNameContain //просто декларация class PrintIfNameContain; что-то не катит :(
{
private:
    std::string m_str;
public:
    PrintIfNameContain( const std::string &str ) 
        : m_str( str )
   {
   }

   void operator ( ) ( const STUDENT &stud ) 
   {
       if( std::string::npos != stud.name.find( m_str ) )
           PrintStudent( stud );
   }
};

int main(int argc, char* argv[])
{
    std::list< STUDENT > listStud( &g_SampleInit[0], &g_SampleInit[g_iSampleSize] );
    std::cout<<"Initial list:\n";
    std::for_each( listStud.begin(), listStud.end(), PrintStudent );

    listStud.sort( LessName );
    std::cout<<"\nSorted list:\n";
    std::for_each( listStud.begin(), listStud.end(), PrintStudent );
    
    std::cout<<"\nPrint all, with \"dor\" in name:\n";
    std::for_each( listStud.begin(), listStud.end(), PrintIfNameContain( "dor" ) );

    std::cin.get();
    return 0;
}

bool LessName( const STUDENT &stud1, const STUDENT &stud2 )
{
    return std::lexicographical_compare( &stud1.name[0], &stud1.name[stud1.name.length()],
                                         &stud2.name[0], &stud2.name[stud2.name.length()] );
}

void PrintStudent( const STUDENT &stud )
{
    std::cout<<stud.name<<"     "<<stud.group<<"     "<<stud.mark<<'\n';
}

Автор: Xenon 8.6.2007, 01:12
Черт, не успел я глянуть, а zkv уже сделал smile
Ну выложу то, что накропал:
Код

template <typename PRED, typename InIter, typename OutIter> void copy_if(InIter FIRST, InIter LAST, OutIter OUT, PRED Cond)
{
    for ( ; FIRST != LAST; ++FIRST)
        if ( Cond(*FIRST) ) OUT = *FIRST;
}

struct STUDENT
{
    std::string m_name; 
    std::string m_group;
    std::string m_mark;
    STUDENT(const std::string& name, const std::string& group, const std::string& mark): m_name(name), m_group(group), m_mark(mark) {}
};

std::ostream& operator << (std::ostream& stream, const STUDENT& obj)
{
    stream << obj.m_name << ' ' << obj.m_group << ' ' << obj.m_mark;
    return stream;
}

std::ostream& operator << (std::ostream& stream, STUDENT* obj)
{
    stream << obj->m_name << ' ' << obj->m_group << ' ' << obj->m_mark;
    return stream;
}

class almost_equal
{
private:
    std::string m_str;
public:
    bool operator()(const STUDENT& obj) 
    {
        return (obj.m_name.find(m_str) !=  std::string::npos);
    }
    bool operator()(STUDENT* obj) 
    {
        return (obj->m_name.find(m_str) !=  std::string::npos);
    }
    almost_equal(const std::string& str):m_str(str) {}
};

int main(int argc, char* argv[]) 
{
    typedef std::vector<STUDENT*> StudArr;
    StudArr stud_base;
    stud_base.push_back( new STUDENT("Anatoly Vetrov", "10", "shit") );
    stud_base.push_back( new STUDENT("Viktor Petrovich", "10", "good") );
    copy_if( stud_base.begin(), stud_base.end(), std::ostream_iterator<STUDENT*>(std::cout, "\n"), almost_equal("Vetr") );
    for (StudArr::iterator iter = stud_base.begin(); iter != stud_base.end(); ++iter) delete *iter;
    std::cin.sync();
    std::cin.get();
    return 0;
}

Автор: zkv 8.6.2007, 01:23
Зато теперь у plastiv'а будет пища для размышлений  smile  

Автор: plastiv 8.6.2007, 17:38
Спасибо! Сейчас буду разбираться.

zkv, зачем нужно лексографическое сравнение массивов?

Автор: zkv 8.6.2007, 20:26
Цитата(plastiv @  8.6.2007,  17:38 Найти цитируемый пост)
зачем нужно лексографическое сравнение массивов?

а поиск отменили уже? http://www.cplusplus.com/reference/algorithm/lexicographical_compare.html например все написано, добавить нечего

Автор: korbian 9.6.2007, 10:47
К слову, недавно использовал boost::multi_index для схожих целей, вообщем остался доволен.

Автор: plastiv 9.6.2007, 18:50
В общем-то написал код программки, посмотрите , пожалуйста, на наличие явных ляпов

Код

#include <string>           //строки
#include <iostream>            //потоки входа\выхода
#include <fstream>            //файловые потоки
#include <stdio.h>            //структура
#include <list>                //список
#include <algorithm>

using std::cout;
using std::cin;
using std::string;
using std::list;
using std::lexicographical_compare;
using std::ifstream;
using std::ofstream;
using std::ios;
using std::binary_function;
using std::input_iterator_tag;
using std::endl;

 
typedef struct student {
    string name; 
    string group;
    string mark;
}
mass;
    

//обьвление перменных
const int size = 2;
mass s[size];
mass *ss=&s[0];
int massSize = sizeof ( s ) / sizeof ( s [0] ); 


int open (); //открытие файла
void PrintStudent( const student &stud ); //вывод всего содержимого на экран
int menu (); //ф-ция экранного меню
void savexit (); //сохранение всех изменений в файл, завершение работы
void find();
void input (); //ф-ция ввода
int sort (); //ф-ция сортировки данных по алфавиту
bool LessName ( const student &stud1, const student &stud2 ); //лексографическое сравнение
void PrintFile (); //печать на экран

class PrintIfNameContain 
{
private:
    string m_str;
public:
    PrintIfNameContain( const string &str ) 
        : m_str( str )
   {
   }

   void operator ( ) ( const student &stud ) 
   {
       if( string::npos != stud.name.find( m_str ) )
           PrintStudent( stud );
   }
};





//основная main
int main()
{
   for ( ; ; ) //Бесконечный цикл выбора функций
    { 
        switch ( menu () ) 
        {
            case 1:  open ();  break; 
            case 2:  PrintFile ()  ;  break; 
            case 3:  input ();  break;
            case 4:  sort ();  break; 
            case 5:  find (); break;
            case 0:  savexit();  break; 
            default: exit(0);
        }
    }    


    return 0;
}

int open ()
{
    system ("cls");
    ifstream in ("student.txt", ios::in | ios::binary); // открываем файл для чтения
    //проверка на открытие файла
    if (!in)
        {
        cout << "Error 1: can't open student.txt \n";
        return 1;
        }

    for(int i=0; i < size; i++)
    {    
        in >> s[i].name;
        in >> s[i].group;
        in >> s[i].mark;
         }
   in.close(); // закрываем файл

   cout << "File is open \n" << endl;
   system ("pause");
   return 0;
}
int menu()
{
    int choice;
    system("cls");
 
    cout << "Choose current item: \n";
   
    cout << "================================== \n"; 
    cout << "1. Read information from file student.txt \n";
    cout << "2. Print information from file student.txt on screen \n";
    cout << "3. Input new information to file student.txt \n";
    cout << "4. Sort struct by nameSearch in file student.txt\n";
    cout << "5. Search in file student.txt \n";
    cout << "0. Save & exit \n\n";
    cout << "> ";
    cin >> choice;
    cout << endl;
    return choice;
}

void savexit ()
{
    ofstream fileout("student.txt", ios::out | ios::binary);
    for(int i=0; i< size; i++)             
        fileout << s[i].name << " \t\t" << s[i].group << " \t " << s[i].mark  << endl;
    fileout.close();
    system("cls");        
    exit(0);


void input ()
{
    ofstream infile ("student.txt", ios::out | ios::binary); // открываем файл для записи
    
    for ( int i = 0; i < size; i ++, ss++)
    {
        cout << "\n Input name\n";
        cin >> ss -> name;
        cout << " Input group\n";
        cin >> ss -> group;
        cout << "Input mark\n";
        cin >> ss -> mark;
        infile.write ( (char*) &s [i], sizeof s [i]); //вывод в файл
    }

    infile.close ();

}

void PrintStudent( const student &stud )
{
    cout << stud.name << "     " << stud.group << "     " << stud.mark << '\n';

}

bool LessName( const student &stud1, const student &stud2 )
{
    return lexicographical_compare( &stud1.name[0], &stud1.name[stud1.name.length()],
                                         &stud2.name[0], &stud2.name[stud2.name.length()] );
}

int sort ()
{
    system ("cls");
    list < student > listStud ( &s[0], &s[massSize] );
    cout<<"Initial list:\n";
    for_each( listStud.begin(), listStud.end(), PrintStudent );

    listStud.sort( LessName );
    cout<<"\nSorted list:\n";
    for_each( listStud.begin(), listStud.end(), PrintStudent );
    
   
    system ("pause");
    return 0;
 
}

void find ()
{
    system ("cls");
    list < student > listStud ( &s[0], &s[massSize] );
    string tmp;
    cout << "Input search text \n";
    cin >> tmp;
    cout<<"\nPrint all, with " << tmp << " in name:\n";
    for_each( listStud.begin(), listStud.end(), PrintIfNameContain( tmp ) );
    system ("pause");
}

void PrintFile ()
{
    system ("cls");
    list < student > listStud ( &s[0], &s[massSize] );
    for_each( listStud.begin(), listStud.end(), PrintStudent );
    system ("pause");
}


Автор: Xenon 9.6.2007, 19:01
plastiv, глобальные переменные - не есть хорошо. Объедини схожие по смыслы функции в пространство имен и в бесконечном цикле анализа возвращаемого значения функции menu() вместо exit(0) пиши return 0; так как exit(0) - это грубый выход smile В даном случае разницы особой вроде нет, но если ты бы в main создавал какие-либо объекты в стеке они бы не уничтожались.

Автор: DigitSphinx 9.6.2007, 22:20
Код

using std::cout;
using std::cin;
using std::string;
using std::list;
using std::lexicographical_compare;
using std::ifstream;
using std::ofstream;
using std::ios;
using std::binary_function;
using std::input_iterator_tag;
using std::endl;

просто 
Код

using namespace std;

 smile 

Автор: zkv 9.6.2007, 22:59
Цитата(DigitSphinx @  9.6.2007,  22:20 Найти цитируемый пост)
просто

угу, только "просто" не всегда лучше, особенно если учесть страсть автора задавать имена функций в нижнем регистре  smile Есть вероятность нарваться на предопределенную.

Автор: Xenon 9.6.2007, 23:20
DigitSphinx, в CPP файлах вообще не рекомендуется using директивы использовать, а почему zkv уже сказал

Автор: plastiv 11.6.2007, 18:45
Если сделать динамическую структуру, то при вводе значений надо поставить символ, отвечающий за завершение набора - подскажите как правильно его описать?

Автор: DigitSphinx 11.6.2007, 21:36
zkvXenon, Спасибо не знал  smile 
Цитата(plastiv @  9.6.2007,  18:50 Найти цитируемый пост)
 посмотрите , пожалуйста, на наличие явных ляпов

Не рекомендуется использовать system ("pause"); короче это не есть хорошо !
Лучше getch(), cin.get() 

Автор: JackYF 12.6.2007, 14:02
Цитата(DigitSphinx @  11.6.2007,  21:36 Найти цитируемый пост)
Лучше getch()


лучше getchar() - она кроссплатформенная. В отличие от Борладовского getch().

Автор: Xenon 12.6.2007, 15:23
JackYF, Он разве борлондовский? В VS он тоже ведь есть.

Автор: JackYF 12.6.2007, 16:16
Цитата(Xenon @  12.6.2007,  15:23 Найти цитируемый пост)
В VS он тоже ведь есть. 

Ноги у него пошли точно от Борланда, так как он был определен в нестандартной борландовской либе <conio.h> еще в 90-м году.

Цитата(Xenon @  12.6.2007,  15:23 Найти цитируемый пост)
В VS он тоже ведь есть.

Допустим. Но в Linux'ах его точно нету. Зато getchar() есть.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)