Re[4]: От начинающего
От: ppp  
Дата: 23.04.02 05:05
Оценка: 23 (2)
Здравствуйте flyker, Вы писали:

F>А слабо без переменной temp ?


легко

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void reverse(char *pc);
void swap(char &a, char &b);

int main()
{
  char str[] = "abcde";
  reverse(str);
  return 0;
}

void reverse( char *pc )
{
  int i;
  int len = strlen(pc);
  char *tmp = pc;
  for( i=0; i<len/2; i++ )
  {
    swap(*(tmp+i), *(tmp+len-i-1));
  }
}

void swap(char &a, char &b)
{
  a^=b^=a^=b;
}
Если ты такой умный, почему ты такой бедный?
Re[5]: От начинающего
От: DarkGray Россия http://blog.metatech.ru/post/ogni-razrabotki.aspx
Дата: 22.04.02 13:30
Оценка: 3 (1)
Здравствуйте Курилка, Вы писали:

К>Дак это-то я понимаю, только кривовато получается.

К>Тогда вопросики (если не трудно):
К>можно ли этот переворот оптимально итераторами сделать?
К>и насколько хуже string::operator[] прямого доступа?
Смотрим реализация VC6.0 STL

    reference operator[](size_type _P0)
        {if (_Len < _P0 || _Ptr == 0)
            return ((reference)*_Nullstr());
        _Freeze();
        return (_Ptr[_P0]); }
    void _Freeze()
        {if (_Ptr != 0
            && _Refcnt(_Ptr) != 0 && _Refcnt(_Ptr) != _FROZEN)
            _Grow(_Len);
        if (_Ptr != 0)
            _Refcnt(_Ptr) = _FROZEN; }

То есть для каждой [] вызывается куча всякой гадости.

Через итераторы:
#include <iostream>
#include <string>

void main()
{
  std::string s;
  std::cout << "> ";
  std::cin >> s;
  for (std::string::iterator pb = s.begin(), pe = s.end(); pb < pe;)
  {
    --pe;
    std::swap (*pb, *pe);
    ++pb;
  }
  std::cout << s << std::endl;
}
От начинающего
От: Аноним  
Дата: 22.04.02 11:48
Оценка:
Переворот стринга

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

void main(void)
{
char string[81];
char temp;
cout<<"Lamer, vvedi string\n";
cin>>string;
int i=strlen(string);
div_t div_result;
div_result=div(i,2);
int k=0,j=0;
if(div_result.rem)// nechotnoe
j=i/2+1;
else
j=i/2;
while(k<j)
{
temp=string[--i];
string[i]=string[k];
string[k++]=temp;

}


cout<<string<<"\n";
}

Но это- поламерски. Как бы это сделать с указателями (вместо string[81])
Re: От начинающего
От: Кодт Россия  
Дата: 22.04.02 12:24
Оценка:
Здравствуйте Аноним, Вы писали:

А>Переворот стринга


А>Но это- поламерски. Как бы это сделать с указателями (вместо string[81])


1) использовать std::string вместо статического массива
2) использовать указатели там, где у тебя индексы
3) использовать системную функцию strrev

(прием 1 несовместим с 2 и 3 — содержимое строки в общем случае не доступно для произвольной записи, а только через обвеску класса string).

В случае std::string преимущества — интеграция с cin/cout, не надо самостоятельно выделять память; недостатки — нет прямого доступа к содержимому строки, что не позволяет сделать оптимизированный алгоритм переворота.
Перекуём баги на фичи!
Re[2]: От начинающего
От: Курилка Россия http://kirya.narod.ru/
Дата: 22.04.02 12:37
Оценка:
Здравствуйте Кодт, Вы писали:
К>1) использовать std::string вместо статического массива

вот мой (ещё один ламерский ) код:
#include<iostream> 
#include<string> 

void main(void){ 
    std::string string; 
    char temp; 
    int len, mid;
    std::cout << "Lamer, vvedi string\n"; 
    std::cin  >> string; 
    len = string.size()-1; 
    mid = len / 2;
    for(int i = 0; i <= mid ;i++){
        temp = string[i];
        string[i] = (char)string[len-i];
        string[len-i] = temp;
    }
    std::cout << string<<"\n"; 
}



К>2) использовать указатели там, где у тебя индексы


