Форум программистов, компьютерный форум CyberForum.ru

ф-ция реверса строки - C++

Восстановить пароль Регистрация
 
 
Рейтинг: Рейтинг темы: голосов - 33, средняя оценка - 4.94
igor001
8 / 3 / 1
Регистрация: 12.02.2013
Сообщений: 68
14.05.2013, 10:51     ф-ция реверса строки #1
был вчера на собеседовании, попросили написать ф-цию реверса строки (поменять местами 1й и последний символы, 2й и предпоследний и т.д.), но ф-ция должна принимать параметром указатель на char т.е. на начало строки и все. я там немного тупанул но написал, вот хочу узнать есть ли решение получше моего.
вот код (писал в Embarcadero RAD Studio (Borland)):
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//ф-ция принимает указатель на массив char с символом окончания строки '\0'
//и производит реверс полученного массива
void TForm1::reverce(char *str)
{
    char* end_str = &str[0];
 
    while (*end_str != '\0') ++end_str;
    
    char  buf;
    while (end_str > str)
    {
        --end_str;
        buf      = *str;
        *str     = *end_str;
        *end_str = buf;
        ++str;  
    }
}
кто захочет проверить, выносим кнопку, лабел и эдит на форму и в ивент на клик кнопки пишем:
C++
1
2
3
4
5
AnsiString str = Edit1->Text.c_str();
 
    reverce(str.c_str());
 
    Label1->Caption = str;
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
14.05.2013, 10:51     ф-ция реверса строки
Посмотрите здесь:

Функция реверса строки C++
C++ Операторная ф-ция
C++ Глобальная ф-ция getline
C++ Какая ф-ция в VC++ определяет длину строки???
C++ ф-ция с throw
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
igor001
8 / 3 / 1
Регистрация: 12.02.2013
Сообщений: 68
14.05.2013, 16:38  [ТС]     ф-ция реверса строки #41
Цитата Сообщение от ninja2 Посмотреть сообщение
А с начала стека можно?

А чо нельзя ошибка будет? Или оно половину удалит, а половину оставит?
delete и delete[], на сколько я знаю вызывается только для указателей (delete[] - для указателей на массивы)
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Tulosba
:)
Эксперт С++
4378 / 3221 / 297
Регистрация: 19.02.2013
Сообщений: 9,044
14.05.2013, 16:55     ф-ция реверса строки #42
Цитата Сообщение от igor001 Посмотреть сообщение
только для указателей
на объект в динамической памяти (куче). Например так делать нельзя:
C++
1
2
3
4
5
int main() {
   int i;
   delete &i; // ошибка выполнения
   return 0;
}
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
14.05.2013, 16:57     ф-ция реверса строки #43
Tulosba, Я бы сказал, что это UB, а будет-ли это ошибкой выполнения (или форматированием жесткого диска) зависит от реализации
Tulosba
14.05.2013, 17:09
  #44

Не по теме:

Цитата Сообщение от ForEveR Посмотреть сообщение
Я бы сказал, что это UB, а будет-ли это ошибкой выполнения (или форматированием жесткого диска) зависит от реализации
Мне повезло. У меня просто ошибка выполнения

taras atavin
Ушёл с форума.
 Аватар для taras atavin
3569 / 1752 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
14.05.2013, 17:19     ф-ция реверса строки #45
Цитата Сообщение от ForEveR Посмотреть сообщение
Я бы сказал, что это UB, а будет-ли это ошибкой выполнения (или форматированием жесткого диска)
А диск то здесь при чём? В худшем случае порча инфы в памяти.
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
14.05.2013, 17:25     ф-ция реверса строки #46
taras atavin,
In the first alternative (delete object), the value of the operand of delete may be a null pointer
value, a pointer to a non-array object created by a previous new-expression, or a pointer to a subobject (1.8)
representing a base class of such an object (Clause 10). If not, the behavior is undefined.
undefined behavior
behavior for which this International Standard imposes no requirements
Мы ведь говорим про С++? Стандарт С++ не регламентирует, что может произойти в случае UB. Следовательно быть может все что угодно. Вы погуглите, ради интереса, многое найдете.
сайфонг
 Аватар для сайфонг
