объясните программу

Модераторы: Hawk, Romeo, Absurd, DeeJayC, WinMain

nikitoz_ru
Сообщения: 9
Зарегистрирован: 07 июн 2009, 14:03

Добрые люди объясните пожалуйста программу можно по строчно:

Код: Выделить всё

#include <iostream.h>
int main() 
{
 
        cout << "\stroka: ";
        const int lineLength = 256;
 
        char *lineBuffer   = new char[lineLength];  
         memset(lineBuffer,0,lineLength);
        char *resultBuffer = new char[lineLength];  
        memset(resultBuffer,0,lineLength);
        
        const char *p = lineBuffer;
        char *pr = resultBuffer;
 
        cin >> lineBuffer;
 
        for (; p; p += 2) 
        {
                if (*p != '\0')      
                        *pr++ = *p;
                else break;
        }
 
        p = lineBuffer;
        ++p;
        for (; p; p+=2) 
        {
                if (*p != '\0') 
                        *pr++ = *p;
                else break;
        }
 
        cout << "\nResult: " << resultBuffer << '\n';
         return 0;
}
BBB
Сообщения: 1298
Зарегистрирован: 27 дек 2005, 13:37

Похоже на "вывести в результирующую строку сначала все четные, а затем все нечетные символы исходной строки".
Только код кривой. Если длина исходной строки нечетная, то первый цикл (формально) окажется бесконечным. Если четная, то второй цикл.
Аватара пользователя
Romeo
Сообщения: 3126
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

Цикл бесконечный и в первом и во втором случае. Чтобы работало правильно, в цикле вместо p следует написать *p. Вот так:

Код: Выделить всё

for ( ; *p; p += 2)
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
BBB
Сообщения: 1298
Зарегистрирован: 27 дек 2005, 13:37

Romeo писал(а):Цикл бесконечный и в первом и во втором случае. Чтобы работало правильно, в цикле вместо p следует написать *p. Вот так:

Код: Выделить всё

for ( ; *p; p += 2)
Отнюдь не бесконечный в ОБОИХ случаях. Если lineBuffer - это null-терминированная строка, то либо в первом, либо во втором случае условие if (*p != '\0') НЕ выполнится, а по else там стоит break из цикла.

Более того, замена во второй "позиции" цикла for p на *p абсолютно ничего не изменит. Так как первым же действием внутри цикла стоит ровно то же самое. А именно, проверка значения байта, на корорый указывает в данный момент p на ноль.
Хотя, писать p, конечно, бессмысленно. В том смысле, что значение этого "выражения" всегда будет TRUE.
Аватара пользователя
Romeo
Сообщения: 3126
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

Мммм, да, каюсь, невнимательно прочитал что внутри цикла стоит. У меня взгляд уцепился за аномалию в условии и тут же возникло желание поведать об этом всем :)

Зато я заметил, что вот такого там нет:
&quot писал(а):Если длина исходной строки нечетная, то первый цикл (формально) окажется бесконечным. Если четная, то второй цикл.
Дело в том, что там делается memset, так что в конце строки не один нуль, а множество и, как следствие, нуль есть и на чётной и на нечётной позиции :)

А вообще неграмотный код зло, он достаточно часто сбивает опытных программистов с толку, если пытаться читать его быстро, не заостряя внимания на мелочах, в то время как быстрое чтение грамотного кода не доставляет никаких проблем.
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
BBB
Сообщения: 1298
Зарегистрирован: 27 дек 2005, 13:37

Romeo писал(а):Дело в том, что там делается memset, так что в конце строки не один нуль, а множество и, как следствие, нуль есть и на чётной и на нечётной позиции :)
Да, на memset я особого внимания не обратил.
Но все равно это ненадежно. В случае краевого эфекта (длина строки окажется равна sizeof (...) - 1), там (в конце) окажется только один ноль. В случае еще бОльшей длины строки, как я понимаю, cin >> lineBuffer уже исполосует память за строкой.

Да в вообще, если это в самом деле такой "тонкий расчет", то уж как-то слишком хитрО это... Я бы вот так циклы написал:

Код: Выделить всё

   ...................
while (TRUE) {
  if (*p != '\0')      
    *pr++ = *p;
  else break;
  p++;
  if (*p == '\0')      
    break;
  p++;
}

p = lineBuffer;
while (TRUE) {
  if (*p == '\0')      
    break;
  p++;
  if (*p != '\0') 
    *pr++ = *p;
  else break;
  p++;
}
Может, писанины чуть длинее, но зато без хитрых выкрутасов, над которыми (через некоторое время) придется голову ломать при попытке понять, а как же это все тут работает?
--------------------------------------------------------------------------------
Добавлено сообщение
--------------------------------------------------------------------------------
Вообще, еще проще, пожалуй, определить перед циклами длину исходной строки и ориентироваться на нее, а не на встречу в строке нулевого символа. Тогда вообще не будет опасности "проскочить дальше", даже в случае инкремента текущей позиции в строке на два. Ведь условие быхода из циклв будет неравество, где сравнивается текущая позиция с длиной строки.
nikitoz_ru
Сообщения: 9
Зарегистрирован: 07 июн 2009, 14:03

может кто нибудь исправит код чтоб не было:

Код: Выделить всё

 char *lineBuffer   = new char[lineLength];  
         memset(lineBuffer,0,lineLength);
        char *resultBuffer = new char[lineLength];  
	memset(resultBuffer,0,lineLength);
а было просто

Код: Выделить всё

char *p;
          char *pr;
короче без =new char[lineLength] и lineLength вобще не нужен
я пробовал не получается
Аватара пользователя
Romeo
Сообщения: 3126
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

Код: Выделить всё

char lineBuffer[lineLength] = {0};
char resultBuffer[lineLength] = {0};
Без lineLength совсем нельзя. Иначе не понятно какого размера должен быть буфер.
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
nikitoz_ru
Сообщения: 9
Зарегистрирован: 07 июн 2009, 14:03

Cделал как ты сказал у меня комп повис))
мне вообше нужно написать программу через указатели строки. Чтобы все было ясно вот текст:
Описать функцию, которая изменяет заданную строку следующим образом: сначала записывает все элементы с четными индексами, а затем все элементы с нечетными индексами ( с сохранением их относительного порядка в каждой группе). Например, abcdefgh => acegbdfh, vwxyz => vxzwy.
эта прога была без указателей написана через char linbuffer; а нужно так: char *linebuffer;
Аватара пользователя
Romeo
Сообщения: 3126
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

Так, как хочешь ты, сделать нельзя. В любом случае нужно указать каков размер буфера. А будет выделяться буфер в куче (через new) или на стеке (локальный массив) - это уже второй вопрос: дела он не касается и в задании способ выделения тоже не оговорен.

Почему у тебя компьютер завис я не знаю. Только что проверил твой вариант у себя на машине на 6-й студии - всё работает.
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Ответить