Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C++ Builder > Проблема со StringGrid


Автор: ilnur 14.1.2008, 17:16
привет.

1. загружаю файл в мемо, файл примерно такого типа
 1 2 3 4 5 
 2 3 4 6
 445 556 4
 445 445 4
 далее считываю и загружаю нужную мне инфу из мемо в стринггрид. вот так:
Код
int a1, a2, a3, a4, a5, a6;
 for (int aa=0; aa<Memo1->Lines->Count; aa++)
 {
  sscanf(Memo1->Lines->Strings[aa].c_str(),"%d %d %d %d %d %d",&a1,&a2,&a3,&a4,&a5,&a6);
  if ((a1==445))
  {
    StringGrid1->Cells[0][sg1]=a1;
    StringGrid1->Cells[1][sg1]=a2;
    StringGrid1->Cells[2][sg1]=a3;
    StringGrid1->Cells[3][sg1]=a4;
    StringGrid1->Cells[4][sg1]=a5;
    StringGrid1->Cells[5][sg1]=a6;
    sg1++;
    StringGrid1->RowCount=sg1;
  }
 }
 
проблема в том, что когда мы находим 445, то а1=445, а2=556, а3=4, а а4=6, т.е. оно берется из предыдущей строки, а мне надо чтоб если нету 4 числа, то в а4 было пусто и в стринг грид ничего не записывалось.

2. после того как загрузили инфу в стринг грид, пользователь выделяет какую то строку. значение 1 ячейки строки я вывожу в едит. в едит у меня прописано вот что:
Код
void __fastcall TForm1::Edit3Change(TObject *Sender)
{
int b2=StringGrid1->Row;
     StringGrid1->Cells[2][b2]=Edit3->Text;
}

т.е. при изменении едит значение в стринггриде тоже должно меняться. 
НО!после всех этих манипуляции, если пользователь выделит след строку, то значение едит будет = значению новой строки. а значение 1 ячйки предыдущей выделенной строки будет равняться значению 1 ячейки выбранной строки.
надеюсь понятно объяснил. 

Автор: artsb 14.1.2008, 17:29
Цитата(ilnur @  14.1.2008,  17:16 Найти цитируемый пост)
проблема в том, что когда мы находим 445, то а1=445, а2=556, а3=4, а а4=6, т.е. оно берется из предыдущей строки, а мне надо чтоб если нету 4 числа, то в а4 было пусто и в стринг грид ничего не записывалось.

тогда так:
Код

int a1=NULL, a2=NULL, a3=NULL, a4=NULL, a5=NULL, a6=NULL;


Цитата(ilnur @  14.1.2008,  17:16 Найти цитируемый пост)
НО!после всех этих манипуляции, если пользователь выделит след строку, то значение едит будет = значению новой строки. а значение 1 ячйки предыдущей выделенной строки будет равняться значению 1 ячейки выбранной строки.

Это не понял, если честно. smile

Автор: ama_kid 14.1.2008, 17:29
Цитата(ilnur @  14.1.2008,  17:16 Найти цитируемый пост)
надеюсь понятно объяснил
не совсем...
Цитата(ilnur @  14.1.2008,  17:16 Найти цитируемый пост)
т.е. оно берется из предыдущей строки
перед считыванием обнулять переменные не пробовал?
По второму пункту - я мало что понял, понял только что программа ведет себя так, как ты ей запрограммировал, осталось только понять что же ты хотел smile 

Автор: ilnur 14.1.2008, 17:42
Цитата(artsb @  14.1.2008,  17:29 Найти цитируемый пост)
тогда так:код C++ Builder1:int a1=NULL, a2=NULL, a3=NULL, a4=NULL, a5=NULL, a6=NULL;

так. теперь значение = 0, т.е. в стринг грид пишутся 0. а мне надо чтобы было пусто. для того чтобы при сохранении структура файла сохранялась
Цитата(ama_kid @  14.1.2008,  17:29 Найти цитируемый пост)
По второму пункту - я мало что понял, понял только что программа ведет себя так, как ты ей запрограммировал,
ага.

в общем вот. exe файл. попробуйте открыть 1.txt, он в архиве. и выделяя строки смотрите пердыдущую строку, 3 ячейку
http://webfile.ru/1683714

Автор: artsb 14.1.2008, 17:57
Цитата(ilnur @  14.1.2008,  17:42 Найти цитируемый пост)
теперь значение = 0, т.е. в стринг грид пишутся 0.

