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

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

Восстановить пароль Регистрация
 
 
Рейтинг: Рейтинг темы: голосов - 23, средняя оценка - 4.96
VitekSR
0 / 1 / 0
Регистрация: 20.10.2013
Сообщений: 233
26.03.2014, 14:26     Написать функцию swap #1
был вот такой код:
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
Посмотрите здесь:

C++ Написать функцию, которая могла бы передать значение в другую функцию
C++ Напишите функцию Swap(a, b), аргументами которой могут быть числа любого типа
Создать функцию SWAP, преобразующую заглавные буквы передаваемой ей строки в строчные и наоборот C++
C++ Написать функцию, которая вычисляет объем и площадь поверхности параллелепипеда, описать функцию IsSquare(K)
не могу разобраться как написать функцию сортировки и исправить функцию добавления в стек C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
hoggy
5226 / 2117 / 403
Регистрация: 15.11.2014
Сообщений: 4,801
Завершенные тесты: 1
15.03.2015, 15:02     Написать функцию swap #61
Цитата Сообщение от MrGluck Посмотреть сообщение
А они, как известно, сохраняют результат вычисления в левом операнде.
ещё известно, что многократное изменение одной и тоже переменной
на протяжении одной точки следования есть undefined behavior.
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
castaway
Эксперт С++
4844 / 2983 / 367
Регистрация: 10.11.2010
Сообщений: 11,016
Записей в блоге: 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
:)
Эксперт С++
4378 / 3221 / 297
Регистрация: 19.02.2013
Сообщений: 9,044
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
Ворчун
Эксперт С++
 Аватар для MrGluck
4920 / 2663 / 243
Регистрация: 29.11.2010
Сообщений: 7,416
16.03.2015, 00:03     Написать функцию swap #64
Цитата Сообщение от Tulosba Посмотреть сообщение
Как с точки зрения предупреждений компилятора, так и с точки зрения результата выполнения.
Корректное поведение - частный случай UB

Я потому сразу и не увидел UB(?) что не заметил возможной неоднозначности. В отличи от кода
C++
1
i = i++ + ++i
здесь всё должно (в теории?) согласно правилу по моей ссылке выше преобразоваться в набор операций с последовательной записью в lhs.
Dennis Ritchie
 Аватар для Dennis Ritchie
546 / 138 / 29
Регистрация: 27.07.2014
Сообщений: 2,444
16.03.2015, 00:32     Написать функцию swap #65
Цитата Сообщение от MrGluck Посмотреть сообщение
здесь всё должно (в теории?) согласно правилу по моей ссылке выше преобразоваться в набор операций с последовательной записью в lhs.
Т. е. в C++11 так можно делать?
Tulosba
:)
Эксперт С++
4378 / 3221 / 297
Регистрация: 19.02.2013
Сообщений: 9,044
17.03.2015, 16:00     Написать функцию swap #66
Цитата Сообщение от Dennis Ritchie Посмотреть сообщение
Т. е. в C++11 так можно делать?
Однострочный вариант обмена через XOR возможен (не приводит к UB) в С++11.
http://stackoverflow.com/a/11989428/3240681
Ссылаются на тот же пункт из Стандарта, что и я.
Alex5
883 / 618 / 81
Регистрация: 12.04.2010
Сообщений: 1,552
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
:)
Эксперт С++
4378 / 3221 / 297
Регистрация: 19.02.2013
Сообщений: 9,044
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
Ворчун
Эксперт С++
 Аватар для MrGluck
4920 / 2663 / 243
Регистрация: 29.11.2010
Сообщений: 7,416
17.03.2015, 23:24     Написать функцию swap #69
Цитата Сообщение от Alex5 Посмотреть сообщение
Эквивалентны ли следующие операторы?
Я же выше ссылку проводил про right-to-left associativity и запись результатов в lvalue.
Alex5
883 / 618 / 81
Регистрация: 12.04.2010
Сообщений: 1,552
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
 Аватар для Dennis Ritchie
546 / 138 / 29
Регистрация: 27.07.2014
Сообщений: 2,444
21.03.2015, 04:29     Написать функцию swap #71
Цитата Сообщение от Alex5 Посмотреть сообщение
В каком порядке будут вызваны функции?
Так ведь это неправильный код, даже на UB не тянет (конкретно неправильный код).
Ведь оператор присваивания работать не будет.
castaway
Эксперт С++
4844 / 2983 / 367
Регистрация: 10.11.2010
Сообщений: 11,016
Записей в блоге: 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
:)
Эксперт С++
4378 / 3221 / 297
Регистрация: 19.02.2013
Сообщений: 9,044
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(A,B), меняющую местами максимальные элементы матриц А и В. C++
C++ рекурсия.написать функцию,принимающую указ. на другую функцию, осуществл. некую операцию с переданным х
C++ Чем можно заменить функцию swap?

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

Или воспользуйтесь поиском по форуму:
Alex5
883 / 618 / 81
Регистрация: 12.04.2010
Сообщений: 1,552
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
Ответ Создать тему
Опции темы

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