Сложная задача со списком c++ - Вопросы по С+

Вопрос Сложная задача со списком c++

Регистрация
16 Ноя 2012
Сообщения
90
Репутация
0
Спасибо
0
Монет
0
Нам задали простую на первый взгляд задачу, но она оказалась очень сложной помогите пожалуйста решить её, задача звучит следующим образом: есть некая строка и в ней хранятся слова например "ABCD 12345 hrom" нужно чтобы после выполнения кода в консоль выводилось сообщение "DCBA 54321 mroh", то есть нужно перевернуть буквы, но слова оставить на месте. ГЛАВНЫЕ УСЛОВИЯ: Можно использовать только 1 цикл за всё выполнения кода, то есть должен быть только 1 проход по массиву списка, можно только 1 раз написать в коде while, или for больше 1 нельзя. Также нельзя использовать любые виды рекурсии, а ещё нельзя использовать goto, и буфер обмена, так же нельзя использовать функцию reverse. Выполнить всё это нужно на языке C++

Вот пример кода:

#include <cstdio>

#include <cstring>



// Функция для разворота букв в слове

void reverseWord(char* start, char* end)

{

if (start >= end) return; // Базовый случай

char temp = *start;

*start = *end;

*end = temp;

reverseWord(start + 1, end - 1); // Рекурсивный вызов

}



// Рекурсивная функция для нахождения конца слова

char* findEndOfWord(char* str)

{

if (*str == '0' || *str == ' ') return str; // Возвращаем указатель на конец слова

return findEndOfWord(str + 1); // Рекурсивно продолжаем поиск

}



// Рекурсивная функция для разворота букв в каждом слове строки

void reverseLetters(char* str)

{

if (*str == '0') return; // Базовый случай: конец строки



// Определяем начало слова

char* wordStart = str;



// Находим конец слова

char* wordEnd = findEndOfWord(str);



// Разворачиваем слово

reverseWord(wordStart, wordEnd - 1);



// Если не достигли конца строки, продолжаем с пробела

if (*wordEnd != '0')

{

reverseLetters(wordEnd + 1); // Пропускаем пробел и продолжаем с следующего слова

}

}



int main()

{

char str[] = "ABCD gfru 1234 0931."; // Статический массив для хранения строки



reverseLetters(str); // Вызов функции для разворачивания букв в строке



printf("%s\n", str); // Вывод результата



return 0; // Завершение программы

}

Только здесь есть goto, который использовать нельзя по этому данное решение является неверным.

Помогите пожалуйста решить эту задачу, буду очень признателен
 
Регистрация
8 Дек 2013
Сообщения
86
Репутация
0
Спасибо
0
Монет
0
#include <cstdio>
#include <cstring>

void reverseLetters(char* str) {
char* start = str; // Начало текущего слова
for (char* ptr = str; ; ptr++) { // Единственный цикл
if (*ptr == ' ' || *ptr == '\0') { // Конец слова или строки
char* end = ptr - 1; // Указатель на последний символ слова
while (start < end) { // Разворот слова
char temp = *start;
*start = *end;
*end = temp;
start++;
end--;
}
if (*ptr == '\0') break; // Конец строки
start = ptr + 1; // Начало следующего слова
}
}
}

int main() {
char str[] = "ABCD 12345 hrom";
reverseLetters(str);
printf("%s\n", str); // Вывод: DCBA 54321 mroh
return 0;
}
Объяснение:

Единственный цикл: Используется один цикл for, который проходит по строке. Он проверяет каждый символ, чтобы определить конец слова (пробел или \0).

Разворот слова: Когда найден конец слова, два указателя (start и end) используются для обмена символов внутри слова без рекурсии и без функции reverse.

Условия задачи:
Запреты на рекурсию, goto, буфер обмена и функцию reverse соблюдены.
Слова остаются на своих местах, переворачиваются только их символы.

Работа с указателями:
start указывает на начало текущего слова.
ptr движется по строке, пока не встретит пробел или конец строки.

При развороте слова используется временная переменная temp для обмена символов.

