Консультация # 185944: Здравствуйте! Прошу ещё раз разъяснить по консультации 185796: Необходимо результирующую модифицированную строку выводить во клавише ENTER! Т.е. каждый бит в строке - элемент списка. Задание: Из входного потока вводится произвольное число строк. Длина строки не ограничена. Каждая строка представляет собой последовательность двоичны...
Здравствуйте! Прошу ещё раз разъяснить по консультации 185796: Необходимо результирующую модифицированную строку выводить во клавише ENTER! Т.е. каждый бит в строке - элемент списка.
Задание: Из входного потока вводится произвольное число строк. Длина строки не ограничена. Каждая строка представляет собой последовательность двоичных кодов, разделённых одним или несколькими пробелами и/или знаками табуляции. Строка представлена списком (первое поле элемента списка - символ строки, второе
указатель на следующий элемент списка или NULL в конце списка). Конец ввода определяется концом файла.
Для каждой строки сформировать новую строку, поместив в неё исходные двоичные коды, дополненные БИТОМ ЧЁТНОСТИ. Бит чётности устанавливается 0 или 1 так, чтобы общее количество единиц в полученном коде было чётным. В полученной строке коды разделять ТОЛЬКО ОДНИМ пробелом. Полученную строку вывести в выходной поток.
Примечания:
Ввод строк неопределённой длины должен быть организован с помощью метода cin.getline (куда, максимум_сколько). Метод cin >> куда не использовать!
Структурв программы должна быть следующей: пока не обнаружен кнец файла { ввести строку с помощью cin.getline(...) ; сформировать список; обработать список в соответствии с условием задачи; вывести результат, освободить память, выделенную под список}. Новый список формировать, модифицируя исходный список.
Здравствуйте, Denis! Пробуйте. Выдаёт тот же результат как в вопросе 185796
Код :
#include <iostream>
#include <string.h>
using namespace std;
struct Elem { //Элемент списка
char ch;
Elem *next;
};
//Создать список
Elem *GetLine()
{
char s[256]; //Временная строка
Elem *Elem0 = 0; //Указатель на первый элемент
Elem *ElemTemp = 0; //Указатель на текущий элемент
Elem *ElemPrev = 0; //Указатель на предыдущий элемент
cin.getline(s,255); //Считаем строку
for (int i=0; i<strlen(s); i++) { //Пробежимся по каждому символу строки
ElemTemp = new Elem; //Выделим память для элемента списка
ElemTemp->ch = s[i]; //Сохранить символ в списке
if (ElemPrev) { //Если определён предыдущий элемент
ElemPrev->next=ElemTemp; //Сослаться на текущий элемент
} else {
Elem0=ElemTemp; //Или запомнить как первый элемент
}
ElemPrev=ElemTemp;
}
if (Elem0) ElemTemp->next=0; //Если список не пустой, то завершить как NULL
return Elem0;
}
//Удаление элемента. Т.к. список односвязный, приходится искать с начала списка
Elem *DelElem(Elem *&ElemFirst, Elem *ElemForDel)
{
if (ElemFirst==ElemForDel) { //Если удаляемый элемент первый в списке
ElemFirst = ElemFirst->next;
delete ElemForDel;
return ElemFirst; //Вернуть указатель на начало списка
} else { //удаляемый элемент не первый в списке
Elem *ElemTemp = ElemFirst; //Начнём искать с первого элемента
while ((ElemTemp)&&(ElemTemp->next != ElemForDel)) //Цикл поиска
ElemTemp = ElemTemp->next; //следующий элемент, если нет совпадения
if (ElemTemp->next == ElemForDel) { //Действительно ли совпадение или конец списка
ElemTemp->next = ElemForDel->next; //Перенаправить указатель на элемент за удаляемым
delete ElemForDel; //Удалить элемент
}
return ElemTemp; //Вернуть указатель на элемент, предстоящий стираемому
}
}
//Вставить элемент
Elem *InsertParity(Elem *Elem1, Elem *Elem2, char ch) //Вставить между Elem1 и Elem2
{
Elem *ElemInserted = new Elem; //Выделить память
ElemInserted->ch = ch; //Присваиваем символ во вставленный элемент
ElemInserted->next = Elem2; //Определить указатель вставленного элемента
Elem1->next = ElemInserted; //Перенаправить указатель предыдущего элемента
return ElemInserted; //Вернуть указатель на вставленный элемент
}
//Обработка строк
Elem *ProcessLine(Elem *Elem0)
{
char ch,ch1;
int spaces=0; //Флаг окончания двоичного числа
int ones=0; //Количество единиц в двоичном числе
int counting=0; //Идёт подсчёт единиц; требуется для последнего числа
Elem *ElemTemp=Elem0; //Запомним начало списка
Elem *ElemPrev=Elem0; //Указатель на предыдущий элемент
while (ElemTemp) { //Переберём все элементы
ch=ElemTemp->ch; //сохраним символ в отдельной переменной для удобства
if ((ch=='\t')||(ch==' ')) { //Если встретился разделитель
if (ElemTemp==Elem0) { //Если элемент первый, то
DelElem(Elem0,ElemTemp); //Удалим первый элемент.
ElemTemp=Elem0;
continue; //Опять проверить первый элемент
} else { //Число закончилось
if (!spaces) { //Если первый разделитель
ch1='0';
if (ones&1) ch1='1'; //Если нечётное количество единиц, то добавить единицу
ElemPrev = InsertParity(ElemPrev,ElemTemp,ch1); //Вставили элемент и получили указатель на него
ElemTemp->ch = ' '; //Заменить первый разделитель на пробел
ones=0;
counting=0;
spaces=1; //Поднять флаг разделителя
} else {
ElemTemp = DelElem(Elem0,ElemTemp); //Удалить элемент и вернуть указатель на предстоящий
}
}
} else { //число
spaces=0;
counting=1;
if (ch=='1') ones++; //Считаем единицы
}
ElemPrev = ElemTemp; //Запомним указатель на элемент
ElemTemp = ElemTemp->next; //Следующий элемент
}
if (Elem0&&counting) { //Если список не пустой, то вставить бит чётности в конце списка
ch1='0';
if (ones&1) ch1='1'; //Если нечётное количество единиц, то добавить единицу
ElemTemp = InsertParity(ElemPrev,0,ch1); //Вставили элемент и получили указатель на него
}
if ((ElemPrev)&&(ElemPrev->ch == ' ')) DelElem(Elem0,ElemPrev); //Стереть последний пробел
return Elem0;
}
//Вывод результата
void PrintLine(Elem *ElemTemp)
{
while (ElemTemp) {
cout<<ElemTemp->ch;
ElemTemp = ElemTemp->next;
}
cout<<endl;
}
//Очистить память
void FreeElems(Elem *ElemTemp)
{
Elem *Elem0;
while (ElemTemp) {
Elem0=ElemTemp;
ElemTemp = ElemTemp->next;
delete(Elem0);
}
}
int main(int argc, char** argv)
{
while (1) {
//Создать список
Elem *ElemFirst = GetLine();
if (cin.eof()) break; //Если конец ввода/файла, то выйти
//Обработка строк
ElemFirst=ProcessLine(ElemFirst);
//Вывод результата
PrintLine(ElemFirst);
//Очистить память
FreeElems(ElemFirst);
}
}
Команда портала RFPRO.RU благодарит Вас за то, что Вы пользуетесь нашими услугами. Вы только что прочли очередной выпуск рассылки. Мы старались.
Пожалуйста, оцените его. Если совет помог Вам, если Вам понравился ответ, Вы можете поблагодарить автора -
для этого в каждом ответе есть специальные ссылки. Вы можете оставить отзыв о работе портале. Нам очень важно знать Ваше мнение.
Вы можете поближе познакомиться с жизнью портала, посетив наш форум, почитав журнал,
который издают наши эксперты. Если у Вас есть желание помочь людям, поделиться своими знаниями, Вы можете зарегистрироваться экспертом.
Заходите - у нас интересно!