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


Автор: GrAndrey 2.11.2003, 15:04
Вот примерно такой код:
Код

main()
{
 char *str1 = (char *) malloc(2500);

 substr(temp, str1, 18, 31);

 free ( str1 );
}

void substr(char * newstr, char * str, int first, int last)
{
int i, len = StrLen(str);

newstr[0]='\0';
for (i=0; i<=last-first && i<len-first; ++i)
 newstr[i] = str[i+first];
newstr[i]='\0';
}

При отладке, примерно до момента, когда i=7, всё нормально. После этого, newstr приобретает значение str лежащее после first, а str претерпевает различные изменения. После строки newstr[i]='\0'; уже при закрытии блока, значение str равно куску newstr размером 6 букв.
Что происходит, и есть ли пути выделить подстроку лучше, чем такой?

Автор: neutrino 2.11.2003, 15:33
void substr(char* newstr, char* str, int first, int last) {
int i;
for (i=first; (i<=last)&&(newstr[i-first]=str[i]); i++);
}

Автор: GrAndrey 2.11.2003, 16:37
Всё равно str1 калечит sad.gif

Автор: frost 2.11.2003, 19:47
Я конечно ламо с ушами, а где у Вас объявляется temp? Она уже готова к работе? А то я не, извините за выражение, въехал.

Автор: GrAndrey 2.11.2003, 21:02
Я объявляю temp сразу следом за str1. Я показал, что умею память выделать, и не вдавался в такие подробности.
Я просто не понимаю, почему происходят изменения со str1, когда я ей ничего нигде не присваиваю?!!! Может ли врать отладчик? Судя по его данным, со строками прям-таки чудеса творятся.

Автор: frost 2.11.2003, 21:16
Непонятно. А в строках то, что надо?, Вы память точно выделили динамически? Если нет, то может компилятор Same strings merge'ит? Больше ничего придумать не могу.

Автор: DENNN 3.11.2003, 11:31
Цитата
Я показал, что умею память выделать, и не вдавался в такие подробности.

Раз такие вещи происходят- значит в все же где-то в коде ошибка. Неплохо бы весь кусок привести. Кроме того, можно заглянуть в справку по поводу команд memset и memcpy ;)

Автор: Albinos 3.11.2003, 19:48
2neutrino:

Цитата
void substr(char* newstr, char* str, int first, int last) {
int i;
for (i=first; (i<=last)&&(newstr[i-first]=str[i]); i++);
}


А вот так писать не хорошо.

Автор: GrAndrey 3.11.2003, 20:26
Вот код. Совершенно левое удалил. Функция substr приведена дословно. mbx вызывает messageBox.
Пишу в C++ Builder 6.0.
Код

{
 char *str1 = (char *) malloc(2500);
 char *str2 = (char *) malloc(2500);
 char *tempstr = (char *) malloc(2500);

 
 str1 = ListBox1->Items->Strings[ListBox1->ItemIndex-ListBox1->ItemIndex%3+1].c_str();
 if (str1!="")
  {
   if (strlen(str1)==70) mbx("Неверная длинна строки данных. ");
   else
   {
    if (str1[0]=='1' && isdigits(str1,18,22))
    {
     char * temp = (char *) malloc(2500);
     char * temp1 = (char *) malloc(2500);
     int sum=0;

     substr(temp, str1, 18, 31);
     LabeledEdit6->Text = temp;

     temp[0]='\0';

     substr(temp1, str1, 33, 33);
     if (temp1[0]=='-' || temp1[0]=='+')
      strcpy(temp, temp1);
     strcat(temp, "0");
     substr(temp1, str1, 34, 42);
     strcat(temp, temp1);
     LabeledEdit7->Text=temp;

     free(temp);
     free(temp1);
    }
    else mbx("Неверный формат данных. ");
   }
  }
  else mbx("Первая строка данных пуста.");

 free (str1);
 free (tempstr);
}

Автор: bel_nikita 4.11.2003, 10:41
Есть функция char *strtok(char *str1, const char *str2); которая позволяет разбить строку до составляющих ее частей.

Автор: Ars 4.11.2003, 12:11
У тебя неверная работа со строками:
1.
Код
str1 = ListBox1->Items->Strings[ListBox1->ItemIndex-ListBox1->ItemIndex%3+1].c_str();

тут же теряется указатель на ранее выделенную память
надо так:
Код
strcpy(str1,ListBox1->Items->Strings[ListBox1->ItemIndex-ListBox1->ItemIndex%3+1].c_str());

2.
Код
if (str1!="")
всегда будет true
надо так:
Код
if (strcmp(str1,"")==0) или
if(str1[0]=='<!--POST BOX-->')

3. Указатель, возвращаемый функцией .c_str() - временный. При выходе из области видимости или при изменении AnsiString он теряет валидность. У тебя что-то подобное и происходит, а память для temp выделяется по адресу немного раньше, чем str1, после чего в substr происходит обычный наезд на память str1 (уже освобожденную и заново выделенную для temp)

Аккуратней работай со строками - char* не строка, а всего лишь указатель...
В AnsiString есть ф-ция выделения подстроки:
Код
LabeledEdit6->Text = ListBox1->Items->Strings[ListBox1->ItemIndex-ListBox1->ItemIndex%3+1].
   SubString(19,14)

Автор: neutrino 4.11.2003, 16:51
Цитата(Albinos @ 3.11.2003, 18:48)
2neutrino:

Цитата
void substr(char* newstr, char* str, int first, int last) {
int i;
for (i=first; (i<=last)&&(newstr[i-first]=str[i]); i++);
}


А вот так писать не хорошо.

Чего тут нехорошего? Усе ОК.

Автор: Albinos 4.11.2003, 17:03
Ну если i = -1, например, то проверки не произойдет - вылетит раньше, в память чужую залезешь...

Или "Index is out of bounds" крикнет.

Автор: GrAndrey 4.11.2003, 17:08
Благодарю всех, а Ars особенно. Надеюсь, всё теперь будет хорошо.

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