Остановка: Цикл завершается, когда встречается \0 (конец строки).
 
Регистрация
17 Сен 2013
Сообщения
88
Репутация
0
Спасибо
0
Монет
0
ну ты намудрил. Читаешь файл до конца, записываешь в строку, И циклом наоборот эту строку выводишь
 
Регистрация
16 Июл 2013
Сообщения
80
Репутация
0
Спасибо
0
Монет
0
Задача не решается в указанных ограничениях уже хотя бы потому, что для вывода в консоль придётся прокрутить ещё один цикл.

Но если цикл для вывода не считать, то у тебя в заголовке вопроса содержится ответ: используй связный список.

При первом и единственном проходе хранишь три указателя, допустим, phrase на начало списка, tail на первую букву слова (которая при развороте слова становится последней) и word на последнюю встреченную до сих пор букву слова. Очередную букву слова заталкиваешь в голову списка букв этого слова, указатель на неё становится головой списка (word). Как встретил разделитель (пробел, точка, и что там ещё у тебя может использоваться в этом качестве), добавляешь его после бывшей первой буквы (после tail), а word делаешь пустым.

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

Структура данных - примерно такая: struct node_t {
node_t *next;
char c;

node_t(node_t *const next, const char c): next(next), c(c) {}

node_t(const char c): next(nullptr), c(c) {}
}; Обход будет выглядеть как-то так: char str[] = "ABCD gfru 1234 0931.";
const uint n = sizeof(str) / sizeof(*str);
node_t *phrase = nullptr;
{ // основной обход - делаем в блоке, чтобы ограничить область видимости указателей
node_t *word = new node_t(*str), *tail = word;
for (uint i = 1; i < n; i++) {
const char c = str;
node_t *letter = new node_t(c);
if (c == ' ' || c == '.') { // добавь сюда условия для остальной пунктуации
tail = tail->next = letter;
if (!phrase) phrase = word;
word = nullptr;
} else if (c) {
letter->next = word;
if (!word) tail = letter;
word = letter;
}
}
}
// вывод в консоль и освобождение памяти
for (node_t *letter = phrase; letter; ) {
putchar(letter->c);
node_t *prev = letter;
letter = letter->next;
delete prev;
}
putchar('\n');
main, заголовки и прочий обвес добавь сам, должен же ты хоть что-то сделать в этой задаче.

P.S. И на будущее, не публикуй здесь бессмысленный код от нейросети, оставь его для одноклассников. Я даже не собираюсь его читать, забивать голову порожняком. Было бы лучше, если бы ты опубликовал свой код, пусть даже кривой и ламерский. А вываливать бессмыслицу от бредогенератора - это неуважение к отвечающим.
 
Регистрация
20 Май 2013
Сообщения
88
Репутация
0
Спасибо
0
Монет
0
#include <iostream>

using namespace std;

int main() {
string s, t;
getline(cin, s); // ввод обрабатываемой строки
for (auto ch: s) {
if (ch != ' ') {
t = ch + t;
} else {
cout << t << ch;
t = "";
}
}
cout << t;
} В коде единственный цикл, нет рекурсии, нет reverse, нет goto, нет обмена (и, следовательно, нет буфера обмена). Но и списков тоже нет. А вот буфер НЕ обмена есть.

А вот так эту задачу можно решить вообще без буферов единственной входной строкой: #include <iostream>

using namespace std;

int main() {
int start = 0, end = 0, cur = 0;
bool is_reverse = false;
string s;
getline(cin, s);

while (cur < (int)s.size()) {
if (is_reverse) {
if (cur >= start) {
cout << s[cur--];
} else {
if (end < s.size()) { cout << s[end]; }
start = cur = end + 1;
is_reverse = false;
}
} else if (s[cur] == ' ') {
end = cur--;
is_reverse = true;
} else if (cur == s.size() - 1) {
end = s.size() + 1;
is_reverse = true;
} else {
++cur;
}
}
} В рамках одного цикла движемся вперёд/назад. Но, опять же, без списка.
 
Сверху Снизу