Но по-моему от этого мало чего не изменится (или опять оптимизация за счёт лишней разиндексации?)
вот ещё один кусочек(если кому покритиковать охота ):
#include<iostream.h> 
#include<string.h> 

void main(void){
    char Text[] = "Hi! It's fun!";
    char *string, *p1, *p2;
    char temp; 
    int len;
    string = new char[sizeof(Text)];
    strcpy( string, Text); 
    len = strlen(string)-1; // нуль нам не нужен
    for(p1 = string, p2 = string+len; p1!=p2; p1++,p2--){
        temp = *p2;
        *p1 = *p2;
        *p1 = temp;
    }
    cout << string<<"\n";
    delete[] string;
}


К>3) использовать системную функцию strrev


вот это самое прямое — нафиг писать то, что уже есть, делает то что нужно и вроде себя зарекомендовало, хотя со вводом char * только лишние мороки, на мой взгляд того не стоящие.
Re: От начинающего
От: DarkGray Россия http://blog.metatech.ru/post/ogni-razrabotki.aspx
Дата: 22.04.02 12:37
Оценка:
Здравствуйте Аноним, Вы писали:

Если уж пошел разговор за ламеров, то вот этот код:
div_t div_result;
div_result=div(i,2);
int k=0,j=0;
if(div_result.rem)// nechotnoe       
    j=i/2+1;
else
    j=i/2;

нафиг не нужен
Достаточно:
int j = i/2;




Через указатели:
#include <iostream>
#include <string>

void main()
{
  std::string s;
  std::cout << "> ";
  std::cin >> s;
  int len = s.size();
  char * ss = new char[len+1];
  strcpy (ss, s.c_str());
  for (char *pb = ss, *pe = ss + len-1; pb < pe;++pb, --pe)
  {
    std::swap (*pb, *pe);
  }
  std::cout << ss << std::endl;
  delete[] ss;
}
Re[2]: От начинающего
От: Курилка Россия http://kirya.narod.ru/
Дата: 22.04.02 12:40
Оценка:
Здравствуйте DarkGray, Вы писали:

DG>Здравствуйте Аноним, Вы писали:


DG>Если уж пошел разговор за ламеров, то вот этот код:

DG>
DG>div_t div_result;
DG>div_result=div(i,2);
DG>int k=0,j=0;
DG>if(div_result.rem)// nechotnoe       
DG>    j=i/2+1;
DG>else
DG>    j=i/2;  
DG>

DG>нафиг не нужен
DG>Достаточно:
DG>
DG>int j = i/2;
DG>




DG>Через указатели:

DG>
DG>#include <iostream>
DG>#include <string>

DG>void main()
DG>{
DG>  std::string s;
DG>  std::cout << "> ";
DG>  std::cin >> s;
DG>  int len = s.size();
DG>  char * ss = new char[len+1];
DG>  strcpy (ss, s.c_str());
DG>  for (char *pb = ss, *pe = ss + len-1; pb < pe;++pb, --pe)
DG>  {
DG>    std::swap (*pb, *pe);
DG>  }
DG>  std::cout << ss << std::endl;
DG>  delete[] ss;
DG>}
DG>


Клёва, получилась смесь из моих кусков кода, только получше (баг у себя нашёл — нуль на конце забыл в выделении памяти). Только вот спрашивается зачем char* и std::string мешать?
Re[3]: От начинающего
От: DarkGray Россия http://blog.metatech.ru/post/ogni-razrabotki.aspx
Дата: 22.04.02 12:45
Оценка:
Здравствуйте Курилка, Вы писали:

К>Клёва, получилась смесь из моих кусков кода, только получше (баг у себя нашёл — нуль на конце забыл в выделении памяти). Только вот спрашивается зачем char* и std::string мешать?


А ты предложи мне безглючный способ ввода строки в char*?

Или прямой доступ к std::string?
Re[4]: От начинающего
От: Курилка Россия http://kirya.narod.ru/
Дата: 22.04.02 12:53
Оценка:
Здравствуйте DarkGray, Вы писали:

DG>Здравствуйте Курилка, Вы писали:


К>>Клёва, получилась смесь из моих кусков кода, только получше (баг у себя нашёл — нуль на конце забыл в выделении памяти). Только вот спрашивается зачем char* и std::string мешать?


