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

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

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 23, средняя оценка - 4.96
VitekSR
0 / 1 / 0
Регистрация: 20.10.2013
Сообщений: 244
#1

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

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

был вот такой код:
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;
            }
        }
    }
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
26.03.2014, 14:26     Написать функцию swap
Посмотрите здесь:

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

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

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

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

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

Написать встроенную функцию min () и обычную функцию imin (), которые возвращают меньшее из двух целых значений - C++
Написать встроенную функцию min () и обычную функцию imin (), которые возвращают меньшее из двух целых значений.

swap - C++
Ф-ция swap, ее написание/подключение. В общем объясните и расскажите как ее подключить и т.д. Спасибо.

После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
hoggy
6369 / 2587 / 452
Регистрация: 15.11.2014
Сообщений: 5,722
Завершенные тесты: 1
15.03.2015, 15:02     Написать функцию swap #61
Цитата Сообщение от MrGluck Посмотреть сообщение
А они, как известно, сохраняют результат вычисления в левом операнде.
ещё известно, что многократное изменение одной и тоже переменной
на протяжении одной точки следования есть undefined behavior.
castaway
Эксперт С++
4881 / 3017 / 370
Регистрация: 10.11.2010
Сообщений: 11,076
Записей в блоге: 10
Завершенные тесты: 1
15.03.2015, 16:01     Написать функцию swap #62
Интересный момент...
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
 
int main()
{
    int i = 1;
    int a[] = { 3, 5 };
 
    a[0] ^= a[1] ^= a[0] ^= a[1];
 
    i = a[i++];
 
    printf( "%d\n", a[0] );
    printf( "%d\n", a[1] );
    return 0;
}
Компилятор GCC 4.9.2 с опциями -std=c++03 и -std=c++11 выдаёт предупреждение:
Bash
1
2
3
4
main.cpp: In function 'int main()':
main.cpp:9:12: warning: operation on 'i' may be undefined [-Wsequence-point]
  i = a[i++];
            ^
только на 10-ю строку.

Если компилировать этот же код как код языка Си этим же компилятором, то это же предупреждение будет распространяться на две строки - 8 и 10.

Цитата Сообщение от Tulosba Посмотреть сообщение
MrGluck, похоже ты не учел отсутствие точек следования.
раз, два.
Первая ссылка ведёт на вопрос по языку Си, вторая на вопрос по С++, но там какая-то каша в ответах в которую смешали Си и С++.

Лично для меня этот вопрос остаётся открытым.
Tulosba
:)
Эксперт С++
4392 / 3235 / 297
Регистрация: 19.02.2013
Сообщений: 9,045
15.03.2015, 23:04     Написать функцию swap #63
castaway, в c++11 заменили термин "sequence point" на отношения "sequenced before", "sequenced after". В связи с чем произошли некоторые изменения в поведении кода. В частности то, что выражение
C++
1
a[0] ^= a[1] ^= a[0] ^= a[1];
считалось до c++11 как UB, в текущем стандарте, судя по всему, таковым не является (поправьте, если я ошибаюсь).

Вырезка из Стандарта на счет оператора присваивания:
14882:2011 5.17/1
In all cases, the assignment is sequenced after the value computation of the right and left operands, and before the value computation of the assignment expression.
Косвенно это подтверждается твоим экспериментом при сборке кода в режимах C и C++11. Как с точки зрения предупреждений компилятора, так и с точки зрения результата выполнения.
У меня например такие результаты:
Bash
1
2
3
4
5
6
7
8
9
10
11
gcc -Wall main.c
main.c: In function ‘main’:
main.c:8:10: warning: operation on ‘a[0]’ may be undefined [-Wsequence-point]
     a[0] ^= a[1] ^= a[0] ^= a[1];
          ^
main.c:10:7: warning: operation on ‘i’ may be undefined [-Wsequence-point]
     i = a[i++];
       ^
./a.out
0
3
Bash
1
2
3
4
5
6
7
8
g++ -Wall main.c
main.c: In function ‘int main()’:
main.c:10:15: warning: operation on ‘i’ may be undefined [-Wsequence-point]
     i = a[i++];
               ^
./a.out
5
3
Хотя clang, что в режиме плюсов, что сей ругался только на
C++
1
i = a[i++];
и результат везде был одинаковым:
Bash
1
2
5
3
MrGluck
Модератор
Эксперт CЭксперт С++
7000 / 4171 / 595
Регистрация: 29.11.2010
Сообщений: 11,065
16.03.2015, 00:03     Написать функцию swap #64
Цитата Сообщение от Tulosba Посмотреть сообщение
Как с точки зрения предупреждений компилятора, так и с точки зрения результата выполнения.
Корректное поведение - частный случай UB

