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

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 33, средняя оценка - 4.94
igor001
8 / 3 / 1
Регистрация: 12.02.2013
Сообщений: 68
#1

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

14.05.2013, 10:51. Просмотров 4644. Ответов 110
Метки нет (Все метки)

был вчера на собеседовании, попросили написать ф-цию реверса строки (поменять местами 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;
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
14.05.2013, 10:51
Здравствуйте! Я подобрал для вас темы с ответами на вопрос ф-ция реверса строки (C++):

Функция реверса строки - C++
На собеседовании в одну компанию меня попросили на бумажке написать функцию реверса строки. Буквально парой дней раньше я услышал о том...

Написание программы реверса строки - C++
Не могу понять в чем ошибка выдаёт (2 3 3 3 3 3 3 3 3 3) Прошу помощи в нахождении ошибки. #include "stdafx.h" #include <stdio.h> ...

Программа реверса строки: почему на экран выводится мусор, вместо нужного текста? - C++
Пишу программу реверса строки (меняет местами первый символ и последний, второй и предпоследний и т.д.). На экран выводится мусор, вместо...

Какая ф-ция в VC++ определяет длину строки??? - C++
Здравствуйте ... не могу разобраться со строками в VC++ помогите пожалуйста

Реализация реверса массива - C++
Первый и последний элемент массива трогать не надо. Как его толком перевернуть? По-разному пробовал уже, не хотят циферки по серединке...

ф-ция - C++
Написать программу, проверяющую делимость целого числа на числа от 2 до 10. Проверка делимости на конкретное число должна быть реализована...

110
ForEveR
В астрале
Эксперт С++
7978 / 4737 / 321
Регистрация: 24.06.2010
Сообщений: 10,543
Завершенные тесты: 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 / 0
Регистрация: 13.05.2013
Сообщений: 6
14.05.2013, 17:25 #47
не могу исправит ошибку в вижел студии что надо для этого сделать
0
Tulosba
:)
Эксперт С++
4396 / 3232 / 297
Регистрация: 19.02.2013
Сообщений: 9,045
14.05.2013, 17:35 #48

Не по теме:

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



Добавлено через 2 минуты
Цитата Сообщение от ForEveR Посмотреть сообщение
If not, the behavior is undefined.
Но тут не стоит забывать и о корреляции. Сомнительно, скажем, чтобы запущенный в виртуалке компилятор смог отформатировать реальный диск, несмотря на все возможности UB
0
accept
4823 / 3244 / 165
Регистрация: 10.12.2008
Сообщений: 10,682
15.05.2013, 02:00 #49
Цитата Сообщение от igor001 Посмотреть сообщение
в случае пустой строки, указатель end_str указывает на область памяти перед 1м эл-том соответственно в цикл прога не заходит
при циклической реализации "область памяти перед первым элементом" может оказаться с другой стороны
по стандарту правильный результат сравнения указателей гарантируется только для адресов элементов одного массива
0
vxg
Модератор
3172 / 1975 / 222
Регистрация: 13.01.2012
Сообщений: 7,605
15.05.2013, 09:10 #50
Цитата Сообщение от accept Посмотреть сообщение
может оказаться с другой стороны
вот поэтому нужно что бы это был указатель на последний элемент. в случае пустой строки этот указатель останется равным началу строки и заход в цикл не произойдет по условию "меньше" так как указатели будут равны
0
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;
}
0
vxg
Модератор
3172 / 1975 / 222
Регистрация: 13.01.2012
Сообщений: 7,605
15.05.2013, 10:14 #52
Цитата Сообщение от igor001 Посмотреть сообщение
следующий код
возврат false для пустой строки - спорный вопрос. вполне можно вернуть true - попробуйте докажите что мы не обратили строку ?
еще раз хотелось бы отметить что
C++
1
char* end_str = &str[0];
рационально записать как
C++
1
char* end_str = str;
+ в 1001 раз хотелось бы обратить ваше внимание что увлечение инкрементом поставленным перед указателем приводит к тому что вы начинаете поиск конца строки со второго символа. это совсем ни к чему. во всяком случае когда я такое вижу начинаю нервничать - вроде бы ничего не случилось (поскольку мы отсекаем случай пустой строки на входе) но тревожное состояние уже наступило кроме того можно выкинуть условия проверки пустой строки если пользоваться инкрементом после указателя.
1
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;" и было))
0
vxg
Модератор
3172 / 1975 / 222
Регистрация: 13.01.2012
Сообщений: 7,605
15.05.2013, 10:46 #54
Цитата Сообщение от igor001 Посмотреть сообщение
не
вы уменьшаете end_str в цикле перестановки. если строка пустая, то, в случае если end_str равно str и указывает на "начало" памяти при уменьшении вы получите "конец" памяти то есть указатель больший чем str и войдете в цикл. это не гуд