0 / 0 / 0
Регистрация: 13.05.2013
Сообщений: 6
14.05.2013, 17:25     ф-ция реверса строки #47
не могу исправит ошибку в вижел студии что надо для этого сделать
Tulosba
:)
Эксперт С++
4378 / 3221 / 297
Регистрация: 19.02.2013
Сообщений: 9,044
14.05.2013, 17:35     ф-ция реверса строки #48

Не по теме:

Цитата Сообщение от сайфонг Посмотреть сообщение
не могу исправит ошибку в вижел студии что надо для этого сделать
расставить знаки препинания для начала



Добавлено через 2 минуты
Цитата Сообщение от ForEveR Посмотреть сообщение
If not, the behavior is undefined.
Но тут не стоит забывать и о корреляции. Сомнительно, скажем, чтобы запущенный в виртуалке компилятор смог отформатировать реальный диск, несмотря на все возможности UB
accept
4838 / 3237 / 165
Регистрация: 10.12.2008
Сообщений: 10,682
15.05.2013, 02:00     ф-ция реверса строки #49
Цитата Сообщение от igor001 Посмотреть сообщение
в случае пустой строки, указатель end_str указывает на область памяти перед 1м эл-том соответственно в цикл прога не заходит
при циклической реализации "область памяти перед первым элементом" может оказаться с другой стороны
по стандарту правильный результат сравнения указателей гарантируется только для адресов элементов одного массива
vxg
Модератор
 Аватар для vxg
2669 / 1680 / 158
Регистрация: 13.01.2012
Сообщений: 6,279
15.05.2013, 09:10     ф-ция реверса строки #50
Цитата Сообщение от accept Посмотреть сообщение
может оказаться с другой стороны
вот поэтому нужно что бы это был указатель на последний элемент. в случае пустой строки этот указатель останется равным началу строки и заход в цикл не произойдет по условию "меньше" так как указатели будут равны
igor001
8 / 3 / 1
Регистрация: 12.02.2013
Сообщений: 68
15.05.2013, 09:56  [ТС]     ф-ция реверса строки #51
Цитата Сообщение от accept Посмотреть сообщение
при циклической реализации "область памяти перед первым элементом" может оказаться с другой стороны
по стандарту правильный результат сравнения указателей гарантируется только для адресов элементов одного массива
я немного неправильно изложил мысль. я имел в виду что в случае пустой строки указатель end_str будет указывать на ячейку памяти перед символом окончания строки, т.е. туда, где был бы 1й символ строки. Полагаю можно это сравнить с итераторами в том же векторе, когда end() возвращает указатель на ячейку памяти за последним элементом массива, в нашем случае это символ окончания строки.
в общем получился следующий код:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//ф-ция принимает указатель на массив char с символом окончания строки ('\0')
//и производит реверс полученного массива
//возвращает true в случае успешного выполнения
//возвращает false в случае передачи "нулевого указателя" либо указателя на пустую строку
bool TForm1::reverse(char *str)
{
    if(!str || !*str) return false;     
 
    char* end_str = &str[0];    
 
    while (*++end_str);     
 
    while (--end_str > str)     
    {
        register char buf = *str;   
        *str              = *end_str;
        *end_str          = buf;
        ++str;
    }
 
    return true;
}
vxg
Модератор
 Аватар для vxg