Я потому сразу и не увидел UB(?) что не заметил возможной неоднозначности. В отличи от кода
C++
1
i = i++ + ++i
здесь всё должно (в теории?) согласно правилу по моей ссылке выше преобразоваться в набор операций с последовательной записью в lhs.
Dennis Ritchie
546 / 138 / 29
Регистрация: 27.07.2014
Сообщений: 2,445
16.03.2015, 00:32     Написать функцию swap #65
Цитата Сообщение от MrGluck Посмотреть сообщение
здесь всё должно (в теории?) согласно правилу по моей ссылке выше преобразоваться в набор операций с последовательной записью в lhs.
Т. е. в C++11 так можно делать?
Tulosba
:)
Эксперт С++
4392 / 3235 / 297
Регистрация: 19.02.2013
Сообщений: 9,045
17.03.2015, 16:00     Написать функцию swap #66
Цитата Сообщение от Dennis Ritchie Посмотреть сообщение
Т. е. в C++11 так можно делать?
Однострочный вариант обмена через XOR возможен (не приводит к UB) в С++11.
http://stackoverflow.com/a/11989428/3240681
Ссылаются на тот же пункт из Стандарта, что и я.
Alex5
1040 / 703 / 102
Регистрация: 12.04.2010
Сообщений: 1,768
17.03.2015, 19:51     Написать функцию swap #67
Цитата Сообщение от Tulosba Посмотреть сообщение
C++
1
a[0] ^= a[1] ^= a[0] ^= a[1];
Эквивалентны ли следующие операторы?
C++
1
x = x ^ (y = y ^ (x = (x ^ y)));
C++
1
x ^= y ^= x ^= y;
Если так, то вот возможный результат.

C++
1
2
3
4
5
6
7
8
9
10
11
/* We evaluate left to right, doing both operands before the operation. */
x = 1; y = 2;
x = 1 ^ (y = y ^ (x = (x ^ y))); // left of outer 
x = 1 ^ (y = 2 ^ (x = (x ^ y))); // left of middle 
x = 1 ^ (y = 2 ^ (x = (1 ^ y))); // left of inner
x = 1 ^ (y = 2 ^ (x = (1 ^ 2))); // right of inner
x = 1 ^ (y = 2 ^ (x = 3)); // inner xor (right inner assign)
x = 1 ^ (y = 2 ^ 3); // inner assign (right middle xor)
x = 1 ^ (y = 1); // middle xor (right middle assign)
x = 1 ^ 1; // middle assign (right outer xor)
x = 0; // outer xor (right outer assign)
Tulosba
:)
Эксперт С++
4392 / 3235 / 297
Регистрация: 19.02.2013
Сообщений: 9,045
17.03.2015, 22:50     Написать функцию swap #68
Цитата Сообщение от Alex5 Посмотреть сообщение
Эквивалентны ли следующие операторы?
Эквивалентны.
Цитата Сообщение от Alex5 Посмотреть сообщение
Если так, то вот возможный результат.
Так это уже Java, а не C++.
И как сказано по приведенной тобой ссылке, в жабе в бинарном выражении всегда сначала вычисляется левый операнд.
В плюсах цепочка вычислений будет другая:
C++
1
2
3
4
5
6
7
8
x = 1; y = 2;
x = x ^ (y = y ^ (x = (x ^ y)));
x = x ^ (y = y ^ (x = (1 ^ 2)));
x = x ^ (y = y ^ (x = 3)); // здесь x стал равен трем.
x = x ^ (y = 2 ^ 3);
x = x ^ (y = 1); // здесь y стал равен единице.
x = 3 ^ 1;
x = 2; // здесь x стал равен двум.
В итоге значения обменялись.
MrGluck
Модератор
Эксперт CЭксперт С++
7000 / 4171 / 595
Регистрация: 29.11.2010
Сообщений: 11,065
17.03.2015, 23:24     Написать функцию swap #69
Цитата Сообщение от Alex5 Посмотреть сообщение
Эквивалентны ли следующие операторы?
Я же выше ссылку проводил про right-to-left associativity и запись результатов в lvalue.
Alex5
1040 / 703 / 102
Регистрация: 12.04.2010
Сообщений: 1,768
20.03.2015, 22:58     Написать функцию swap #70
Цитата Сообщение от Tulosba Посмотреть сообщение
В плюсах цепочка вычислений будет другая:
Tulosba, что же другие цепочки вычислений в C++ невозможны?

Добавлено через 8 минут
Цитата Сообщение от MrGluck Посмотреть сообщение
Я же выше ссылку проводил про right-to-left associativity и запись результатов в lvalue
MrGluck, там что-нибудь говорится про порядок вычисления операндов? В каком порядке будут вызваны функции?
C++
1
2
3
4
5
6
7
8
int& f(int n)
{
    std::cout << n << std::endl;
    static int x = 0;
    return x;
}
/* Что будет выведено на экран? */
f(1) = f(2) = f(3);
Dennis Ritchie
546 / 138 / 29
Регистрация: 27.07.2014
Сообщений: 2,445
21.03.2015, 04:29     Написать функцию swap #71
Цитата Сообщение от Alex5 Посмотреть сообщение
В каком порядке будут вызваны функции?
Так ведь это неправильный код, даже на UB не тянет (конкретно неправильный код).
Ведь оператор присваивания работать не будет.
castaway
Эксперт С++
4881 / 3017 / 370
Регистрация: 10.11.2010
Сообщений: 11,076
Записей в блоге: 10
Завершенные тесты: 1
21.03.2015, 10:13     Написать функцию swap #72
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
 