Тогда пишите:
Код

int a1=-1, a2=-1, a3=-1, a4=-1, a5=-1, a6=-1;

И потом перед вставкой проверяйте чему равно значение переменной. Если "-1", то ничего не вставляете.

Добавлено через 4 минуты и 18 секунд
А вообще, попробуйте так:
Объявите переменные как AnsiString 
Код

AnsiString a1=NULL, a2=NULL, a3=NULL, a4=NULL, a5=NULL, a6=NULL;

и пишите:
Код

sscanf(Memo1->Lines->Strings[aa].c_str(),"%s %s %s %s %s %s",&a1,&a2,&a3,&a4,&a5,&a6);

Остальное как есть.

P.S. только я не помню, для AnsiString %s или нет...

Автор: ilnur 14.1.2008, 18:30
Цитата(artsb @  14.1.2008,  17:57 Найти цитируемый пост)
Цитата(ilnur @  14.1.2008,  17:42 )теперь значение = 0, т.е. в стринг грид пишутся 0.Тогда пишите:код C++ Builder1:
Код

int a1=-1, a2=-1, a3=-1, a4=-1, a5=-1, a6=-1
И потом перед вставкой проверяйте чему равно значение переменной. Если "-1", то ничего не вставляете.

сдела так. всё работает. спасибо. а как быть со второй проблемой?

Автор: ama_kid 14.1.2008, 18:38
Цитата(ilnur @  14.1.2008,  17:42 Найти цитируемый пост)
выделяя строки смотрите пердыдущую строку, 3 ячейку
смотри обработчик StrinGrid.OnClick - это там у тебя косячит что-то...
Код
int a1=NULL, a2=NULL, a3=NULL, a4=NULL, a5=NULL, a6=NULL
так имхо неправильно, т.к. обнулять надо перед каждым считыванием параметром... Если не нужен 0 при занесении в стринггрид - тогда просто проверяй перед записью на равность нулю (сделай функцию которая будет возвращать соответствующую строку)...

Автор: ilnur 14.1.2008, 18:43
Цитата(ama_kid @  14.1.2008,  18:38 Найти цитируемый пост)
мотри обработчик StrinGrid.OnClick - это там у тебя косячит что-то...

только не в  OnClick, а в OnSelectCell, вот что у меня там:
Код

void __fastcall TForm1::StringGrid1SelectCell(TObject *Sender, int ACol,
      int ARow, bool &CanSelect)
{
int b1=ARow; //выделенная строка
Edit1->Text=StringGrid1->Cells[0][b1];
Edit2->Text=StringGrid1->Cells[1][b1];
Edit3->Text=StringGrid1->Cells[2][b1];
Edit4->Text=StringGrid1->Cells[3][b1];
}

т.е. чтоб значения записывались в едиты. далее пользователь может их изменить. 
в едите у меня вот такой обработчик:
Код

void __fastcall TForm1::Edit3Change(TObject *Sender)
{
int b2=StringGrid1->Row;
     StringGrid1->Cells[2][b2]=Edit3->Text;
}

чтобы изменения сохранялись сразу в стринггриде.

Автор: artsb 14.1.2008, 18:45
А вы это пробовали:

Цитата(artsb @  14.1.2008,  17:57 Найти цитируемый пост)
А вообще, попробуйте так:
Объявите переменные как AnsiString 
Выделить всёкод C++ Builder
1:
    
AnsiString a1=NULL, a2=NULL, a3=NULL, a4=NULL, a5=NULL, a6=NULL;

и пишите:
Выделить всёкод C++ Builder
1:
    
sscanf(Memo1->Lines->Strings[aa].c_str(),"%s %s %s %s %s %s",&a1,&a2,&a3,&a4,&a5,&a6);

Остальное как есть.

P.S. только я не помню, для AnsiString %s или нет... 

Может так даже лучше будет. Не нужно никаких проверок.

Автор: ama_kid 14.1.2008, 18:51
ilnur, у тебя обработчики зациклены: обработчик OnSelectCell вызывается до смены ячейки, вызывая изменение текста в Edit'е, а тот в свою очередь вызывает изменение в текущей (еще не измененной ячейке)...

Автор: ilnur 14.1.2008, 18:54
artsb, 
пробовал только при работе exe вылетала ошибка. наверное всё таки не %s
s - строка символ. тип аргумента функции - char arg[]
вот что нашёл в книжке архангелького. больше ничего. а самя не пойму что это значит

