Форум программистов, компьютерный форум, киберфорум
Наши страницы
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.77/22: Рейтинг темы: голосов - 22, средняя оценка - 4.77
Golovastik
11 / 11 / 2
Регистрация: 25.05.2009
Сообщений: 435
1

Реверсирование строк

08.09.2009, 00:08. Просмотров 4287. Ответов 17
Метки нет (Все метки)

Всем добрый вечер! Как всегда, практикуюсь по книжным примерам. Вот дошёл до темы реверсирования строк, то есть расположения букв в обратном порядке. Столкнулся с таким кодом, и не ясен стал цикл,то есть как именно происходит замена букв в нём?
Если кто может, подскажите,если не сложно? Не ясен сам цикл, и строка перед ним: end = &str[len-1];
Заранее благодарю.

Вот исходник:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <iostream>
using namespace std;
 
int main() 
{
setlocale(0, "" ); 
char str[] = "Россия - щедрая душа";
char *start, *end;
int len;
char t;
 
cout<<"Исходная строка: "<<str<<'\n';
len = strlen(str);
start = str;
end = &str[len-1];
while(start < end)
{
    t = *start;
    *start = *end;
    *end = t;
    start++;
    end--;
}
cout<<"Результат после реверсирования: \n"<<str;
 
cin.get();
return 0;
 
}
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
08.09.2009, 00:08
Ответы с готовыми решениями:

Реверсирование строк
Нужно отсортировать строки по алфавиту и вывести в файл реверсированные строки. #include...

Реверсирование
Помогите пожалуйста! Задача Реверсировать число и увеличить его в 2 раза.

Реверсирование самих строк в очереди
Здравствуйте, нужно создать очередь из произволных числа строк и реверсировать их,то есть изменить...

реверсирование строки
Помогите написать программу реверсирования строки, т.е. замены прядка следования символов в строке...

Объединение и реверсирование
Всем привет! Помогите пожалуйста с программой. Необходимо написать реверсирование строки, используя...

17
alex_x_x
бжни
2456 / 1663 / 134
Регистрация: 14.05.2009
Сообщений: 7,162
08.09.2009, 00:14 2
все довольно просто -
C++
1
end = &str[len-1];
- указатель на конец строки (адрес последнего символа)
C++
1
2
3
4
5
6
7
8
while(start < end) //пока символы не пересеклись
{
        t = *start; //в направление вперед - символ в t
        *start = *end; // в символ с начала - символ с конца
        *end = t; //в конечный - с начала
        start++; //сдвигаем указатель начала вперед
        end--;//указатель на конец назад
}
1
M128K145
Эксперт JavaЭксперт С++
8340 / 3561 / 420
Регистрация: 03.07.2009
Сообщений: 10,708
08.09.2009, 00:24 3
Хм... Мне кажется, что это не самый лучший учебник(ну или пример в частности). Вот
мой вариант
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
 
int main() 
{
    setlocale(LC_ALL, "Russian"); 
    char str[] = "Россия - щедрая душа";
    std::cout<<"Исходная строка: "<<str<<'\n';
 
    size_t len = strlen(str);
    for(unsigned short i = 0; i < len/2; ++i)
        str[i] ^= str[len - i - 1] ^= str[i] ^= str[len - i - 1];
    std::cout<<"Результат после реверсирования: \n"<<str<<'\n';
 
    system("pause");
    return 0;
}
, он намного проще. Все вышесказанное действительно, если тема - это не работа с указателями.

C++
1
2
3
4
5
6
7
8
9
10
end = &str[len-1];//запись в end - последнего символа строки
while(start < end) // пока старт меньше конца(читай пока не середина строки)
{
        t = *start; //сохраняем в буфер левый символ
        *start = *end; //записываем в левый символ правый символ
        *end = t; //в правый символ записываем содержимое буфера
// ну как обычный пузырек
        start++; // и просто смещаем указатель слева на один символ вправо
        end--; // и справа на один символ влево
}
1
Gravity
571 / 565 / 65
Регистрация: 29.01.2009
Сообщений: 1,274
08.09.2009, 00:45 4
Наверное, автора смущает то, что к элементам строки обращаются по адресам. Думаю, с обычной индексацией было бы понятнее.

Добавлено через 18 минут
Собстно, вот:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
#include <cstring>
int main()
{
    char str[] = "Goodbye, cruel world. I'm leaving you today", tmp;
    int i, j;
 
    std::cout << "Исходная строка: " << str << std::endl;
    for(i = 0, j = strlen(str)-1; i < j; i++, j--) {
        tmp = str[i];
        str[i] = str[j];
        str[j] = tmp;
    }
    std::cout << "Результат после реверсирования: " << str << std::endl;
    std::cin.get();
    return 0;
}
1
08.09.2009, 00:45
Monte-Cristo
2797 / 1386 / 107
Регистрация: 07.03.2009
Сообщений: 4,446
08.09.2009, 01:01 5
Цитата Сообщение от M128K145 Посмотреть сообщение
str[i] ^= str[len - i - 1] ^= str[i] ^= str[len - i - 1];
Ууу... я понимаю, что минимализм - это хорошо. Но через дополнительную перменную будет и быстрее и проще.. да и ТС будет понятней.
0
ISergey
Maniac
Эксперт С++
1426 / 932 / 154
Регистрация: 02.01.2009
Сообщений: 2,774
Записей в блоге: 1
08.09.2009, 01:16 6
проще так:
C++
1
2
3
4
5
6
7
8
9
10
#include <iostream>
#include <algorithm>
 