DG>А ты предложи мне безглючный способ ввода строки в char*?


DG>Или прямой доступ к std::string?


Дак это-то я понимаю, только кривовато получается.
Тогда вопросики (если не трудно):
можно ли этот переворот оптимально итераторами сделать?
и насколько хуже string::operator[] прямого доступа?
Re: От начинающего
От: Sergei  
Дата: 22.04.02 12:59
Оценка:
Здравствуйте Аноним, Вы писали:

А>Переворот стринга


void reverseString(char* str)
{
char* begin=str;
char* end=str+strlen(str)-1;
while(begin<end)
std::swap(*begin++,*end--);
}
Re[3]: От начинающего
От: flyker Россия  
Дата: 22.04.02 13:45
Оценка:
Здравствуйте Курилка, Вы писали:

К>Здравствуйте Кодт, Вы писали:

К>>1) использовать std::string вместо статического массива

К>вот мой (ещё один ламерский ) код:

К>
К>#include<iostream> 
К>#include<string> 

К>void main(void){ 
К>    std::string string; 
К>    char temp; 
К>    int len, mid;
К>    std::cout << "Lamer, vvedi string\n"; 
К>    std::cin  >> string; 
К>    len = string.size()-1; 
К>    mid = len / 2;
К>    for(int i = 0; i <= mid ;i++){
К>        temp = string[i];
К>        string[i] = (char)string[len-i];
К>        string[len-i] = temp;
К>    }
К>    std::cout << string<<"\n"; 
К>} 
К>



К>>2) использовать указатели там, где у тебя индексы


К>Но по-моему от этого мало чего не изменится (или опять оптимизация за счёт лишней разиндексации?)

К>вот ещё один кусочек(если кому покритиковать охота ):
К>
К>#include<iostream.h> 
К>#include<string.h> 

К>void main(void){
К>    char Text[] = "Hi! It's fun!";
К>    char *string, *p1, *p2;
К>    char temp; 
К>    int len;
К>    string = new char[sizeof(Text)];
К>    strcpy( string, Text); 
К>    len = strlen(string)-1; // нуль нам не нужен
К>    for(p1 = string, p2 = string+len; p1!=p2; p1++,p2--){
К>        temp = *p2;
К>        *p1 = *p2;
К>        *p1 = temp;
К>    }
К>    cout << string<<"\n";
К>    delete[] string;
К>} 
К>


К>>3) использовать системную функцию strrev


К>вот это самое прямое — нафиг писать то, что уже есть, делает то что нужно и вроде себя зарекомендовало, хотя со вводом char * только лишние мороки, на мой взгляд того не стоящие.



А слабо без переменной temp ?
Все гениальное — просто
Re[6]: От начинающего
От: Курилка Россия http://kirya.narod.ru/
Дата: 22.04.02 13:47
Оценка:
Здравствуйте DarkGray, Вы писали:
DG>Смотрим реализация VC6.0 STL

DG>
DG>    reference operator[](size_type _P0)
DG>        {if (_Len < _P0 || _Ptr == 0)
DG>            return ((reference)*_Nullstr());
DG>        _Freeze();
DG>        return (_Ptr[_P0]); }
DG>    void _Freeze()
DG>        {if (_Ptr != 0
DG>            && _Refcnt(_Ptr) != 0 && _Refcnt(_Ptr) != _FROZEN)
DG>            _Grow(_Len);
DG>        if (_Ptr != 0)
DG>            _Refcnt(_Ptr) = _FROZEN; }
DG>

DG>То есть для каждой [] вызывается куча всякой гадости.

вот STPort гадости вроде как не вставляет (_M_start — указатель):
  const_reference operator[](size_type __n) const
    { return *(this->_M_start + __n); }
  reference operator[](size_type __n)
    { return *(this->_M_start + __n); }


DG>Через итераторы:

DG>
DG>#include <iostream>
DG>#include <string>

DG>void main()
DG>{
DG>  std::string s;
DG>  std::cout << "> ";
DG>  std::cin >> s;
DG>  for (std::string::iterator pb = s.begin(), pe = s.end(); pb < pe;)
DG>  {
DG>    --pe;
DG>    std::swap (*pb, *pe);
DG>    ++pb;
DG>  }
DG>  std::cout << s << std::endl;
DG>}
DG>


