LINUX.ORG.RU

Двунаправленный список на Си.

 


0

1

Здравствуйте. Являюсь начинающим в разработке на языке Си, и столкнулся с проблемой в решении следующей задачи: Для решения задачи сформируйте двунаправленный список. Дана последовательность латинских букв, оканчивающаяся точкой. Среди букв есть специальный символ Ch, появление которого означает отмену предыдущего символа. Учитывая вхождение этого символа, преобразуйте последовательность.

На бумаге всё проще простого, но с реализацией на Си есть проблемы. Можете предложить свой пример решения? Всё в статике, никаких динам. массивов и тд. maxsize взять за 100



Последнее исправление: LokiGG (всего исправлений: 1)

Являюсь начинающим в разработке на языке Си

начинающим лодырем и попрошайкой

либо ты пишешь свой вариант, кривизну которого тебе помогут поправить местные сердобольные, либо собираешь котомку с вещами и уходишь красиво в закат.

olelookoe ★★★
()

Если все в статике и max size 100 то зачем здесь список? Бери массив на 100 символов и указатель на последний символ и читай свою последовательность

cobold ★★★★★
()

Для решения задачи сформируйте двунаправленный список.

сделайте стек из двунаправленного списка (структур у которых есть указатели на предыдущий и последующий).

Если символ не Ch создать элемент и push его в стек (добавить в конец списка),

если Ch то pop из стека (удалить последний элемент).

Дошли до конца - печать полученного списка от начала до конца.

код за вас вряд-ли будут писать. Это только вредить

MKuznetsov ★★★★★
()

и столкнулся с проблемой в решении следующей задачи

Ты описал задачу. А где описание проблемы с которой ты столкнулся в процессе ее решения?

iron ★★★★★
()

Всё в статике, никаких динам. массивов и тд. maxsize взять за 100

В задаче про это ни слова.


На бумаге всё проще простого, но с реализацией на Си есть проблемы

Я могу представить, что это за проблемы, раз ты даже код не приложил. Тогда расписывай своё решение «на бумаге», пойдём от него

XMs ★★★★★
()
Кусочек 
{
   букафка;
   папа;
   дочка;
}

Составить из кусочков цепочку, в каждый кусочек букафку, каждый новый кусочек в дочку, а каждый текущий в папу

цикл пока кусочек
   если кусочек.букафка равно 'Ы' тогда
      кусочек.папа.дочка = кусочек.дочка;
   всё
   кусочек = кусочек.дочка
всё

вывести что получилось, букафку из кусочка, затем взять дочку и из неё букафку пока не кончаться дочки. 
LINUX-ORG-RU ★★★★★
()

На бумаге всё проще простого

Не томи, показывай. Сомневаюсь, что имея решение на бумаге, его трудно перевести в код.

ox55ff ★★★★★
()
Ответ на: комментарий от anonymous

Среди букв есть специальный символ Ch, появление которого означает отмену предыдущего символа.

Из этого можно сделать вывод, что Ch является точно такой же буквой, как и любоя другая, и может быть отменён.

Но условие всратое, да.

HE_KOT
()

Ну нельзя же быть таким балбесом! Задай свой вопрос ГПТ хотя бы для начала. Что за люди пошли: ни украсть, ни покараулить. Вообще соображалки нет.

no-such-file ★★★★★
()
Последнее исправление: no-such-file (всего исправлений: 1)
Ответ на: комментарий от ya-betmen

Из списка символов сформировать связный список, где в каждом листе по символу, затем пройтись по этому списку и если встретится определённый символ в листе, то заменить текущим листом предыдущий. Типа есть строка ABXCDEXFG из неё строится список

  • A<->B<->X<->C<->D<->E<->X<->F<->G

теперь проходимся по нему и если встретим символ X то убираем предыдущий лист, ставя себя на место него.

  • A<->X<->C<->D<->X<->F<->G

Тоесть берём child пред-предыдущего листа и меняем его на себя, а свой parent на на parent из предыдущего, который анигилируем.

LINUX-ORG-RU ★★★★★
()
Ответ на: комментарий от LINUX-ORG-RU

Из списка символов сформировать связный список, где в каждом листе по символу

связный список, где в каждом листе по символу = список символов

Из списка символов сформировать список символов

ЯННП

ya-betmen ★★★★★
()
Ответ на: комментарий от LINUX-ORG-RU

Из массива символов сформировать двунаправленный связанный список. Ок. А преобразовать то куда?

ya-betmen ★★★★★
()
Последнее исправление: ya-betmen (всего исправлений: 1)

специальный символ Ch

Я не знаю такого символа. Может быть это имя переменной, которая хранит код того специального символа?

Shushundr ★★★★
()

Можете предложить свой пример решения?

А то, ня:

package Test;

import java.util.Arrays;

