Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Алгоритм подсчета количества одинаковых строк 
:(
    Опции темы
avatara
Дата 14.11.2007, 23:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 20
Регистрация: 28.5.2004

Репутация: нет
Всего: нет



Помогите написать код подсчета количества одинаковых строк и определения начальной позиции данной строки в списке. 
Есть ListBox, в котором находятся данные типа:
АА
АА
АА
АА
АБ
АБ
АБ
АВ
АГ
АГ
АД
ЕЕ
ЕЕ
КР
КР
МО
МО
ПС

Необходимо в EditBox вывести данные таким образом:
АА - позиция 0, кол-во 4; АБ - позиция 4, кол-во 3; АВ - позиция 7, кол-во 1; АГ - позиция 8, кол-во 1; АД - позиция 10, кол-во 1; ЕЕ -  позиция 11, кол-во 2 .......     и т.д.

Данные уже отсортированы, затруднение вызывает написание кода подсчета.

Спасибо.
PM MAIL   Вверх
avatara
Дата 15.11.2007, 11:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 20
Регистрация: 28.5.2004

Репутация: нет
Всего: нет



Это надо было, чтобы узнать начальный индекс данной строки и количество.
На самом деле все немного сложнее. В проекте есть ListCtrl, в котором 2 столбца - Серия и Номер
например
ЖХ    222222
ЖЦ    222223
ЖЦ    333333
ЖЦ    222221
ЖЦ    444440
ЖЦ    344444
ЖЦ    322222
ЖЦ    311111
ЖЧ    332222
ЖЧ    355555
ЖЧ    111111
ЖЧ    355555
ЖЧ    322221
ЖЧ    355555
ЖЧ    355554
ЖЧ    355553
ЖЧ    366666
ЖЧ    366667
ЖЧ    366669
ЖЧ    366668
ЖЧ    300000
ЖЧ    363910
ХЩ    295363
в первом столбце данные уже отсортированы по алфавиту, и нужно отсортировать данные во втором столбце соответственно внутри СЕРИИ
Вот две функции

Код

void CNewMarkDlg::OnBnClickedButton2()
{
    // Подсчет количества и начала одинаковых записей
    int kol;
    kol = m_list.GetItemCount();
    CString Seria, num, Sstart;
    int count = 1;
    int pos = 0;
    for (int i = 1; i < kol; ++i)
    {
        if (m_list.GetItemText(i, 0) == m_list.GetItemText(pos, 0))
            count++;
        else
        {
            //Seria = m_list.GetItemText(pos, 0);
            //num.Format("%i", count);
            //Sstart.Format("%i", pos);
            
            PuzirikSort(pos, count); // если вместо рos и count указывать числа, то все нормально работает
            //m_str = m_str + Seria + ' ' + "поз - " + Sstart + ' ' + "кол-во - " + num;
            pos = i;
            count = 1;
        }
    }
    UpdateData(FALSE);
}
// Сортировка методом пузырька
void CNewMarkDlg::PuzirikSort(int StartIndex, int Size)
{
    int *ListAr;
    ListAr = new int[Size];
    for (int i = 0; i < Size; i++)
    {
        ListAr[i] = StrToInt(m_list.GetItemText(i, 1));
    }
    int temp;
    for (int pass = 1; pass < Size; pass++)
    {
        for (int j = 0; j < Size - 1; j++)
        {
            if (ListAr[j] > ListAr[j+1])
            {
                temp = ListAr[j];
                ListAr[j] = ListAr[j + 1];
                ListAr[j + 1] = temp;
            }
        }
    }
    CString strmass, element;
    for (i = 0; i < Size; i++)
    {
        strmass.Format("%i", ListAr[i]);
        m_list.SetItemText(StartIndex + i, 1, strmass);
    }
    delete []ListAr;
}

Сама функция сортировки PuzirikSort работает правильно, если указывать числовые значения в ее параметрах, а если использовать переменные pos и count то часть данных просто изчезает, а вместо них появляются дубликаты имеющихся.
Посмотрите, в чем проблемы. На всякий случай прикрепляю файл с проектом. В папке ДЕБАГ есть текстовые файлики с данными для загрузки.

Присоединённый файл ( Кол-во скачиваний: 6 )
Присоединённый файл  NewMark.rar 63,28 Kb
PM MAIL   Вверх
Ln78
Дата 15.11.2007, 13:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 274
Регистрация: 25.11.2006

Репутация: 1
Всего: 15



avatara, я не понял, что тебе нужно: решить задачу с сортировкой самому, или просто, чтобы было всё отсортировано. Если второе - лучше воспользоваться готовыми алгоритмами, типа sort.  Или другими контейнерами, в которых такая сортировка происходит автоматически, на этапе заполнения, например, map. Например, в твоей функции OnBnClickedButton1 можно написать что-то вроде 
Код

   CString itogo;
   std::map<CString,int> mapStr;
   int i = 0;
   while (fOpen.ReadString(str))
  {
        mapStr[str] = i;
  }
  std::map<CString,int>::iterator it;
  for(it=mapStr.begin(); it!=mapStr.end(); ++it)
  {
      stritem = ((*it).first).Mid(0,2);
      strsubitem = ((*it).first).Mid(3,9);
      m_list.InsertItem(i, stritem);
      m_list.SetItemText(i, 1, strsubitem);
      i++;
   }
   UpdateData(FALSE);

Здесь я, правда, дважды поленился: если используется не одна CString, а какая-нибудь структура, то для неё нужно определить операцию "меньше", чтобы использовать map. И лучше, по соображениям эффективности, использовать дополнительный класс - указатель на структуру, чтобы уменьшить число операций копирования. Если это интересно, я могу позже (когда будет свободное время) написать этот фрагмент с учётом этих замечаний.
PM MAIL   Вверх
avatara
Дата 15.11.2007, 14:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 20
Регистрация: 28.5.2004

Репутация: нет
Всего: нет



Да, нужно чтобы все было отсортировано - СЕРИИ по алфавиту и НОМЕРА по возрастанию внутри  серии. Серии уже отсортированы и нужно сортировать только номера в серии.
Сортировать можно как угодно, хоть собстренную делать сортировку, хоть использовать стандартные метоты. 
Я не очень силен в программировании и с контейнером map еще невстречался. 
Делаю проект  MFC application в Visual Studio 2003.net подскажите Какие инклюды сделать чтобы Ваш пример заработал.
PM MAIL   Вверх
Ln78
Дата 15.11.2007, 15:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 274
Регистрация: 25.11.2006

Репутация: 1
Всего: 15



Нужно добавить
Код

#include <map>

В самой функции я специально первую и последнюю строчки привёл из оригинала, чтобы проще можно было определить, что на что поменять. Других изменений вроде я не делал.
PM MAIL   Вверх
avatara
Дата 15.11.2007, 15:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 20
Регистрация: 28.5.2004

Репутация: нет
Всего: нет



Сделал, все заработало, за исключением одного НО. 
Серии стали сортироваться в другом порядке. 
В программе серии должны отсортированы согласно украинского алфавита

а б в г ґ д е є ж з і ї й к л м н о п р с т у ф х ц ч ш щ ю я ь

Поэтому в исходном файле, который загружается в программу, такая сортировка уже сделана по сериям согласно украинскому алфавиту

В данном случае при загрузке файла с данными происходит пересортировка серий.  И в результате серии с начальными буквами Є,  Ї,  І   становятся в самом начале списка, т.е. нарушается порядок следования букв в алфавите.

PM MAIL   Вверх
zkv
Дата 15.11.2007, 16:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата



****


Профиль
Группа: Участник Клуба
Сообщений: 2133
Регистрация: 23.7.2006
Где: Санкт-Петербург

Репутация: 16
Всего: 92



Цитата(avatara @  15.11.2007,  15:53 Найти цитируемый пост)
В данном случае при загрузке файла с данными происходит пересортировка серий.  И в результате серии с начальными буквами Є,  Ї,  І   становятся в самом начале списка, т.е. нарушается порядок следования букв в алфавите.

Цитата(Ln78 @  15.11.2007,  13:23 Найти цитируемый пост)
для неё нужно определить операцию "меньше", чтобы использовать map

PM MAIL   Вверх
avatara
Дата 15.11.2007, 16:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 20
Регистрация: 28.5.2004

Репутация: нет
Всего: нет



Цитата(Ln78 @ 15.11.2007,  13:23)
Здесь я, правда, дважды поленился: если используется не одна CString, а какая-нибудь структура, то для неё нужно определить операцию "меньше", чтобы использовать map. И лучше, по соображениям эффективности, использовать дополнительный класс - указатель на структуру, чтобы уменьшить число операций копирования. Если это интересно, я могу позже (когда будет свободное время) написать этот фрагмент с учётом этих замечаний.

Был бы очень рад, заодно и поучился бы правильно делать такое.
PM MAIL   Вверх
Ln78
Дата 15.11.2007, 18:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 274
Регистрация: 25.11.2006

Репутация: 1
Всего: 15



avatara, я, честно говоря, не силён в украинском, увидел какие-то чудные буковки, но не придал этому значения. Возможно, для украинского пройдёт такой вариант
Код


_locale_t locale;

class MyCmp
{
public:
   bool operator() (const CString& S1, const CString& S2) const
   {
      int r = _stricmp_l(LPCTSTR(S1),LPCTSTR(S2),locale);
      return r < 0;
   }
};
void CNewMarkDlg::OnBnClickedButton1()
{
    // TODO: Add your control notification handler code here
    CString m_FileName;

    m_FileName = "";
    CFileDialog OpenDialog(true, "txt", m_FileName, OFN_FILEMUSTEXIST | OFN_HIDEREADONLY, "Text Files (*.txt)|*.txt||");

   locale = _create_locale(LC_ALL, "Ukrainian");

    if (OpenDialog.DoModal() == IDOK)
    {
        CStdioFile fOpen(OpenDialog.GetPathName(), CFile::modeRead);
        CString str, stritem, strsubitem;
        CString itogo;
      std::map<CString,int,MyCmp> mapStr;
        int i = 0;
        while (fOpen.ReadString(str))
        {
         mapStr[str] = i;
        }
      std::map<CString,int,MyCmp>::iterator it;
      for(it=mapStr.begin(); it!=mapStr.end(); ++it)
      {
         stritem = ((*it).first).Mid(0,2);
         strsubitem = ((*it).first).Mid(3,9);
         m_list.InsertItem(i, stritem);
         m_list.SetItemText(i, 1, strsubitem);
         i++;
      }
        UpdateData(FALSE);
        fOpen.Close();
        itogo.Format("%i", i);
        m_stat.SetWindowText(itogo);
    }
    
}

Я как-то и не в состоянии проверить, правильно ли после этого работает. А сама идея с определением операции меньше здесь продемонстрирована, просто здесь - сравнение с учётом украинской (мне так кажется, ни разу до этого не делал smile ) локали. Можно, если в примере где-то уже есть реализация сравнения украинских букв, написать свою реализацию оператора bool operator() .

PM MAIL   Вверх
avatara
Дата 16.11.2007, 09:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 20
Регистрация: 28.5.2004

Репутация: нет
Всего: нет



По MSDN нашел какие надо сделать инклюды (в stdafx.h)

Код

#include <locale>
#include <iostream>
#include <tchar.h>


Выдает ошибки
error C2146: syntax error : missing ';' before identifier 'locale'
error C2501: '_locale_t' : missing storage-class or type specifiers
error C2501: 'locale' : missing storage-class or type specifiers
error C3861: '_create_locale': identifier not found, even with argument-dependent lookup

Несилен я в STL, простите.


 
PM MAIL   Вверх
Ln78
Дата 16.11.2007, 11:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 274
Регистрация: 25.11.2006

Репутация: 1
Всего: 15



avatara, это мой недосмотр, забыл дописать, что нужно добавить
Код

#include <locale.h>
#include <map>


PM MAIL   Вверх
avatara
Дата 16.11.2007, 11:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 20
Регистрация: 28.5.2004

Репутация: нет
Всего: нет



Те же самые ошибки выдает.
PM MAIL   Вверх
Ln78
Дата 16.11.2007, 11:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 274
Регистрация: 25.11.2006

Репутация: 1
Всего: 15



Странно, а хэлп что выдаёт? У меня сейчас нет под рукой 2003-й, делал в 2005-й, подключал в NewMarkDlg.cpp, никаких ошибок не выдаётся, в справке указано:
Цитата

Requirements
Routine                               Required header                   Compatibility  
_create_locale                    <locale.h>                           Windows 95, Windows 98, Windows 98 Second Edition, Windows Millennium Edition, Windows NT 4.0, Windows 2000, Windows XP Home Edition, Windows XP Professional, Windows Server 2003

попробуй сделать Rebuild
PM MAIL   Вверх
avatara
Дата 16.11.2007, 12:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 20
Регистрация: 28.5.2004

Репутация: нет
Всего: нет



Rebuild не помог, сегодня дома поставлю 2005-ю Студию и попробую.
Спасибо еще раз.
PM MAIL   Вверх
Ln78
Дата 17.11.2007, 11:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 274
Регистрация: 25.11.2006

Репутация: 1
Всего: 15



avatara, вот версия файла, чтобы работал в 2003-й VS

Присоединённый файл ( Кол-во скачиваний: 6 )
Присоединённый файл  NewMarkDlg.cpp 7,16 Kb
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Visual C++/MFC/WTL | Следующая тема »


 




[ Время генерации скрипта: 0.0534 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.