2669 / 1680 / 158
Регистрация: 13.01.2012
Сообщений: 6,279
15.05.2013, 10:14     ф-ция реверса строки #52
Цитата Сообщение от igor001 Посмотреть сообщение
следующий код
возврат false для пустой строки - спорный вопрос. вполне можно вернуть true - попробуйте докажите что мы не обратили строку ?
еще раз хотелось бы отметить что
C++
1
char* end_str = &str[0];
рационально записать как
C++
1
char* end_str = str;
+ в 1001 раз хотелось бы обратить ваше внимание что увлечение инкрементом поставленным перед указателем приводит к тому что вы начинаете поиск конца строки со второго символа. это совсем ни к чему. во всяком случае когда я такое вижу начинаю нервничать - вроде бы ничего не случилось (поскольку мы отсекаем случай пустой строки на входе) но тревожное состояние уже наступило кроме того можно выкинуть условия проверки пустой строки если пользоваться инкрементом после указателя.
igor001
8 / 3 / 1
Регистрация: 12.02.2013
Сообщений: 68
15.05.2013, 10:38  [ТС]     ф-ция реверса строки #53
vxg, полностью с Вами согласен, это не очень хороший стиль программирования. А сделать чтобы ф-ция возвращала булево значение я решил следуя из тех соображений, что таким образом ф-ция может еще и проверить пустая ли строка и указывает ли указатель на строку вообще, хотя это сокрее всего тоже не есть хорошо, так как работа этой ф-ции лишь изменить строку в соответствии с требованиями.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void TForm1::reverse(char *str)
{
    if(!str) return;
 
    char* end_str = str;
 
    while (*end_str) ++end_str;
 
    while (--end_str > str)
    {
        register char buf = *str;
        *str              = *end_str;
        *end_str          = buf;
        ++str;
    }
}
ЗЫ: в первоначальной версии почти так "while (*end_str) ++end_str;" и было))
vxg
Модератор
 Аватар для vxg
2669 / 1680 / 158
Регистрация: 13.01.2012
Сообщений: 6,279
15.05.2013, 10:46     ф-ция реверса строки #54
Цитата Сообщение от igor001 Посмотреть сообщение
не
вы уменьшаете end_str в цикле перестановки. если строка пустая, то, в случае если end_str равно str и указывает на "начало" памяти при уменьшении вы получите "конец" памяти то есть указатель больший чем str и войдете в цикл. это не гуд

Добавлено через 1 минуту
...кроме того теперь в этом нет нужды - раньше вы были вынуждены так делать потому что после подсчета строки получали end_str указывающий на символ после конца строки. теперь в цикле перестановки вы просто можете делать декремент в теле
igor001
8 / 3 / 1
Регистрация: 12.02.2013
Сообщений: 68
15.05.2013, 11:05  [ТС]     ф-ция реверса строки #55
vxg, а вот теперь Вы неправы

Цитата Сообщение от vxg Посмотреть сообщение
вы уменьшаете end_str в цикле перестановки. если строка пустая, то, в случае если end_str равно str и указывает на "начало" памяти при уменьшении вы получите "конец" памяти то есть указатель больший чем str и войдете в цикл. это не гуд
в начале выполняется проверка указателя и если он указывает на 0, на сколько я помню там быть ничего не должно, то будет реторн из ф-ции, к тому же массивы располагаются в памяти строго последовательно, а это означает что Ваше следующее заключение так же неверно

Цитата Сообщение от vxg Посмотреть сообщение
кроме того теперь в этом нет нужды - раньше вы были вынуждены так делать потому что после подсчета строки получали end_str указывающий на символ после конца строки. теперь в цикле перестановки вы просто можете делать декремент в теле
указатель end_str сдвигается вперед и не может выйти за пределы массива, т.к. символ окончания строки является его частью. т.е.:
while(символ)
символ?
да
указатель ++ (сдвинулись и сейчас end_str указывает на '\0')
символ?
нет
break

Добавлено через 2 минуты
хотя посмотрев в дебагере все еще лучше. В случае пустой строки по указателю находится сразу символ окончания строки, так что оба цикла пропускаются, т.к. условия входа в них не выполняются

Добавлено через 4 минуты
мб я не очень хорошо умею излагать свои мысли, за это уж простите))
vxg
Модератор
 Аватар для vxg