public class AbcPoint
{
	public static void main(String[] args)
	{
		String str[] = {"A", "B", "C", "D", "Ch", ".",};
		int j = 0;
		int k = 0;
		System.out.println(Arrays.toString(str));
		for(int i=0; i<str.length; i++)
		{
			if(str[i].equals("Ch")) 
				{
				str[i-1] = "";
				j++;
				}
		}
	   System.out.println(Arrays.toString(str));
	   String sub[] = new String[(str.length -j)];
	   for(int i=0; i<str.length; i++)
		{
			if(!(str[i].equals("")))
				{
				sub[k] = str[i];
				k++;
				}
		}
       System.out.println(Arrays.toString(sub));
}
}
Ygor ★★★★★
()
Ответ на: комментарий от HE_KOT

Либо два указателя, либо перебор в обратном направлении

Как мне видится - даже с аннигиляцией если спец-символ фиксированный то список нафиг не впился. Всё становится веселее если он является функцией предыдущего - тогда без полного прохода назад не обойтись, и без списка придётся двигать потенциально длинный хвост.

ПыСы. Хорошая задачка.

bugfixer ★★★★★
()

Всё очень просто. Я сейчас объясню.

  1. Берёшь свой двусвязный список, обходишь с конца и строешь односвязный список с обратным порядком элементов.

  2. Проходишься по односвязному списку, на каждом этапе если текущая буква нормальная, добавляешь её в аккумулятор, а если Ch, то игнорируешь следующую букву.

  3. Из полученного односвязного списка строишь обратно двусвязный. Ну или не строишь, нормальные списки рулят, а двусвязные — фигня беспонтовая, вообще неясно зачем нужны и кому.

ugoday ★★★★★
()

Сильно не тестировал, но вроде работает.

#include <stdbool.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>

struct node {
  char c;
  struct node *prev;
  struct node *next;
};

struct node *read_string(void);

void process_string(struct node **node);

void write_string(struct node *node);

int main(void)
{
  struct node *node = read_string();
  process_string(&node);
  write_string(node);
}

struct node *alloc_node(void);

struct node *read_string(void)
{
  struct node *first = NULL;
  struct node *prev = NULL;
  while (true) {
    char c;
    ssize_t rv = read(0, &c, 1);
    if (rv != 1) abort();
    struct node *curr = alloc_node();
    curr->c = c;
    curr->prev = prev;
    if (prev != NULL) prev->next = curr;
    prev = curr;
    if (first == NULL) first = curr;
    if (c == '.') break;
  }
  prev->next = NULL;
  return first;
}

struct node *alloc_node(void)
{
  static struct node buffer[100];
  static size_t next = 0;
  if (next >= sizeof(buffer) / sizeof(buffer[0])) abort();
  return &buffer[next++];
}

void remove_node(struct node *node);

void process_string(struct node **node)
{
  struct node *n = *node;
  while (n != NULL) {
    if (n->c == 'H') {
      if (n->prev != NULL) remove_node(n->prev);
      remove_node(n);
    }
    n = n->next;
  }
  n = *node;
  while (n->next != NULL && n->next->prev != n) n = n->next;
  *node = n;
}

void remove_node(struct node *node) {
  if (node->prev != NULL) node->prev->next = node->next;
  if (node->next != NULL) node->next->prev = node->prev;
}

void write_string(struct node *node)
{
  while (node != NULL) {
    ssize_t rv = write(1, &node->c, 1);
    if (rv != 1) abort();
    node = node->next;
  }
}
vbr ★★★★
()
Ответ на: комментарий от ugoday

Всё очень просто. Я сейчас объясню.

Я бы, наверное, просто шёл по строке и пушил байты в стек, а по Ch выщёлкивал бы один. Зачем списки? почему двусвязные? загадка.

Nervous ★★★★★
()
Ответ на: комментарий от Nervous

Я бы, наверное, просто шёл по строке и пушил байты в стек, а по Ch выщёлкивал бы один. Зачем списки? почему двусвязные? загадка.

Видимо стек реализован на базе двусвязного списка.

Psilocybe ★★★★
()
Ответ на: комментарий от ya-betmen

Из списка символов сформировать список символов

ЯННП

Ну очевидно же, что на сях надо написать простейший интерпретатор лишпа, в котором реализовать элементарный ДСЛ для решения задачи!

GAMer ★★★★★
()
Ответ на: комментарий от GAMer

очевидно же, что на сях надо написать простейший интерпретатор лишпа, в котором реализовать элементарный ДСЛ для решения задачи!

…чтобы больше никогда не писать на сях.

Nervous ★★★★★
()
Ответ на: комментарий от bugfixer

вы из односвязного списка даже элемент удалить не сможете без указателя на предыдущий.

scheme@(guile-user)> (define l '(1 2 3 4 5 6))
scheme@(guile-user)> (set-cdr! (cdr l) (cdddr l))
scheme@(guile-user)> l
$7 = (1 2 4 5 6)

Ой, что-это, третий элемент списка куда-то делся!

ugoday ★★★★★
()