это-то понятно, я имел в виду какой-нибудь принципиально иной метод (хотя по ходу это наверно моя выдумка...)
Re[4]: От начинающего
От: Кодт Россия  
Дата: 22.04.02 14:34
Оценка:
Здравствуйте flyker, Вы писали:

F>А слабо без переменной temp ?


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

С другой стороны — нам ведь нужно вывести строку на обозрение.
А то как мы узнаем, что в ней есть...
void main()
{
  string str;
  cin >> str;
  string::iterator i = str.end();
  while(i != str.begin())
    cout << *(--i);
  cout << endl;
}
Перекуём баги на фичи!
Re: От начинающего
От: Bell Россия  
Дата: 22.04.02 15:37
Оценка:
Здравствуйте Аноним, Вы писали:

using namespace std;


int main(int argc, char* argv[])
{
string str("Some string");
reverse(str.begin(), str.end());
return 0;
}
Любите книгу — источник знаний (с) М.Горький
Re[5]: От начинающего
От: Курилка Россия http://kirya.narod.ru/
Дата: 23.04.02 05:22
Оценка:
Здравствуйте ppp, Вы писали:

ppp>Здравствуйте flyker, Вы писали:


F>>А слабо без переменной temp ?


ppp>легко


ppp>
ppp>#include <stdio.h>
ppp>#include <stdlib.h>
ppp>#include <string.h>

ppp>void reverse(char *pc);
ppp>void swap(char &a, char &b);

ppp>int main()
ppp>{
ppp>  char str[] = "abcde";
ppp>  reverse(str);
ppp>  return 0;
ppp>}

ppp>void reverse( char *pc )
ppp>{
ppp>  int i;
ppp>  int len = strlen(pc);
ppp>  char *tmp = pc;
ppp>  for( i=0; i<len/2; i++ )
ppp>  {
ppp>    swap(*(tmp+i), *(tmp+len-i-1));
ppp>  }
ppp>}

ppp>void swap(char &a, char &b)
ppp>{
ppp>  a^=b^=a^=b;
ppp>}
ppp>


Замечания (не судите и не судимы будете..., но всё же):
1. модификация константы есть не хорошо (вот тут кое-что об том было — http://www.rsdn.ru/forum/message.asp?mid=43714&amp;only
Автор: Sergei
Дата: 09.04.02
)
2. цикл у тебя ну не оптимальный (большую часть вычислений из него можно вынести и избавиться от переменной i, примеры смотри рядом)
Хотя если смысл был избавиться от temp, то ты своего достиг
Re[5]: От начинающего
От: Кодт Россия  
Дата: 23.04.02 07:04
Оценка:
Здравствуйте ppp, Вы писали:

F>>А слабо без переменной temp ?


ppp>легко


void swap(char &a, char &b)
{
  a^=b^=a^=b;
}


Колдун!
Перекуём баги на фичи!
Re[6]: От начинающего
От: ppp  
Дата: 24.04.02 06:31
Оценка:
Здравствуйте Курилка, Вы писали:
К>Замечания (не судите и не судимы будете..., но всё же):
К>1. модификация константы есть не хорошо (вот тут кое-что об том было — http://www.rsdn.ru/forum/message.asp?mid=43714&amp;only
Автор: Sergei
Дата: 09.04.02
)

К>2. цикл у тебя ну не оптимальный (большую часть вычислений из него можно вынести и избавиться от переменной i, примеры смотри рядом)
К>Хотя если смысл был избавиться от temp, то ты своего достиг :)

Ну если придираться так придираться :))
1)
char str[] = "abcde"; //это вовсе не константная строка
//char *cptr = "aaa"; вот это уже константа

2) цикл нормальный (оптимальный). Требует O(n/2) вычислений и перестановок, где n — длина строки. Можно вводить temp-переменные. Тут я с тобой согласен, что быстродействие может увеличиться (а может и нет). Просто это не относится к оптимизации цикла, а к оптимизации кода.
Если ты такой умный, почему ты такой бедный?
Re: От начинающего
От: Deb Россия  
Дата: 25.04.02 12:28
Оценка:
Вот небольшой текстик:
#include <string.h>
void my_reverse(char* str)
{
int len = strlen(str)-1;
for (int b = 0; b < len; b++, len--)
str[b] ^= str[len] ^= str[b]^= str[len];

}
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.