2669 / 1680 / 158
Регистрация: 13.01.2012
Сообщений: 6,279
15.05.2013, 11:15     ф-ция реверса строки #56
Цитата Сообщение от igor001 Посмотреть сообщение
к тому же массивы располагаются в памяти строго последовательно, а это означает что Ваше следующее заключение так же неверно
не знаю что вы этим хотите сказать. вот у нас строка. вот у нас оперативная память. ячейки оперативной памяти имеют адреса от 100 (что бы вы не зацикливались на числе 0 - не нужно жестко ассоциировать 0 и NULL) до 200 (ну пускай). строка расположена по адресу 100. мы делаем декремент и получаем 200 (такое вот свойство у арифметики). хотя может я чего то и не выткаю но просто привык к тому что такое может случаться: если что то уменьшаешь ниже пола будь готов что оно может выпрыгнуть тебе на голову.
Цитата Сообщение от igor001 Посмотреть сообщение
не может выйти за пределы массива
имелся ввиду выход за пределы перестановочной части. у вас раньше был инкремент в условии и вы всегда завышали значение указателя.
Tulosba
:)
Эксперт С++
4378 / 3221 / 297
Регистрация: 19.02.2013
Сообщений: 9,044
15.05.2013, 11:23     ф-ция реверса строки #57
Цитата Сообщение от vxg Посмотреть сообщение
возврат false для пустой строки - спорный вопрос. вполне можно вернуть true - попробуйте докажите что мы не обратили строку
А нужно ли вообще возвращаться какое-то значение?
Кстати, вот, если еще не видели.
igor001
8 / 3 / 1
Регистрация: 12.02.2013
Сообщений: 68
15.05.2013, 11:48  [ТС]     ф-ция реверса строки #58
я понял что Вы имели в виду. сначала выполняется "while (*end_str) ++end_str;" т.е. указатель продвигается по массиву до тех пор пока не достигнет терминального нуля, а лишь потом выполняется операция декремента указателя "while (--end_str > str)", т.е. в этом цикле указатели "двигаются" в пределах массива навстречу друг другу (а в пределах массива сравнение указателей по стандарту гарантировано, на сколько я знаю). так что все в порядке

Добавлено через 21 минуту
Tulosba, по ссылке в принципе то же самое, но, конечно, с битовыми операциями сильно)) минус переменная. правда все-таки в варианте, который здесь написан, по моему мнению, если сделать переброску символов не через переменную, а битовыми операциями, лучше

Добавлено через 3 минуты
получается что-то вроде следующего:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void reverse(char *str)
{
    if(!str) return;
 
    char* end_str = str;
 
    while (*end_str) ++end_str;
 
    while (--end_str > str)
    {
        *str     ^= *end_str;
        *end_str ^= *str;
        *str     ^= *end_str;
        ++str;
    }
}
vxg
Модератор
 Аватар для vxg
2669 / 1680 / 158
Регистрация: 13.01.2012
Сообщений: 6,279
15.05.2013, 11:54     ф-ция реверса строки #59
Цитата Сообщение от igor001 Посмотреть сообщение
так что все в порядке
тогда уж как раньше народ предлагал
C++
1
    if(!str || !*str) return;
Добавлено через 55 секунд
иначе
C++
1
while (--end_str > str)
может погнать
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
15.05.2013, 11:59     ф-ция реверса строки
Еще ссылки по теме:

C++ ф-ция
C++ Рандомная ф-ция rand()
C++ Параметризованная ф-ция класса

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

Или воспользуйтесь поиском по форуму:
igor001
8 / 3 / 1
Регистрация: 12.02.2013
Сообщений: 68
15.05.2013, 11:59  [ТС]     ф-ция реверса строки #60
vxg, запусти у себя эту ф-цию и попробуй сломать, посмотри через дебаг. лично я никаких траблов не смог найти
а проверка указателя нужна на тот случай если кто-нибудь додумается передать в ф-цию нулевой указатель, а все строки в С стиле заканчиваются терминальным нулем, так что передача нулевого указателя в ф-цию это самое опасное что может произойти, по идее))
Yandex
Объявления
15.05.2013, 11:59     ф-ция реверса строки
Ответ Создать тему
Опции темы

Текущее время: 23:26. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru