Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.52/65: Рейтинг темы: голосов - 65, средняя оценка - 4.52
0 / 1 / 4
Регистрация: 20.10.2013
Сообщений: 270
1

Написать функцию swap

26.03.2014, 14:26. Показов 12354. Ответов 73
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
был вот такой код:
C++
1
2
3
4
5
6
7
8
9
10
for(i = 0; i < n - 1; i++)
    {
        for(j = i + 1; j < n; j++)
        {
            if(p[i].pro < p[j].pro)
            {
            swap (p[i], p[j]);
            }
        }
    }
нужно теперь написать функцию swap, вот мои наброски, но почему то ничего не получается, помогите:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
for(i = 0; i < n - 1; i++)
    {
        for(j = i + 1; j < n; j++)
        {
            if(p[i].pro < p[j].pro)
            {
                void swap (p[i].pro, p[j].pro);
                int t = p[i].pro;
                p[i].pro = p[j].pro;
                p[j].pro = t;
            }
        }
    }
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
26.03.2014, 14:26
Ответы с готовыми решениями:

Заменить функцию swap
У меня есть программа. Я задаю массив, потом мне выводится массив, в котором удаляются все...

Чем можно заменить функцию swap?
Чем можно заменить функцию swap? Она на моем компиляторе не работает. Библиотеку iostream...

Массив: Описать функцию swap(A,B), меняющую местами максимальные элементы матриц А и В.
Надо исправить программу чтобы заработала. У самой уже ничего не получается=(( Описать функцию...

Напишите функцию Swap(a, b), аргументами которой могут быть числа любого типа
Напишите функцию Swap(a, b), аргументами которой могут быть числа любого типа. Функция меняет...

73
Модератор
Эксперт по электронике
8908 / 6677 / 918
Регистрация: 14.02.2011
Сообщений: 23,521
26.03.2014, 17:35 21
Author24 — интернет-сервис помощи студентам
Цитата Сообщение от gazlan Посмотреть сообщение
Попробуйте обменять два равных значения.
a=5 b=5
a=a^b 5^5=0
b=a^b 0^5=5
a=a^b 0^5=5

попробовал

Добавлено через 1 минуту
с минусами плюсами
a=a+b; 5+5=10
b=a-b; 10-5=5
a=a-b; 10-5=5
0
3176 / 1935 / 312
Регистрация: 27.08.2010
Сообщений: 5,131
Записей в блоге: 1
26.03.2014, 17:58 22
Цитата Сообщение от ValeryS Посмотреть сообщение
попробовал
Угу. Запамятовал. Это не будет работать, если оба аргумента разделяют тот же самый адрес.
0
Модератор
Эксперт по электронике
8908 / 6677 / 918
Регистрация: 14.02.2011
Сообщений: 23,521
26.03.2014, 18:21 23
Цитата Сообщение от gazlan Посмотреть сообщение
Это не будет работать, если оба аргумента разделяют тот же самый адрес.
а зачем их тогда менять
0
3176 / 1935 / 312
Регистрация: 27.08.2010
Сообщений: 5,131
Записей в блоге: 1
26.03.2014, 18:35 24
Эта ситуация возможна, когда обмениваются элементы некоторого набора. Поэтому при использования XOR Swap() обязательна проверка на несовпадение адресов. Ссылку с ходу не дам, но парочка громких фэйлов, связанная с использованием этого трюка в DB точно была.

И, к слову, "наивный" метод с третьей переменной, обычно, эффективнее.
0
18840 / 9839 / 2408
Регистрация: 30.01.2014
Сообщений: 17,280
26.03.2014, 18:59 25
Лучший ответ Сообщение было отмечено ValeryS как решение

Решение

Вариант с прибитым гвоздями xor (или аналогичный) на современных машинах самый дурацкий. Т.к. вносит прямую зависимость операций, что препятствует эффективному параллельному выполнению внутри конвейера. Т.е. при мизерном выигрыше в памяти получаем замедление выполнения. Еще не стоит забывать, что обменивать так можно только целые числа. И еще, рекомендую чаще смотреть на ассемблерный код, который генерит ваш компилятор, не исключено, что он уже и так оптимизировал вариант с временной переменной, до варианта с xor. Во многих гайдланах к современным компиляторам к тому же написано, что не стоит заниматься ручной микрооптимизацией кода, т.к. это может заблокировать более эффективную и обширную оптимизацию компилятора.
Все это естественно не касается тех, кто пишет под встроенные системы, или около того. Там свои законы, и там оправданное применение xor-swap может найтись. Однако это не отменяет профилирования, а значит доказательства того, что именно этот вариант выигрывает по скорости в нашей задаче.
Юзать такое решение по-умолчанию, не очень хорошая идея, но знать про него безусловно полезно.
3
:)
Эксперт С++
4773 / 3267 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
26.03.2014, 19:17 26
Цитата Сообщение от DrOffset Посмотреть сообщение
но знать про него безусловно полезно.
В первую очередь полезно знать про нежелательность преждевременных оптимизаций, о чем уже, собственно, было сказано выше.
А варианты с ксорами сродни использованию сдвигов вместо деления/умножения на степень двойки. Часто они рассматриваются новичками как некоторое "хакерского" решение (которое якобы должно работать быстрее) без понимания сути происходящего.
2
Модератор
Эксперт по электронике
8908 / 6677 / 918
Регистрация: 14.02.2011
Сообщений: 23,521
26.03.2014, 19:57 27
Цитата Сообщение от DrOffset Посмотреть сообщение
Еще не стоит забывать, что обменивать так можно только целые числа.
это почему еще

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
void swapD(long long *a, long long *b)
{
*a=*a^*b;
*b=*a^*b;
*a=*a^*b;
}
 
void swapF(int *a, int *b)
{
*a=*a^*b;
*b=*a^*b;
*a=*a^*b;
}
.........................
float fA=10E30f;
float fB=10E-30f;
 
double dA=10E30;
double dB=10E-30;
 
 
swapD((long long*)&dA,(long long*)&dB);
swapF((int*)&fA,(int*)&fB);
прекрасно меняется

DrOffset, Tulosba, я с вами полностью согласен
а это я так, выпендриваюсь
0
18840 / 9839 / 2408
Регистрация: 30.01.2014
Сообщений: 17,280
26.03.2014, 20:02 28
Цитата Сообщение от ValeryS Посмотреть сообщение
а это я так, выпендриваюсь
Зря. Потому что в стандартах С и С++ совершенно не гарантируется, что указатель будет целым числом. И это работает только потому, что на x86 указатели - целые. Но по стандарту твой код - UB.
1
Модератор
Эксперт по электронике
8908 / 6677 / 918
Регистрация: 14.02.2011
Сообщений: 23,521
26.03.2014, 20:11 29
Цитата Сообщение от DrOffset Посмотреть сообщение
Потому что в стандартах С и С++ совершенно не гарантируется,
сошлюсь на Я. Гашека "Похождение бравого солдата Швейка"
"Много что не разрешается, но допускается"
Цитата Сообщение от DrOffset Посмотреть сообщение
что указатель будет целым числом. И это работает только потому, что на x86 указатели - целые.
а где ты указатели увидел?
я беру адрес и интерпретирую его содержимое по другому
UB. там может быть из за несовпадения размеров плавающих и целочисленных
0
DrOffset
26.03.2014, 20:18
  #30

Не по теме:

Цитата Сообщение от ValeryS Посмотреть сообщение
а где ты указатели увидел?
Да, сори - проглядел. Увидел параметры и перещелкнуло :)

0
3176 / 1935 / 312
Регистрация: 27.08.2010
Сообщений: 5,131
Записей в блоге: 1
26.03.2014, 20:19 31
Обсуждение в MSDN: Stupid Coding Tricks
0
Модератор
Эксперт по электронике
8908 / 6677 / 918
Регистрация: 14.02.2011
Сообщений: 23,521
26.03.2014, 20:22 32
gazlan,
я так понял что там неоднозначность из-за точек следования
недавно где то тема такая пролетала и именно с такой конструкцией
C++
1
a ^= b ^= a ^= b;
0
3176 / 1935 / 312
Регистрация: 27.08.2010
Сообщений: 5,131
Записей в блоге: 1
26.03.2014, 20:29 33
Цитата Сообщение от ValeryS Посмотреть сообщение
неоднозначность из-за точек следования
Там еще и интересные комментарии к статье :-)
0
1130 / 789 / 232
Регистрация: 12.04.2010
Сообщений: 2,012
27.03.2014, 16:00 34
Цитата Сообщение от gazlan Посмотреть сообщение
Обсуждение в MSDN: Stupid Coding Tricks
"During a lunch interview, ... wrote on a napkin: a ^= b ^= a ^= b;"
("За завтраком... написал на салфетке ..." )
Прочитал 1-ю строчку и подумал, стоит ли читать дальше?
Автор заметки "Stupid Coding Tricks", видимо, плохо понимает, о чём пишет. Он путает
1) порядок выполнения операций ^=
этот порядок задан однозначно, т.к. a ^= b ^= a ^= b; эквивалентно a ^= (b ^= (a ^= b) );
2) порядок вычисления аргументов (сначала a, потом b или наоборот). Здесь, действительно C++ не даёт никаких гарантий.