Добавлено через 1 минуту и 1 секунду
Цитата(ama_kid @  14.1.2008,  18:51 Найти цитируемый пост)
ilnur, у тебя обработчики зациклены: обработчик OnSelectCell вызывается до смены ячейки, вызывая изменение текста в Edit'е, а тот в свою очередь вызывает изменение в текущей (еще не измененной ячейке)...
ага. я понял это. но вот не додумаюсь как избавиться от этого. или сделать по другому

Автор: ama_kid 14.1.2008, 19:03
Цитата(ilnur @  14.1.2008,  18:54 Найти цитируемый пост)
но вот не додумаюсь как избавиться от этого
у тебя в OnSelectСell нет никакого кода, специфичного для этого обработчика (нет специальных проверок на возможность выбора ячейки) - следовательно просто юзай OnClick - он вроде вызывается после смены ячейки...

Автор: ilnur 14.1.2008, 19:15
ama_kid, 
ясно спасибо. вроде всё теперь работает как надо. просто через поиск нашёл тот код, который был на OnSelectСell
подправил только вот это:
Код

int b1=StringGrid1->Row; //выделенная строка
Edit1->Text=StringGrid1->Cells[0][b1];
....

Автор: artsb 14.1.2008, 19:29
Цитата(ilnur @  14.1.2008,  18:54 Найти цитируемый пост)
пробовал только при работе exe вылетала ошибка. наверное всё таки не %s
s - строка символ. тип аргумента функции - char arg[]

Я посмотрел справку. Попробуйте так:
Код

String a1="", a2="", a3="", a4="", a5="", a6="";

Должно работать...

Автор: ilnur 14.1.2008, 19:49
artsb, 
Код

String a1, a2, a3, a4, a5, a6;
 for (int aa=0; aa<Memo1->Lines->Count; aa++)
 {
  sscanf(Memo1->Lines->Strings[aa].c_str(),"%s %s %s %s %s %s",&a1,&a2,&a3,&a4,&a5,&a6);
  int a11=StrToInt(a1);
  if ((a11==8))
  {
    StringGrid1->Cells[0][sg1]=a1;
    StringGrid1->Cells[1][sg1]=a2;
    StringGrid1->Cells[2][sg1]=a3;
    StringGrid1->Cells[3][sg1]=a4;
    //if (!(a5==-1)){StringGrid1->Cells[4][sg1]=a5;}
    //if (!(a6==-1)){StringGrid1->Cells[5][sg1]=a6;}
    sg1++;
    StringGrid1->RowCount=sg1;
  }
    //a1=-1;
   // a2=-1;
   // a3=-1;
    //a4=-1;
    //a5=-1;
   // a6=-1;
 }

так? всё равно такая ошибка вылетает.
ну ладно оставлю вот так:
Код

int a1, a2, a3, a4, a5, a6;
 for (int aa=0; aa<Memo1->Lines->Count; aa++)
 {
  sscanf(Memo1->Lines->Strings[aa].c_str(),"%d %d  %d %d %d %d",&a1,&a2,&a3,&a4,&a5,&a6);
  int a11=StrToInt(a1);
  if ((a11==8))// 8 группа
  {
    StringGrid1->Cells[0][sg1]=a1;
    StringGrid1->Cells[1][sg1]=a2;
    StringGrid1->Cells[2][sg1]=a3;
    StringGrid1->Cells[3][sg1]=a4;
    if (!(a5==-1)){StringGrid1->Cells[4][sg1]=a5;}
    if (!(a6==-1)){StringGrid1->Cells[5][sg1]=a6;}
    sg1++;
    StringGrid1->RowCount=sg1;
  }
    a1=-1;
    a2=-1;
    a3=-1;
    a4=-1;
    a5=-1;
    a6=-1;
 }

так работает. 

Автор: artsb 14.1.2008, 20:02
Придумал ещё лучше!
Код

TStringList *lst=new TStringList;
lst->Delimiter=' ';
lst->DelimitedText=Memo1->Lines->Strings[aa];

  if ((lst->Strings[0]=="445"))
  {
     for(int i=0;i<lst->Count;i++)  
      {
          StringGrid1->Cells[i][sg1]=lst->Strings[i];
      }
    sg1++;
    StringGrid1->RowCount=sg1;
 }
 delete lst;

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