int main(){
 
    char str[] = "string";
    std::reverse(str, str + strlen(str));
    std::cout << str << std::endl;
    return 0;
}
1
mirso
527 / 345 / 45
Регистрация: 05.04.2009
Сообщений: 709
08.09.2009, 01:46 7
Цитата Сообщение от Monte-Cristo Посмотреть сообщение
Но через дополнительную перменную будет и быстрее и проще..
Цитата Сообщение от ISergey Посмотреть сообщение
проще так
или так
C++
1
2
3
4
5
6
7
8
9
10
11
#include <iostream>
 
int main()
{
char str[] = "reverse";
size_t i = 0;
        
  while( str[i] ) std::cout << str[strlen(str) - ++i];         
       
return 0;
}
1
ISergey
Maniac
Эксперт С++
1426 / 932 / 154
Регистрация: 02.01.2009
Сообщений: 2,774
Записей в блоге: 1
08.09.2009, 02:07 8
mirso, э не.. исходная строка у вас не меняется..
0
Golovastik
11 / 11 / 2
Регистрация: 25.05.2009
Сообщений: 435
08.09.2009, 20:12  [ТС] 9
Что-то я не могу понять вот эту строку:
C++
1
while(start < end)
Ведь смотрите, строка Россия - щедрая душа, занимает 20 символов+нулевой символ окончания = 21.
Теперь происходит такое условие: "Пока 21(тоесть start) < 20(end)".
Как может 21 быть меньше 20,ведь тогда цикл прекратится сразу.
Как это понимать?
0
easybudda
Модератор
Эксперт JavaЭксперт CЭксперт С++
10297 / 6179 / 1555
Регистрация: 25.07.2009
Сообщений: 11,762
08.09.2009, 20:28 10
Цитата Сообщение от Golovastik Посмотреть сообщение
Что-то я не могу понять вот эту строку:
C++
1
while(start < end)
Ведь смотрите, строка Россия - щедрая душа, занимает 20 символов+нулевой символ окончания = 21.
Теперь происходит такое условие: "Пока 21(тоесть start) < 20(end)".
Как может 21 быть меньше 20,ведь тогда цикл прекратится сразу.
Как это понимать?
1. strlen возвращает длинну строки без завершающего нуля.
2.
C
1
2
3
4
char *s = "Россия - щедрая душа";
char *start = s; /* то же, что start = &s[0]; то есть Р*/
char *end = s + strlen(s) - 1; /* тоже, что end = &s[strlen(s) - 1];  */
/* *start == 'P'; *end == 'a'; */
а дальше - пока указатель на начало меньше указателя на конец строки, поменять местами то, на что они указывают, start увеличить, end уменьшить, то есть на втором проходе start указывает на второй символ, end - на предпоследний...
0
M128K145
Эксперт JavaЭксперт С++
8340 / 3561 / 420
Регистрация: 03.07.2009
Сообщений: 10,708
08.09.2009, 20:46 11
Golovastik, грубо говоря происходит следующее(сразу скажу что и start, и end проходят всего половину строки)

Р|о|с|с|и|я| |-| |щ|е|д|р|а|я| |д|у|ш|а
s|*|*|*|*|*|*|*|*|*|*|*|*|*|*|*|*|*|*|e
*|s|*|*|*|*|*|*|*|*|*|*|*|*|*|*|*|*|e|*
*|*|s|*|*|*|*|*|*|*|*|*|*|*|*|*|*|e|*|*
*|*|*|s|*|*|*|*|*|*|*|*|*|*|*|*|e|*|*|*
*|*|*|*|s|*|*|*|*|*|*|*|*|*|*|e|*|*|*|*
*|*|*|*|*|s|*|*|*|*|*|*|*|*|e|*|*|*|*|*
*|*|*|*|*|*|s|*|*|*|*|*|*|e|*|*|*|*|*|*
*|*|*|*|*|*|*|s|*|*|*|*|e|*|*|*|*|*|*|*
*|*|*|*|*|*|*|*|s|*|*|e|*|*|*|*|*|*|*|*
*|*|*|*|*|*|*|*|*|s|e|*|*|*|*|*|*|*|*|*
где положение s - start, а e - end на каждой итерации
1
Golovastik
11 / 11 / 2
Регистрация: 25.05.2009
Сообщений: 435
08.09.2009, 22:32  [ТС] 12
Наконец-то прояснилось. Последний вопрос.
Скажите, почему так:
C++
1
2
3
4
    