Добавлено через 1 час 22 минуты
Здесь (см.пример на C++) ( Алгоритм обмена при помощи исключающего ИЛИ ) (см.пример на C++) объясняется, почему неправильна запись x ^= (y ^= (x ^= y));
0
Модератор
Эксперт по электронике
8908 / 6677 / 918
Регистрация: 14.02.2011
Сообщений: 23,521
27.03.2014, 16:08 35
Цитата Сообщение от Alex5 Посмотреть сообщение
Здесь (см.пример на C++)
я не могу найти, где то здесь на форуме, месяца два назад,человек писал, что всегда пользовался
вот такой записью
C++
1
a ^= b ^= a ^= b;
и все работало, но стоило изменить аргументы, то ли с указателя на ссылку то ли наоборот, и все рухнуло
0
1130 / 789 / 232
Регистрация: 12.04.2010
Сообщений: 2,012
27.03.2014, 21:22 36
Цитата Сообщение от ValeryS Посмотреть сообщение
месяца два назад,человек писал
Да, в начале февраля рассматривалась эта тема:
Цитата Сообщение от Pershin Посмотреть сообщение
вторая запись перестает работать, если вынести обмен в функцию
Хотелось бы разобраться. Компилятор gcc 4.6.3.
0
4226 / 1795 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
14.03.2015, 15:42 37
Ксор переполняет каждый бит и гарантированно. В данной задаче это не критично, так как переполнение строго парно и исправляет само себя, но беда ксора в неприменимости к большинству типов.

Добавлено через 2 минуты
Цитата Сообщение от gazlan Посмотреть сообщение
Попробуйте обменять два равных значения.
C++
1
2
3
a^=b; // Здесь a обнуляется
b^=a; // Ксор с нолём равен второму операнду, b сохраняет значение
a^=b; // Ксор с нолём равен второму операнду, a восстанавливает значение
Добавлено через 1 минуту
Цитата Сообщение от gazlan Посмотреть сообщение
Угу. Запамятовал. Это не будет работать, если оба аргумента разделяют тот же самый адрес.
Тогда сама задача обмена стоять не должна.

Добавлено через 2 минуты
Цитата Сообщение от ValeryS Посмотреть сообщение
это почему еще
C++
1
void swapD(long long *a, long long *b)
А ничего, что полное имя long long вообще то long long int?

Добавлено через 2 минуты
Цитата Сообщение от ValeryS Посмотреть сообщение
void swapF(int *a, int *b)
Указатель есть целое специального вида, предназначенное для хранения адреса функции, или другого данного, то есть для хранения номер байта (трайта).
Нужны комментарии?

Добавлено через 1 минуту
Цитата Сообщение от ValeryS Посмотреть сообщение
swapF((int*)&fA,(int*)&fB);
А это только при совпадении размеров. И приведение в данном контексте - грязный хак.
0
Форумчанин
Эксперт CЭксперт С++
8215 / 5045 / 1437
Регистрация: 29.11.2010
Сообщений: 13,453
14.03.2015, 17:14 38
Цитата Сообщение от MastAKK Посмотреть сообщение
par1 = par1^par2;
Хреновый вариант. Если менять переменные с одним и тем же адресом он их обнулит.

А для шаблонов - попробуйте передать в swap пользовательский тип. Не вышло? Всё дело в том, что данный алгоритм подходит только для типов, у которых определён operator^.

Добавлено через 2 минуты
Мой вариант (С++11)
C++
1
2
3
4
5
6
7
template <typename T>
void swap(T &a, T &b)
{
    T tmp(std::move(a));
    a = std::move(b);
    b = std::move(tmp);
}
Стоит отметить, что явно указывать тип у шаблонной функции при вызове не требуется.
0
4226 / 1795 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
14.03.2015, 17:54 39
Цитата Сообщение от MrGluck Посмотреть сообщение
реновый вариант. Если менять переменные с одним и тем же адресом он их обнулит.
При совпадении адресов имеет одну переменную и задача обмена её местами просто не может существовать.
0
Модератор
Эксперт по электронике
8908 / 6677 / 918
Регистрация: 14.02.2011
Сообщений: 23,521
14.03.2015, 18:06 40
Цитата Сообщение от taras atavin Посмотреть сообщение
А ничего, что полное имя long long вообще то long long int?
вообще то int допускается опускать
long long тоже самое, что и long long int
short тоже самое, что и short int
Цитата Сообщение от taras atavin Посмотреть сообщение
А это только при совпадении размеров. И приведение в данном контексте - грязный хак.
а я где то утверждал обратное?
Цитата Сообщение от ValeryS Посмотреть сообщение
я беру адрес и интерпретирую его содержимое по другому
UB. там может быть из за несовпадения размеров плавающих и целочисленных
Добавлено через 1 минуту
Цитата Сообщение от taras atavin Посмотреть сообщение
Нужны комментарии?
желательно
0
14.03.2015, 18:06
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
14.03.2015, 18:06
Помогаю со студенческими работами здесь

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

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

Написать функцию, которая могла бы передать значение в другую функцию
как сделать функцию которая бы могла передать значеие в другую функцию ну к примеру a=4*b; где...

не могу разобраться как написать функцию сортировки и исправить функцию добавления в стек
#include &lt;iostream&gt; #include&lt;Windows.h&gt; using namespace std; struct NE{ int x; NE...


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

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru