приветствую всех.
FAKK2
В принципе из отсортированного по фамилиям списка (сохраненного в ArrayList) нужно выбрать всех клиентов, фамилии которых начинаются на заданный текст(это может быть и одна буква и фамилия целиком).
При использовании String.Compare(str, int,str,int,int) найти клиента не сложно. Далее от найденной позиции мы должны идти в право(вниз) или влево(вверх) по списку и проверить есть ли клиенты с фамилией начинающейся на указанный текст. Для этого написана отдельная функция Duplicate(ref int start, ref int end), которой мы в качестве параметров передаем гайденную позицию (два раза, т.е. мы начинаем проверку с одного места - start=end=найденной позиции).
Эта функция возвращает два значения. Это индекс начала и конца в ArrayList, между которыми находятся записи на клиентов с фамилиями начинающимися на указанный для поиска текст.
Далее данные этих клиентов нужно вывести в ListView, где можно выбрать нужного.
Да проект учебный и соответственно данные на клиентов и товар сгенерированы. В реальной жизни в программе должен быть предусмотрен ввод нормальных данных.
В общем я реализовал в конце концов это так:
- класс для клиентов
- Код: Выделить всё
using System;
using StringFunctions;
using System.Collections;
namespace Verkoop
{
public class Persoon
{
# region attributen
int persNr; ' номер клиента
string vnm; ' имя
string nm; ' фамилия
string straatNr; ' адрес
string postcode; ' почтовый индекс
string gemeente; 'город
DateTime gebDat; ' дата рождения
#endregion
# region constructors
public Persoon(int getal)
{
TimeSpan t;
DateTime startdat= new DateTime(1980,1,1);
persNr=getal;
vnm=Globals.eigennaam(Globals.nrToString(getal+1));
nm=Globals.nrToString(getal);
straatNr=Globals.inverseer(nm)+" "+(getal%100);
postcode=Convert.ToString((getal%100)*100+1000);
gemeente=Globals.nrToString((getal%100)*100+1000);
t=new TimeSpan(getal,0,0,0);
if(getal%2==0)
gebDat=startdat.Add(t);
else
gebDat=startdat.Subtract(t);
}
#endregion
# region property
public string PersoonNr
{
get{return persNr.ToString();}
}
public string VoorNaam
{
get{return vnm;}
}
public string FamilieNaam
{
get{return nm;}
}
public string Adres
{
get{return straatNr;}
}
public string Postcode
{
get{return postcode;}
}
public string Woonplaats
{
get{return gemeente;}
}
public string Datum
{
get{return gebDat.ToShortDateString();}
}
#endregion
#region vergelijking ' методы для сравнения
public class cmpNr:IComparer
{
int IComparer.Compare(object o1, object o2)
{
if(o2.GetType()==typeof(Persoon))
return ((Persoon)o1).persNr - ((Persoon)o2).persNr;
else
return ((Persoon)o1).persNr - (int)o2;
}
}
public class cmpVoorNaam:IComparer
{
int IComparer.Compare(object o1, object o2)
{
if(o2.GetType()==typeof(Persoon))
return string.Compare(((Persoon)o1).vnm, ((Persoon)o2).vnm);
else
return string.Compare(((Persoon)o1).vnm,0,(string)o2,0,((string)o2).Length);
}
}
public class cmpFamilieNaam:IComparer
{
int IComparer.Compare(object o1, object o2)
{
return string.Compare(((Persoon)o1).nm, ((Persoon)o2).nm);
}
}
public class cmpZip:IComparer
{
int IComparer.Compare(object o1, object o2)
{
return string.Compare(((Persoon)o1).postcode, ((Persoon)o2).postcode);
}
}
#endregion
}
}
- класс описания товаров
- Код: Выделить всё
using System;
using StringFunctions;
using System.Collections;
namespace Verkoop
{
public class Artikel
{
#region attributen
int artNr; 'номер товара
string artNaam; 'наименование товара
string barcode; 'Еаn13 код товара - это цыферки под баркодом
double prijs; 'цена
int voorraad; 'запас на скаладе (сток)
int minstock; 'минимальный запас(сток)
#endregion
#region konstructors
public Artikel(int volgnr)
{
artNr=volgnr+1000;
artNaam=Globals.nrToString(volgnr);
barcode=maakEan(artNr);
prijs=volgnr+(volgnr/5.0);
voorraad=volgnr/10;
Random gen=new Random(volgnr);
minstock=gen.Next(15);
}
#endregion
#region property
public string ArtNr
{
get{return artNr.ToString();}
}
public string ArtNaam
{
get{return artNaam;}
}
public string Barcode
{
get{return barcode;}
}
public double Prijs
{
get{return prijs;}
set{prijs=value;}
}
public int Voorraad
{
get{return voorraad;}
set{voorraad=value;}
}
public int Minstock
{
get{return minstock;}
set{minstock=value;}
}
#endregion
#region methods
'функция для создания Еаn13 кода по номеру страны 54, номеру фирмы производителя 8000 и номеру товара(6 следующих знаков). Последняя знак контрольная сумма. Всего 13 знаков.
private string maakEan(long artNr)
{
int somE=0;
int somO=0;
int getal=0;
string code, _artNr;
_artNr=artNr.ToString();
if(_artNr.Length<6)
{
int k=6-_artNr.Length;
for(int n=0;n<k;n++)
{
_artNr="0"+_artNr;
}
}
code="548000" + _artNr;
for(int i=0;i<code.Length;i+=2)
{
somE+=Convert.ToInt32(code.Substring(i,1));
}
for(int j=1;j<code.Length;j+=2)
{
somO+=Convert.ToInt32(code.Substring(j,1));
}
getal=10-((somE+somO*3)%10);
if(getal!=10)
return code + getal.ToString();
else
return code + "0";
}
#endregion
# region Vergelijking ' сравнения
public class cmpArtNr:IComparer
{
int IComparer.Compare(object o1, object o2)
{
if(o2.GetType()==typeof(Artikel))
return ((Artikel)o1).artNr - ((Artikel)o2).artNr;
else
return ((Artikel)o1).artNr - (int)o2;
}
}
public class cmpArtNaam:IComparer
{
int IComparer.Compare(object o1, object o2)
{
if(o2.GetType()==typeof(Artikel))
return string.Compare(((Artikel)o1).artNaam, ((Artikel)o2).artNaam);
else
return string.Compare(((Artikel)o1).artNaam,0,(string)o2,0,((string)o2).Length);
}
}
public class cmpBarcode:IComparer
{
int IComparer.Compare(object o1, object o2)
{
if(o2.GetType()==typeof(Artikel))
return string.Compare(((Artikel)o1).barcode, ((Artikel)o2).barcode);
else
return string.Compare(((Artikel)o1).barcode,(string)o2);
}
}
#endregion
}
}
- и далее код на самой форме
- Код: Выделить всё
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using StringFunctions;
namespace Verkoop
{
public class Form1 : System.Windows.Forms.Form
{
#region Form elements
[STAThread]
static void Main()
{
Application.Run(new Form1());
}
private ArrayList Klanten = new ArrayList(); 'обьявил список клиентов
private ArrayList Artikelen = new ArrayList(); 'обьявил список товаров
#region Form
#region Klanten
' создаем список клиентов
private void btnMaakKlant_Click(object sender, System.EventArgs e)
{
int n=10;
DateTime dat= DateTime.Now;
Random gen=new Random(dat.Millisecond);
int loper;
for(loper=0;loper<n;loper++)
{
Persoon p=new Persoon(gen.Next(997)); // создаем экземпляр класса
if(Klanten.IndexOf(p)<0)
{
Klanten.Add(p); // записываем его в ArrayList
}
toonKlanten(); // показываем данные в листвью.
}
}
' показываем данные на клиентов в ListView
private void toonKlanten()
{
int index=0;
lstvKlant.Items.Clear();
foreach(Persoon el1 in Klanten) // перебираем все элементы el1 типа Persoon в ArrayList Klanten
{
lstvKlant.Items.Add((index+1).ToString());
lstvKlant.Items[index].SubItems.Add(el1.PersoonNr.ToString());
lstvKlant.Items[index].SubItems.Add(el1.VoorNaam);
lstvKlant.Items[index].SubItems.Add(el1.FamilieNaam);
lstvKlant.Items[index].SubItems.Add(el1.Adres +", " + el1.Postcode +", " + el1.Woonplaats);
lstvKlant.Items[index++].SubItems.Add(el1.Datum);
}
}
' возможность сортировки по столбцам (по номеру. по фамилии и ...)
private void lstvKlant_ColumnClick(object sender, System.Windows.Forms.ColumnClickEventArgs e)
{
switch(e.Column)
{
case 1:
Klanten.Sort(new Persoon.cmpNr());
break;
case 2:
Klanten.Sort(new Persoon.cmpVoorNaam());
break;
case 3:
Klanten.Sort(new Persoon.cmpFamilieNaam());
break;
case 4:
Klanten.Sort(new Persoon.cmpZip());
break;
}
toonKlanten();
}
#endregion
#region Artikelen
' создаем список товаров
private void btnMaakArtikelen_Click(object sender, System.EventArgs e)
{
int n=10;
DateTime dat= DateTime.Now;
Random gen=new Random(dat.Millisecond);
int loper;
for(loper=0;loper<n;loper++)
{
Artikel a=new Artikel(gen.Next(997));
if(Artikelen.IndexOf(a)<0)
{
Artikelen.Add(a);
}
toonArtikelen();
}
}
'показываем товары в ListView
private void toonArtikelen()
{
int index=0;
lstvArtikel.Items.Clear();
foreach(Artikel el1 in Artikelen) // el1 type Artikel(exemplayr classa) in ArrayList Artikelen
{
lstvArtikel.Items.Add((index+1).ToString());
lstvArtikel.Items[index].SubItems.Add(el1.ArtNr);
lstvArtikel.Items[index].SubItems.Add(el1.ArtNaam);
lstvArtikel.Items[index].SubItems.Add(el1.Barcode);
lstvArtikel.Items[index].SubItems.Add(el1.Prijs.ToString());
lstvArtikel.Items[index].SubItems.Add(el1.Voorraad.ToString());
lstvArtikel.Items[index++].SubItems.Add(el1.Minstock.ToString());
}
}
#endregion
#region Zoeken klanten
'ищем клиента по его номеру
private void txtZoekNr_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e)
{
if(e.KeyChar==13)
{
lstvKl.Visible=false; 'не показываем lIstView предусмотренный для вывода дупликатов
Klanten.Sort(new Persoon.cmpNr());
int vindpos=-1;' впервоначальный момент ничего не нашли
Object zoekwarde=int.Parse(txtZoekNr.Text);
vindpos=Klanten.BinarySearch(zoekwarde, new Persoon.cmpNr());
if(vindpos>=0) ' нашли найденная позиция положительна
{
Persoon data=(Persoon)(Klanten[vindpos]);
lblKlantData.Text="KlantNr: "+data.PersoonNr+", Voornaam: "+data.VoorNaam+", Familienaam: "+data.FamilieNaam+", Adres: "+data.Adres+", "+data.Postcode+", "+data.Woonplaats+", Datum: "+data.Datum;
txtZoekArtNr.Focus();
}
else ' не нашли найденнная позиция отрицательна
{
lblKlantData.Text="Klant met dit Nr bestaat niet. Probeer op nieuw.";
txtZoekNr.Text="";
txtZoekNr.Focus();
}
}
}
' поиск клиента по имени или части имени
private void txtZoekNaam_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e)
{
if(e.KeyChar==13)
{
lstvKl.Items.Clear();
Klanten.Sort(new Persoon.cmpVoorNaam());
int vindpos=-1; ' начало поиска
Object zoekwarde=txtZoekNaam.Text;
vindpos=Klanten.BinarySearch(zoekwarde, new Persoon.cmpVoorNaam());
if(vindpos>=0) ' если нашли найденная позиция положительная
{ 'считываем данные на клмента из ArrayList в переменную data используя явный кастинг
Persoon data=(Persoon)(Klanten[vindpos]);
if(data.VoorNaam.Length==txtZoekNaam.Text.Length) 'если искали полное имя то пишем данные на клмента в label
lblKlantData.Text="KlantNr: "+data.PersoonNr+", Voornaam: "+data.VoorNaam+", Familienaam: "+data.FamilieNaam+", Adres: "+data.Adres+", "+data.Postcode+", "+data.Woonplaats+", Datum: "+data.Datum;
else ' если искали и нашли по части имени то ищем дупликаты(всех клментов с именем начинающимся на искомый текст
{
lstvKl.Visible=true; ' делаем видимым ListView для вывода данных
int begin=vindpos;
int end=vindpos;
Duplicate(ref begin, ref end);
int index=0;
for(int i=begin; i<end; i++) 'выводим данные в ListView
{
data=(Persoon)(Klanten[i]);
lstvKl.Items.Add((index+1).ToString());
lstvKl.Items[index].SubItems.Add(data.PersoonNr.ToString());
lstvKl.Items[index].SubItems.Add(data.VoorNaam);
lstvKl.Items[index].SubItems.Add(data.FamilieNaam);
lstvKl.Items[index].SubItems.Add(data.Adres +", " + data.Postcode +", " + data.Woonplaats);
lstvKl.Items[index++].SubItems.Add(data.Datum);
}
}
}
else 'если не нашли if(vindpos>=0)
{
lblKlantData.Text="Klant met dit Naam bestaat niet. Probeer op nieuw.";
txtZoekNaam.Text="";
txtZoekNaam.Focus();
}
}
}
'функция поиска дупликатов
public void Duplicate(ref int begin, ref int end)
{
Object zoekwarde=txtZoekNaam.Text;
while(Klanten.BinarySearch(begin,1,zoekwarde, new Persoon.cmpVoorNaam())>0 && begin+1>0)
{
begin--;
}
while(end<Klanten.Count && Klanten.BinarySearch(end,1,zoekwarde, new Persoon.cmpVoorNaam())>0)
{
end++;
}
} ' КАК Я ЭТО РЕАЛИЗОВАЛ МНЕ НЕ НРАВИТЬСЯ! Но как заставить сравнивать элемент ArrayList с последующим я не смог записать в коде. Потому использовал функцию бинарного поиска с параметрами начала поиска и длинны проверяемого (в данном случае 1 позиция) для проверки стоит ли на данной позиции в ArrayList элемент с такой же частью имени или нет.
'здесь мы выбираем из списка нужного клиента и выводим данные на него в label а ListView прячем опять.
private void lstvKl_SelectedIndexChanged(object sender, System.EventArgs e)
{
for(int i=0;i<lstvKl.Items.Count;i++)
{
if(lstvKl.Items[i].Selected)
{
lblKlantData.Text=lstvKl.Items[i].Text+", "+lstvKl.Items[i].SubItems[1].Text+", "+lstvKl.Items[i].SubItems[2].Text+", "+lstvKl.Items[i].SubItems[3].Text+", "+lstvKl.Items[i].SubItems[4].Text+", "+lstvKl.Items[i].SubItems[5].Text;
txtZoekArtNr.Focus();
}
}
lstvKl.Visible=false;
}
#endregion
' далее реализация продаж, тут мне все понятно и без проблем.
#region Verkoop
public Artikel dataArt;
public int index; //artikel voor verkoop tonen
public double BrPrijs, subtotaal;
string tekst;
private void txtZoekArtNr_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e)
{
if(e.KeyChar==13)
{
if(txtZoekArtNr.Text!="")
{
Artikelen.Sort(new Artikel.cmpArtNr());
//Artikelen.Sort(new Artikel.cmpBarcode()); // zoeken op 'ean13' code
int vindposArt=-1;
Object zoekArt=int.Parse(txtZoekArtNr.Text);
//Object zoekArt=txtZoekArtNr.Text; // zoeken op 'ean13' code
vindposArt=Artikelen.BinarySearch(zoekArt,new Artikel.cmpArtNr());
//vindposArt=Artikelen.BinarySearch(zoekArt,new Artikel.cmpBarcode()); // zoeken op 'ean13' code
if(vindposArt>=0)
{
dataArt=(Artikel)Artikelen[vindposArt];
lblArtNaam.Text=dataArt.ArtNaam;
lblArtPrijs.Text=dataArt.Prijs.ToString();
txtAantalArt.Focus();
}
}
else
{
verkocht(); // volgende klant
}
}
}
private void txtAntaalArt_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e)
{
if(e.KeyChar==13)
{
int aantalArt=int.Parse(txtAantalArt.Text);
if(aantalArt<Convert.ToInt32(dataArt.Voorraad))
{
subtotaal=aantalArt * Convert.ToDouble(dataArt.Prijs);
lblSubTotaal.Text=subtotaal.ToString();
btnOK.Focus();
dataArt.Voorraad-=aantalArt;
toonArtikelen();
}
else
{
MessageBox.Show("Oeps!We heben zo veel niet!","Voorraad is leeg!");
txtAantalArt.Text="";
txtAantalArt.Focus();
}
}
}
private void btnOK_Click(object sender, System.EventArgs e)
{
//artikel voor verkoop tonen
lstvVerkoop.Items.Add((index+1).ToString());
lstvVerkoop.Items[index].SubItems.Add(txtZoekArtNr.Text);
lstvVerkoop.Items[index].SubItems.Add(lblArtNaam.Text);
lstvVerkoop.Items[index].SubItems.Add(txtAantalArt.Text);
lstvVerkoop.Items[index].SubItems.Add(lblArtPrijs.Text);
lstvVerkoop.Items[index++].SubItems.Add(lblSubTotaal.Text);
//totaal verkoop berekenen en tonen
double BTW,Totaal;
BrPrijs+=subtotaal;
BTW=BrPrijs*0.21;
Totaal=BrPrijs+BTW;
lstvTotaalVerkoop.Items.Clear();
int ind=0;
lstvTotaalVerkoop.Items.Add(BrPrijs.ToString());
lstvTotaalVerkoop.Items[ind].SubItems.Add(BTW.ToString());
lstvTotaalVerkoop.Items[ind].SubItems.Add(Totaal.ToString());
// eind verkoop voor dit klant voorbereiden
tekst="Totaal te betalen: " + Totaal.ToString()+ " Euro";
// opruimen vakken voor volgende artikel
txtZoekArtNr.Text="";
txtAantalArt.Text="";
lblArtNaam.Text="";
lblArtPrijs.Text="";
lblSubTotaal.Text="";
txtZoekArtNr.Focus();
}
private void verkocht()
{
MessageBox.Show(tekst,"Verkocht!");
txtZoekNr.Text="";
txtZoekNaam.Text="";
lblKlantData.Text="";
lstvTotaalVerkoop.Items.Clear();
lstvVerkoop.Items.Clear();
txtZoekNr.Focus();
}
#endregion
}
}
В принцыпе ответ на вопрос, который я поставил в названии топика, я нашел.
- Код: Выделить всё
int begin=vindpos;
int end=vindpos;
Duplicate(ref begin, ref end);
Ларчик как оказалось просто открывался.
Но вот, повторюсь, как я реализовал поиск дупликатов с одинаковой частью имени МНЕ НЕ НРАВИТЬСЯ!
Т.е. я понимаю что должна делать эта функция.
Она получает в качестве входных параметров позицию найденного элемента в отсортированном ArrayList и должна пошагово в двух направлениях сравнивать искомое со стоящим на следующей позиции.
Для сравнения нужно использовать Comparer. Он у нас есть в классе Persoon.
Но вот как это сравнение грамотно записать в коде
while этой функции(см. первый пост)
я не знаю.
Всем наилучшие пожелания. И самые горячие поздравления с одним из самых любимых в народе Праздником 1 Мая!
Весенней солнечной и ТЕПЛОЙ погоды всем.