Модераторы: bsa
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Задача на реверс строки 
V
    Опции темы
Arden
Дата 4.2.2009, 20:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 20
Регистрация: 23.1.2009
Где: Украина, Волынь

Репутация: нет
Всего: нет



Задача состоит в следующем: Каждое слово в строке вывести в обратном виде, при этом сохранить порядок слов. Например "меня зовут артём" надо вывести как "янем тувоз мётра". Собственно вот:
Код

#include <cstdlib>
#include <iostream>
#include <string.h>

using namespace std;

int main(int argc, char *argv[])
{
    char a[50] = "Hello world";
    char *p = a;
    int n=1;
    for(int i=0;i<strlen(a);i++){ // Определяем количество слов
            if(*(a+i)==' ') n++;  // пересчитав пробелы.
            }
    for(int i=0;i<n;i++){         
            p = strtok(p," \0");  // находим слово,
            strrev(p);                 // переворачиваем его
            cout<<p<<" ";         // и выводим
            p+=strlen(p)+1;       // Сдвигаем указатель на начало следующего слова.
            }
    cout<<endl;
    system("PAUSE");
    return EXIT_SUCCESS;
}

Мне показалось, что программа довольно кривая, хоть и работает, поэтому и создал тему. Подскажите, пожалуйста, алгоритм получше. Как работает функция strrev() и что она возвращает? Я так понял что она возвращает адрес указателю и изменяет сам массив? Меня интересует, почему после использования этой функции strrev() и вызове cout<<a выводится только первое слово, но если сместить указатель дальше на количество символов в этом слове, то можно работать с остальной частью массива а? Надеюсь я понятно выразился, если нет, то распишу свою мысль. Если можно еще какие то советы по теме. Спасибо.
PM MAIL   Вверх
GoldFinch
Дата 4.2.2009, 21:20 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата



****


Профиль
Группа: Завсегдатай
Сообщений: 2141
Регистрация: 30.11.2008

Репутация: 6
Всего: 26



алгоритм прост: в цикле с текущей позиции ищем пробел или 0, переворачиваем строку между началом слова и его концом, и так далее
переворачивать можно на месте или переписывать в другой буфер
PM MAIL ICQ   Вверх
mes
Дата 4.2.2009, 21:43 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 79
Всего: 250



Цитата(Arden @  4.2.2009,  19:46 Найти цитируемый пост)
Меня интересует, почему 

Потому что функция strtok() ставит символ конца строки ('\0') вместо символа разделителя, который вы указали (' ')
 



--------------------
PM MAIL WWW   Вверх
Rififi
Дата 4.2.2009, 22:05 (ссылка) |   (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1254
Регистрация: 9.3.2008

Репутация: 3
Всего: 36



Arden, 
на С++ можно и покрасивше сделать (:

Код
#include <string>
#include <algorithm>
#include <functional>
#include <iterator>

template <typename T>
void reverse_words(T begin, T end)
{
    typedef typename std::iterator_traits<T>::value_type value_type;
    const value_type space = value_type(' ');

    T b = begin;
    while (true)
    {
        b = std::find_if(b, end, std::not1(std::bind2nd(std::equal_to<value_type>(), space)));
        if (b == end)
            break;
        T e = std::find(b, end, space);
        std::reverse(b, e);
        if (e == end)
            break;
        b = e;
    }
}


Добавлено через 3 минуты и 53 секунды
использование:
Код
std::string s = "меня зовут артём";
reverse_words(s.begin(), s.end());
std::cout << s << std::endl;


Это сообщение отредактировал(а) Rififi - 4.2.2009, 22:05
PM MAIL   Вверх
mes
Дата 4.2.2009, 22:10 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 79
Всего: 250



а вот на си с результатом в отдельном буффере и со списком разделителей :
Код

    char a[] = "Hello world, World ,hello";
    char b[sizeof(a)/sizeof(char)]= { 0 };


    for (char * p = a, *p1=a, *pb=b; ;++p)
    if(*p==' '|| *p==',' || *p=='\0') // дополнить список разделителей если необходимо :
    {
       for (char *p2=p-1; p2>=p1; --p2)
       *(pb++)= *p2;   // реверс слова

       *(pb++)=*p; // перенос текущего разделителя

       if  (*p=='\0') break; // прерывание цикла по концу строки

       p1=p+1; // указание нового начала слова
    }


    cout << b;



--------------------
PM MAIL WWW   Вверх
Arden
Дата 5.2.2009, 00:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 20
Регистрация: 23.1.2009
Где: Украина, Волынь

Репутация: нет
Всего: нет



Цитата(GoldFinch @  4.2.2009,  20:20 Найти цитируемый пост)
алгоритм прост: в цикле с текущей позиции ищем пробел или 0, переворачиваем строку между началом слова и его концом, и так далеепереворачивать можно на месте или переписывать в другой буфер

Ну что то подобное я и сделал smile 

Цитата(mes @  4.2.2009,  20:43 Найти цитируемый пост)
Потому что функция strtok() ставит символ конца строки ('\0') вместо символа разделителя, который вы указали (' ')

Это объясняет всё над чем я ломал голову smile 

Цитата(Rififi @  4.2.2009,  21:05 Найти цитируемый пост)
Arden, на С++ можно и покрасивше сделать (:

Не дорос я еще, похоже, в таких кодах копаться smile 

Цитата(mes @  4.2.2009,  21:10 Найти цитируемый пост)
а вот на си с результатом в отдельном буффере и со списком разделителей :

А ваш вариант разобрал, спасибо большое за ответ и комменты к коду smile 
PM MAIL   Вверх
afanp
Дата 6.2.2009, 17:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 147
Регистрация: 25.11.2008

Репутация: нет
Всего: нет



Код

#include "stdafx.h"
#include <string>
#include <iostream>
using namespace std;
int main(){
    string s1,s2;
    getline(cin,s1);
    s1=s1+' ';
    for(int i=0;i<s1.length();i++){
        s2=s2+s1[i];
        if(s1[i]==' '){
            for(int j=s2.length();j>=0;j--){
                cout << s2[j];}
            cout << endl;
            s2.clear();
        }
    }
    system("pause");
    return 0;
}

а так ни?
PM MAIL   Вверх
Rififi
Дата 6.2.2009, 19:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1254
Регистрация: 9.3.2008

Репутация: 3
Всего: 36



afanp, 
100% undefined behavior во внутреннем цикле
PM MAIL   Вверх
afanp
Дата 6.2.2009, 19:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 147
Регистрация: 25.11.2008

Репутация: нет
Всего: нет



Rififi, 
работает все )
PM MAIL   Вверх
bsa
Дата 6.2.2009, 21:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196



Цитата(afanp @ 6.2.2009,  19:27)
Rififi, 
работает все )

Удивительно. Ты же выходишь за границу массива.
PM   Вверх
GoldFinch
Дата 6.2.2009, 21:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата



****


Профиль
Группа: Завсегдатай
Сообщений: 2141
Регистрация: 30.11.2008

Репутация: 6
Всего: 26



UB оно только до компиляции UB, а готовая прога работает весьма определенным образом
PM MAIL ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0560 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.