Добавлено через 1 минуту
...кроме того теперь в этом нет нужды - раньше вы были вынуждены так делать потому что после подсчета строки получали end_str указывающий на символ после конца строки. теперь в цикле перестановки вы просто можете делать декремент в теле
0
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 минуты
мб я не очень хорошо умею излагать свои мысли, за это уж простите))
0
vxg
Модератор
3172 / 1975 / 222
Регистрация: 13.01.2012
Сообщений: 7,605
15.05.2013, 11:15 #56
Цитата Сообщение от igor001 Посмотреть сообщение
к тому же массивы располагаются в памяти строго последовательно, а это означает что Ваше следующее заключение так же неверно
не знаю что вы этим хотите сказать. вот у нас строка. вот у нас оперативная память. ячейки оперативной памяти имеют адреса от 100 (что бы вы не зацикливались на числе 0 - не нужно жестко ассоциировать 0 и NULL) до 200 (ну пускай). строка расположена по адресу 100. мы делаем декремент и получаем 200 (такое вот свойство у арифметики). хотя может я чего то и не выткаю но просто привык к тому что такое может случаться: если что то уменьшаешь ниже пола будь готов что оно может выпрыгнуть тебе на голову.
Цитата Сообщение от igor001 Посмотреть сообщение
не может выйти за пределы массива
имелся ввиду выход за пределы перестановочной части. у вас раньше был инкремент в условии и вы всегда завышали значение указателя.
0
Tulosba
:)
Эксперт С++
4396 / 3232 / 297
Регистрация: 19.02.2013
Сообщений: 9,045
15.05.2013, 11:23 #57
Цитата Сообщение от vxg Посмотреть сообщение
возврат false для пустой строки - спорный вопрос. вполне можно вернуть true - попробуйте докажите что мы не обратили строку
А нужно ли вообще возвращаться какое-то значение?
Кстати, вот, если еще не видели.
0
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;
    }
}
0
vxg
Модератор
3172 / 1975 / 222
Регистрация: 13.01.2012
Сообщений: 7,605
15.05.2013, 11:54 #59
Цитата Сообщение от igor001 Посмотреть сообщение
так что все в порядке
тогда уж как раньше народ предлагал
C++
1
    if(!str || !*str) return;
Добавлено через 55 секунд
иначе
C++
1
while (--end_str > str)
может погнать
0
igor001
8 / 3 / 1
Регистрация: 12.02.2013
Сообщений: 68
15.05.2013, 11:59  [ТС] #60
vxg, запусти у себя эту ф-цию и попробуй сломать, посмотри через дебаг. лично я никаких траблов не смог найти
а проверка указателя нужна на тот случай если кто-нибудь додумается передать в ф-цию нулевой указатель, а все строки в С стиле заканчиваются терминальным нулем, так что передача нулевого указателя в ф-цию это самое опасное что может произойти, по идее))
0
15.05.2013, 11:59
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
15.05.2013, 11:59
Привет! Вот еще темы с ответами:

Операторная ф-ция - C++
Добрый вечер, вот есть код: #include <iostream> #include <stdio.h> #include <stdlib.h> #include <vector> #include...

ф-ция с throw - C++
Встретил такую мне незнакомую запись: тип имя_функции( параметры ) throw(что-то) { тело_ф-ции } Что дает такая запись с...

Параметризованная ф-ция класса - C++
Пытаюсь заменить списки (используя структуры) на списки используя параметризованную функцию класса Компилятор ругается на строчку где я...

ф-ция getche() не выполняется - C++
В MVS 2015 не выполняется ф-ция getche() (в коде строка 52) по этому цикл выполняется всего один раз. Как это исправить? Проверял код в...


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

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

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