struct A {
    A & operator = ( A & ) { return *this; }
};
 
int & foo( int n ) {
    std::cout << n << ' ';
    static int x;
    return x;
}
 
A & bar( int n ) {
    std::cout << n << ' ';
    static A a;
    return a;
}
 
int main() {
    foo( 1 ) = foo( 2 ) = foo( 3 ); // 1, 2, 3
    std::cout << std::endl;
    bar( 1 ) = bar( 2 ) = bar( 3 ); // 3, 2, 1
    std::cout << std::endl;
}
Кто-нибудь знает почему так происходит?
Tulosba
:)
Эксперт С++
4392 / 3235 / 297
Регистрация: 19.02.2013
Сообщений: 9,045
22.03.2015, 15:43     Написать функцию swap #73
Цитата Сообщение от castaway Посмотреть сообщение
Кто-нибудь знает почему так происходит?
Любопытный момент, надо будет поизучать. А пока замечу, что с дефолтовой версией оператора присваивания порядок снова будет 1,2,3. Пруф.

Добавлено через 19 часов 53 минуты
Цитата Сообщение от Alex5 Посмотреть сообщение
что-нибудь говорится про порядок вычисления операндов?
Нашел например такую цитату:
There is no concept of left-to-right or right-to-left evaluation in C++, which is not to be confused with left-to-right and right-to-left associativity of operators: the expression f1() + f2() + f3() is parsed as (f1() + f2()) + f3() due to left-to-right associativity of operator+, but the function call to f3 may be evaluated first, last, or between f1() or f2() at run time.
Проводя параллели с оператором присваивания можно утверждать, что выражение:
C++
1
f(1) = f(2) = f(3);
будет интерпретировано парсером так же как
C++
1
f(1) = (f(2) = f(3));
Однако, это никоим образом не задает порядок вызова функций f(). Единственное что гарантируется на основании упомянутого ранее пункта 5.17/1, то что f(2) и f(3) должны быть вызваны до правого присваивания, а f(1) до левого присваивания.
Проверим:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
 
struct A {
    A(int i) : i(i) {}
    A & operator = ( const A & a )
    { 
        std::cout << "op=(" << i << "," << a.i << ") ";
        i = a.i;
        return *this; 
    }
    int i = 0;
};
 
A & bar( int n ) {
    std::cout << "bar(" << n << ") ";
    return *new A(n);
}
 
int main() {
    bar( 1 ) = bar( 2 ) = bar( 3 );
    std::cout << std::endl;
}
Результат:
Код
bar(3) bar(2) op=(2,3) bar(1) op=(1,3)
Т.о. на вопрос
Цитата Сообщение от castaway Посмотреть сообщение
Кто-нибудь знает почему так происходит?
скорее всего ответ такой: компилятор сам определяет (implementation defined) порядок вычисления аргументов, для которых выполняется правило unsequenced (1.9/13). Возможно, когда оператор присваивания для пользовательского класса тривиальный (например, когда он явно не задан или задан как = default), компилятору проще вычислить сразу все аргументы, чем чередовать их вычисление с присваиванием.

Хотя вот например clang в любом случае вычисляет все операнды до присваивания. Не важно задан пользовательский оператор= или нет.

Подводя итог можно сказать: не стоит полагаться на порядок вычисления аргументов в цепочке присваиваний. Он может быть совсем не очевиден с первого взгляда.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
27.03.2015, 23:03     Написать функцию swap
Еще ссылки по теме:

swap - C++
max, swap, min входят в &lt;iostream&gt; это стандартные функции?

swap - C++
Cи подчеркивает swap и говорит что он не определен! в данном случаи а это массив, а i и j индексы элементов swap(a,i,j)

Функция swap() - C++
А что выгоднее с точке зрения быстродействия - использование стандартной функции или &quot;ручной&quot; обмен через промежуточную...

Функция swap - C++
Доброго времени суток! Задался вопросом о реализации алгоритмов обмена двух переменных, но кроме этих ничего другого придумать не...

Объясните о swap() - C++
Есть такое задание: Описать процедуру Minmax(x,y) записывающую в переменную Х минимальное из значений Х и Y, а в переменную Y –...


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

Или воспользуйтесь поиском по форуму:
Alex5
1040 / 703 / 102
Регистрация: 12.04.2010
Сообщений: 1,768
27.03.2015, 23:03     Написать функцию swap #74
Цитата Сообщение от Tulosba Посмотреть сообщение
Однако, это никоим образом не задает порядок вызова функций f().
Верно. И поэтому результат вычисления
C++
1
2
3
x = 1;
y = 2;
x = x ^ (y = y ^ (x = (x ^ y)));
может быть x == 0 (см. сообщение 67) или x == 2 (см. сообщение 68).

Добавлено через 12 минут
C++
1
2
3
4
x = 
    x /* здесь может быть исходное значение  x  или результат выражения  (x = (x ^ y)  */ 
    ^ 
    (y = y ^ (x = (x ^ y)));
Yandex
Объявления
27.03.2015, 23:03     Написать функцию swap
Ответ Создать тему
Опции темы

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