t = *start;
*start = *end;
*end = t;
А не так:
C++
1
2
3
t = &(*start);
*start = *end;
*end = &t;
Добавлено через 21 минуту
Можно ли написать просто так:
C++
1
2
3
4
5
6
7
8
9
while(start < end)
{
    
    *start = *end;
    *end = start;
    
    start++;
    end--;
}
0
easybudda
Модератор
Эксперт JavaЭксперт CЭксперт С++
10297 / 6179 / 1555
Регистрация: 25.07.2009
Сообщений: 11,762
08.09.2009, 22:32 13
Цитата Сообщение от Golovastik Посмотреть сообщение
Наконец-то прояснилось. Последний вопрос.
Скажите, почему так:
C++
1
2
3
4
    
t = *start;
*start = *end;
*end = t;
А не так:
C++
1
2
3
t = &(*start);
*start = *end;
*end = &t;
t - переменная типа char, а start и end - указатели на переменную типа char. Унарный оператор * - разыменовывание указателя. Суть в следующем: временной переменной t присваивается значение, взятое по адресу start, после чего это значение меняется на то, на которое указывает end, в свою очередь значение, находящиеся по адресу end меняется на значение переменной t. Выражение &(*start) читалось бы примерно так: адрес того, на что указывает start. То есть масло масленное
0
M128K145
Эксперт JavaЭксперт С++
8340 / 3561 / 420
Регистрация: 03.07.2009
Сообщений: 10,708
08.09.2009, 22:43 14
&(*start) эквивалентен start и содержит в себе указатель на всю строку.
*start - содержит в себе указатель на конкретный элемент. Чтобы убедится в этом я всегда советую прибегать к практике, в данном случае к печати. Вот подставь этот код
C++
1
2
3
4
5
6
7
8
9
    while(start < end)
    {
        cout<<start<<'\n'<<*start<<'\n';
        t = *start;
        *start = *end;
        *end = t;
        start++;
        end--;
    }
и посмотри как он отработает. Сразу станет все ясно
0
mirso
527 / 345 / 45
Регистрация: 05.04.2009
Сообщений: 709
08.09.2009, 23:33 15
Цитата Сообщение от ISergey Посмотреть сообщение
mirso, э не.. исходная строка у вас не меняется..
пнял. испрафлюсь.

Golovastik, методов реверсии много
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
#include <string>
 
int main()
{
std::string s = "abracadabra";
size_t i = 1;
    
      std::cout << s << std::endl;
    // - a b r a c a d a b r a -   
  while ( s[i] ) 
  {
    s.insert( 0, 1, s[i] );
    s.erase ( ++i, 1 ); 
  } // - a r b a d a c a r b a -  
      std::cout << s << std::endl;    
 
system( "pause" );       
return 0;
}
0
Golovastik
11 / 11 / 2
Регистрация: 25.05.2009
Сообщений: 435
08.09.2009, 23:55  [ТС] 16
А это, это что-то новенькое, не растолкуете что это делается:

C++
1
2
 s.insert( 0, 1, s[i] );
 s.erase ( ++i, 1 );
0
mirso
527 / 345 / 45
Регистрация: 05.04.2009
Сообщений: 709
09.09.2009, 00:01 17
Golovastik,
Цитата Сообщение от Golovastik Посмотреть сообщение
что это
ты и сам можешь посмотреть
C++
1
2
3
4
5
6
7
  while ( s[i] ) 
  {
    s.insert( 0, 1, s[i] );
    std::cout << s << std::endl;
    s.erase ( ++i, 1 ); 
    std::cout << s << std::endl << std::endl; 
  }
вставка и удаление

что бы лучше заметить разницу сделай так(вставь пробел)
C++
1
std::string s = " abracadabra";
0
AnonymC
1181 / 466 / 87
Регистрация: 23.06.2009
Сообщений: 6,381
Завершенные тесты: 1
12.12.2009, 18:12 18
Цитата Сообщение от mirso Посмотреть сообщение
int main()
{
char str[] = "reverse";
size_t i = 0;
while( str[i] ) std::cout << str[strlen(str) - ++i];
return 0;
}
как переделать что бы функция возвращала?

Добавлено через 9 минут
усё решено!
0
12.12.2009, 18:12
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
12.12.2009, 18:12

Реверсирование строки
может ошибки где есть? .data stroka db 'stroka',0 len equ $-stroka stdout DWORD ? cWritten...

Проверка и реверсирование списка
Проверяем подсписок на элементы с d по k, если таковые имеются, то выводим реверсированный список,...

Реверсирование части подсписков
Здравствуйте! Поставлена следующая задача: реверсировать только подсписки, четных степеней...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
18
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru