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

Странное поведение - C++

Восстановить пароль Регистрация
 
Hagrael
БТР - мой друг
 Аватар для Hagrael
331 / 273 / 2
Регистрация: 07.01.2010
Сообщений: 1,932
10.06.2012, 11:35     Странное поведение #1
Здравствуйте еще раз Теперь возникла другая непонятка. Есть класс StringParser, объекты которого умеют разбивать строку на подстроки, разделенные запятыми. Всякий раз, когда вы вызываете метод .getNextPart(), он возвращает вам следующую подстроку. Описывается класс StringParser в файле StringParser.h:
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
25
26
27
28
29
30
31
32
33
34
35
36
37
38
using namespace std;
 
class StringParser {
    private:
        char *str, *seperators;
        int position;
        bool isSeperator(int seperatorPosition) {
            for (int i = 0; seperators[i] != '\0'; i++) {
                if (str[seperatorPosition] == seperators[i])
                    return true;
            }
 
            return false;
        }
    public:
        StringParser (char* newStr) {
            str = newStr;
            seperators = new char[1];
            seperators[0] = ',';
            position = 0;
        }
        char* getNextPart () {
            int partLength = 0;
            while (!isSeperator(position+partLength) and str[position+partLength] != '\0') {
                partLength++;
            }
 
            char* part = new char[partLength+1];
            for (int i = 0; i < partLength; i++) {
                part[i] = str[position+i];
            }
            part[partLength] = '\0';
 
            position += partLength+1;
 
            return part;
        }
};
Сам класс работает, вроде, исправно, однако есть одна странность.
Когда я пишу в главном файле программы так:
C++
1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
#include "StringParser.h"
using namespace std;
 
int main () {
    StringParser parser("1, 2, 3");
    cout << parser.getNextPart();
    cout << parser.getNextPart();
    cout << parser.getNextPart();
 
    return 0;
}
то все работает, как надо, на экран выводится "1 2 3" (пробелы parser не пропускает, т. к. они не являются разделителями, разделителем является только запятая).
Но когда я пишу так:
C++
1
2
3
4
5
6
7
8
9
10
#include <iostream>
#include "StringParser.h"
using namespace std;
 
int main () {
    StringParser parser("1, 2, 3");
    cout << parser.getNextPart() << parser.getNextPart() << parser.getNextPart();
 
    return 0;
}
то на экран выводится " 3 21", т. е. все выводится в обратном порядке. Почему так?
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
10.06.2012, 11:35     Странное поведение
Посмотрите здесь:

C++ Странное поведение транслятора
C++ Странное поведение компилятора
C++ Странное поведение getline
Странное поведение wstring C++
странное поведение указателя C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Somebody
2770 / 1583 / 141
Регистрация: 03.12.2007
Сообщений: 4,139
Завершенные тесты: 1
10.06.2012, 11:40     Странное поведение #2
C++
1
cout << parser.getNextPart() << parser.getNextPart() << parser.getNextPart();
это
C++
1
operator<<(operator<<(operator<<(cout, parser.getNextPart()), parser.getNextPart()), parser.getNextPart());
А порядок вычисления аргументов функций может быть любой, не обязательно слева направо. Раздели на три отдельных выражения.
Hagrael
БТР - мой друг
 Аватар для Hagrael
331 / 273 / 2
Регистрация: 07.01.2010
Сообщений: 1,932
11.06.2012, 12:12  [ТС]     Странное поведение #3
По-моему, самый первый вызов должен быть в самой глубине, т. е. в подчеркнутом месте:
operator<<(operator<<(operator<<(cout, parser.getNextPart()), parser.getNextPart()), parser.getNextPart());
Вначале произойдет вызов метода .getNextPart() в этом месте, потом то, что он вернет отправится в функцию operator<<, а после то, что вернет функция operator<<, пойдет в "более внешнюю" функцию operator<<.
Somebody
2770 / 1583 / 141
Регистрация: 03.12.2007
Сообщений: 4,139
Завершенные тесты: 1
11.06.2012, 15:58     Странное поведение #4
http://www.open-std.org/jtc1/sc22/op...html#expr.call
8 The order of evaluation of arguments is unspecified. All side effects
of argument expression evaluations take effect before the function is
entered. The order of evaluation of the postfix expression and the
argument expression list is unspecified.
И, так как параметры в стек обычно заталкиваются справа налево, вполне предсказуемо, что компилятор выбрал такой порядок.
Hagrael
БТР - мой друг
 Аватар для Hagrael
331 / 273 / 2
Регистрация: 07.01.2010
Сообщений: 1,932
12.06.2012, 11:45  [ТС]     Странное поведение #5
Не очень понял
Т. е. вначале в память записываются 3 значения, которые возвращает функция .getNextPart() при 3-х вызовах, а потом в самый внешний вызов подставляется 1-е значение, в более внутренний - 2-е и в самый глубокий - 3-е?

Если так, то почему тогда такой код выводит на экран "12"?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
using namespace std;
 
int A ();
int B ();
 
int main () {
    cout << A() << B();
 
    return 0;
}
 
int A () {
    return 1;
}
 
int B () {
    return 2;
}
soon
 Аватар для soon
2536 / 1301 / 81
Регистрация: 09.05.2011
Сообщений: 3,086
Записей в блоге: 1
12.06.2012, 12:04     Странное поведение #6
Hagrael, вы неправильно поняли. Это более наглядно
C++
1
2
3
4
5
6
7
8
#include <iostream>
 
int main()
{
    int a = 5;
    std::cout << a << ' ' << ++a << std::endl;
    return 0;
}
Yandex
Объявления
12.06.2012, 12:04     Странное поведение
Ответ Создать тему
Опции темы

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