Консультация № 185944
02.05.2012, 09:12
105.75 руб.
02.05.2012, 17:53
0 5 1
Здравствуйте! Прошу ещё раз разъяснить по консультации 185796: Необходимо результирующую модифицированную строку выводить во клавише ENTER! Т.е. каждый бит в строке - элемент списка.

Задание:
Из входного потока вводится произвольное число строк. Длина строки не ограничена. Каждая строка представляет собой последовательность двоичных кодов, разделённых одним или несколькими пробелами и/или знаками табуляции. Строка представлена списком (первое поле элемента списка - символ строки, второе указатель на следующий элемент списка или NULL в конце списка). Конец ввода определяется концом файла.

Для каждой строки сформировать новую строку, поместив в неё исходные двоичные коды, дополненные БИТОМ ЧЁТНОСТИ.
Бит чётности устанавливается 0 или 1 так, чтобы общее количество единиц в полученном коде было чётным. В полученной строке коды разделять ТОЛЬКО ОДНИМ пробелом. Полученную строку вывести в выходной поток.



Примечания:

Ввод строк неопределённой длины должен быть организован с помощью метода cin.getline (куда, максимум_сколько). Метод cin >> куда не использовать!

Структурв программы должна быть следующей: пока не обнаружен кнец файла { ввести строку с помощью cin.getline(...)
; сформировать список; обработать список в соответствии с условием задачи; вывести результат, освободить память, выделенную под список}.
Новый список формировать, модифицируя исходный список.

Обсуждение

Неизвестный
02.05.2012, 17:52
общий
03.05.2012, 17:19
Я правильно понимаю алгоритм?
1. В консоли вводится некоторая последовательность нулей, единиц, пробелов и табуляций.
2. Нажимается ENTER.
3. Если конец ввода/файла (EOF), то завершить программу.
4. Для каждого символа в строке создаётся элемент односвязного списка.
5. Список обрабатывается по условию.
6. Первое поле каждого элемента списка выводится в выходной поток
7. Очистить список.
8. Переход на пункт 1.
Неизвестный
03.05.2012, 21:59
общий
Да, вводятся двоичные коды разделенные пробелами, одним или несколькими, табуляцию можно не использовать, после нажатия клавиши ввода, выводится результирующая строка, разделенная одним пробелом с битом чет.
Неизвестный
03.05.2012, 22:02
общий
03.05.2012, 22:07
Да, для каждого символа создается элемент списка
Неизвестный
03.05.2012, 22:11
общий
это ответ
Здравствуйте, 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);
}
}
5
Очередной раз выручили!) Спасибо
Неизвестный
03.05.2012, 22:34
общий
Спасибо, всё правильно теперь работает, буду разбираться в коде сейчас.
Форма ответа