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

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

Войти
Регистрация
Восстановить пароль
 
Lyosha12
6 / 6 / 0
Регистрация: 02.04.2016
Сообщений: 152
#1

Не могу определить причину "магической" операции присвоения - C++

02.04.2016, 18:11. Просмотров 248. Ответов 9
Метки нет (Все метки)

Суть такая: написал посимвольный парсер для консоли. До недавнего времени работал как часы. Обращаюсь сюда по тому, что понять не могу причину такой магии:

При присвоении значения элементу массива [0][1], значение присваивается и [0][1], и [1][0]. Как? Я не вижу, чтобы я то увеличивал индекс строк и уменьшал индекс столбцов, то возвращал их обратно (я бы такую конструкцию заметил -_-)

Моё творение:
Кликните здесь для просмотра всего текста
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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#include <stdio.h>
#include <math.h>
#include <iostream>
using namespace std;
 
#define size 50
bool isNegative = false;
 
int invert_number(int current){
    int newCurrent = 0, F = current, number_count = 0;
    while(abs(F) > 0){
        F /= 10;
        number_count++;
    }
 
    int i = --number_count; int j = 0;
    while(abs(current) > 0){
        newCurrent += (current/pow(10,(double)i))*pow(10,(double)j++);
        current %= (int)pow(10,(double)i--);
    }
    if(isNegative == true){
        isNegative = false;
        return -newCurrent;
    }
    else
        return newCurrent;
}
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
void main(){setlocale (0,"");
    int MN1[size][1], MN2[size][1], countMN1, countMN2;
 
    for(int i = 0; i < size; i++){
        MN1[i][0] = 0; MN1[i][1] = 0; 
        MN2[i][0] = 0; MN2[i][1] = 0;
    }
    cout<< " Введите количество заданных точек первого множества (<" << size << "): ";
        cin >> countMN1; 
    cout<< " Введите количество заданных точек второго множества (<" << size << "): ";
        cin >> countMN2; 
 
                for(int i = 0; i < countMN1; i++) {
                if(i%3 == 0) 
                    cout<< endl << "\tТочка A" << i << ": (" << MN1[i][0] << "," << MN1[i][1] << "); ";
                else 
                    cout<< "\tТочка A" << i << ": (" << MN1[i][0] << "," << MN1[i][1] << "); "; 
            }
            cout<< endl;
 
    cout<< " Введите " << countMN1 << " точек первого множества в формате "x1,y2 x2,y2 ...":\n -> ";
 
 
    /* -------------------------- Парсер -------------------------- */
    int number_pos = 0, index_x = 0; char this_char = 0, x_or_y_next = 'X';
 
 
    while(index_x < countMN1){
        /* Получение символ слева направо */
        this_char = getchar();
        
        /* Если символ - минус */
        if(this_char == '-'){ 
            isNegative = true; continue;
        }
 
        /* Получение цифр из символов для координат X1 и Y1 точки A */
        if(this_char >= '0'  &&  this_char <= '9'  &&  x_or_y_next == 'X'){ MN1[index_x][0] += (-'0' + this_char) * pow(10,(double)number_pos); number_pos++; continue; }
        if(this_char >= '0'  &&  this_char <= '9'  &&  x_or_y_next == 'Y'){ 
            MN1[index_x][1] = MN1[index_x][1] + (-'0' + this_char) * pow(10,(double)number_pos); 
            number_pos++; 
            continue; }
 
        /* Обработка запятой после коордиаты X1 */
        if(this_char == ',' && x_or_y_next == 'X') {
            MN1[index_x][0] = invert_number(MN1[index_x][0]); 
            x_or_y_next = 'Y'; number_pos = 0; continue; }
 
        /* Обработка пробела и новой строки после координаты Y1 */
        if((this_char == ' ' || this_char == 10) && x_or_y_next == 'Y') {
            MN1[index_x][1] = invert_number(MN1[index_x][1]);
            number_pos = 0; index_x++; x_or_y_next = 'X'; 
            continue; }
 
        /* Обработка перевода строки \ подтверждения ввода */
        if(this_char == 10) continue;
 
    }
 
    cout<< endl;
 
            for(int i = 0; i < countMN1; i++) {
                if(i%3 == 0) 
                    cout<< endl << "\tТочка A" << i << ": (" << MN1[i][0] << "," << MN1[i][1] << "); ";
                else 
                    cout<< "\tТочка A" << i << ": (" << MN1[i][0] << "," << MN1[i][1] << "); "; 
            }
            cout<< endl;
 
    /* ---------------------------- Конец парсера -------------------------- */
    system("pause");
}


Проблема наблюдается в этом участке:
C++
1
2
3
        if(this_char >= '0'  &&  this_char <= '9'  &&  x_or_y_next == 'Y'){ 
            MN1[index_x][1] = MN1[index_x][1] + (-'0' + this_char) * pow(10,(double)number_pos); 
            number_pos++;
Могу даже видео прикрепить, если не верите .-.
Кликните здесь для просмотра всего текста
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
02.04.2016, 18:11
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Не могу определить причину "магической" операции присвоения (C++):

В зависимости от времени года "весна", "лето", "осень", "зима" определить погоду "тепло", "жарко", "холодно", "очень холодно" - C++
В зависимости от времени года &quot;весна&quot;, &quot;лето&quot;, &quot;осень&quot;, &quot;зима&quot; определить погоду &quot;тепло&quot;, &quot;жарко&quot;, &quot;холодно&quot;, &quot;очень холодно&quot;. Я так...

Создать класс комплексных чисел и ввести операции: "+", "-", "*", "/". - C++
пожалуйста-помогите написатьпрограмму!!! сижу на экзамене!!! вот само задание: создать класс комплексных чисел и ввести операции: &quot;+&quot;,...

Определить тип данных "Запись", имеющий поля "Фамилия", "Пол", "Зарплата" - C++
определить тип данных запись имеющий поля фамилия пол зарплата. определить массив из 10 записей. в программе ввести в массив данные и...

Error C2400: синтаксическая ошибка во встроенном коде на языке ассемблера в "код операции"; обнаружено "SHL" - C++
visual studio выдал такую ошибку error C2400: синтаксическая ошибка во встроенном коде на языке ассемблера в &quot;код операции&quot;; обнаружено...

Определить, какая из точек "В" или "С" расположены ближе к точке "А". - C++
На оси Ох расположены 3 точки А, В и С. Определить, какая из точек &quot;В&quot; или &quot;С&quot; расположены ближе к точке &quot;А&quot;. Предусмотреть вариант...

Найти причину ошибки "fatal error LNK1120: неразрешенных внешних элементов: 1" - C++
Добрый день, код по условию задачи выбивает ошибку &quot; fatal error LNK1120: неразрешенных внешних элементов: 1&quot; В чем проблема? ...

Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
yrceus
82 / 82 / 54
Регистрация: 25.08.2013
Сообщений: 326
02.04.2016, 18:57 #2
Потому что с массивами не разобрались Строки, столбцы, его лучше так не представлять. Массив это подряд идущие адреса памяти, каким бы он многомерным не был. То есть если есть двумерный массив, как говорят, из пяти строк и например семи столбцов arr[5][7], то это просто отрезок памяти подряд идущих пяти массивов по семь элементов. [0][1][2][3][4][5][6][0][1][2][3][4][5][6]... и т.д. еще три массива.
И если вы промахнетесь с индексом "в первой строке", например arr[0][9] то попадете на следующую "строку" arr[1][2].
А у вас же совсем интересно, фактический одномерный массив из 50 элементов называется двумерным массивом из 50 "строк" по одному элементу MN1[50][1]
Поэтому MN1[0][1] и MN1[1][0] это один и тот же элемент массива, одна ячейка памяти)))))

Добавлено через 5 минут
вот так выглядит ваш массив MN1[0][1][2][3][4][5][6]...[49]

MN1[1][2] это вот этот элемент MN1[0][1][2][*][4][5][6]...[49] и MN1[2][1] это тоже этот элемент MN1[0][1][2][*][4][5][6]...[49]
1
Lyosha12
6 / 6 / 0
Регистрация: 02.04.2016
Сообщений: 152
02.04.2016, 19:19  [ТС] #3
Цитата Сообщение от yrceus Посмотреть сообщение
Поэтому MN1[0][1] и MN1[1][0] это один и тот же элемент массива, одна ячейка памяти)))))
Почему? О_О
Если массивы нумеруются от нуля, то, да, у меня должен быть массив из 50 строк. Но я же и указываю, что в этих пятидесяти строках будут сидеть только 2 элемента, то есть таблица будет иметь размер "50 строк на 2 столбца". И я обращаюсь к i-ой строке нулевого или первого столбца. Разве нет?
0
yrceus
82 / 82 / 54
Регистрация: 25.08.2013
Сообщений: 326
02.04.2016, 19:23 #4
В каждой строке у вас сидит только один элемент
C++
1
int MN1[size][1], MN2[size][1],
1
Lyosha12
6 / 6 / 0
Регистрация: 02.04.2016
Сообщений: 152
02.04.2016, 19:24  [ТС] #5
Так, окей. Поставил количество столбцов 2 в определении. Теперь вернулся к изначальному варианту без магии. Но почему? Я не понимаю! Объясните, пожалуйста, подробнее: почему я не могу обратиться к элементу массива MN[0][1], не затронув MN[1][0]? Индексы же нумеруются с нуля! о_О
0
yrceus
82 / 82 / 54
Регистрация: 25.08.2013
Сообщений: 326
02.04.2016, 19:24 #6
Индексируются от нуля, а вот резервируются(определяются) от единицы
0
Lyosha12
6 / 6 / 0
Регистрация: 02.04.2016
Сообщений: 152
02.04.2016, 19:27  [ТС] #7
Значит, если я пишу, что хочу массив 50x2, то в определении я должен написать [51][2]?
0
yrceus
82 / 82 / 54
Регистрация: 25.08.2013
Сообщений: 326
02.04.2016, 19:30 #8
Лучший ответ Сообщение было отмечено автором темы, экспертом или модератором как ответ
Если создадите двумерный массив из пятидесяти массивов по два элемента
C++
1
int MN1[size][2], MN2[size][2],
то MN[0][1] и MN[1][0] будут разные элементы

Добавлено через 2 минуты
Если хотите 50х2 то и пишите 50х2, а если хотите 50 массивов по одному элементу пишите 50х1... и колдуете MN[0][1] == MN[1][0]
1
Lyosha12
6 / 6 / 0
Регистрация: 02.04.2016
Сообщений: 152
02.04.2016, 19:41  [ТС] #9
Хоть я это пока ещё не понимаю, но запомню, что указав количество строк 50, я получу строки с индексами 0...49. А указав количество столбцов 2, я получу 0...1. Или это неправильно и нужно обращаться к ним как 1...2?

Добавлено через 9 минут
Понятно. Просто отниму единицу от указанного размера массива и получу количество созданного, включая ноль. Спасибо. Шарики за ролики в какой-то момент точно заехали, в поисках "производительности" xD
0
yrceus
82 / 82 / 54
Регистрация: 25.08.2013
Сообщений: 326
02.04.2016, 19:45 #10
Лучший ответ Сообщение было отмечено автором темы, экспертом или модератором как ответ
Повторюсь, выражение "строки" сбивает с толку. Представляйте не строку, а массив, если есть 50 строк по 1 столбцу, это пятьдесят массивов по одному элементу, которые находятся непрерывно в памяти(подряд). И если вы обращаетесь например к первому и единственному элементу третьего массива, то это выглядит так arr[2][0], но в случае если вы случайно обратитесь ко второму элементу третьего массива arr[2][1](которого якобы нет) ошибки не будет, вы получите доступ уже к третьему массиву(строке) из одного элемента. Ошибка будет если вы уже выйдете из границ памяти этого двумерного массива массивов.
1
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
02.04.2016, 19:45
Привет! Вот еще темы с ответами:

Не понимаю причину ошибки "Statement missing ;" - C++
ИДЕ -- C++Builder 6 Суть кода: Перевод инфикской записи в постфиксную. Стек работает, проблема в самой функции перевода PolConv. Я...

Реализовать классы "Воин", "Пехотинец", "Винтовка", "Матрос", "Кортик" (наследование) - C++
Разработать программу с использованием наследования классов, реализующую классы: − воин; − пехотинец(винтовка); − матрос(кортик). ...

Определить, сколько в строке символов "*", ":", ";" - C++
Учусь языку,не могу разобраться со строками,а точнее с их описанием! Помогите пожалуйста на примере задачи:Дана строка.Определить сколько в...

Создать класс "Книга" с полями "название книги", "количество страниц", "год издания" - C++
Создать класс Книга поля: название книги,количество страниц,год издания методы: вычислить сколько лет книге и количество дней прошедших...


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

Или воспользуйтесь поиском по форуму:
Yandex
Объявления
02.04.2016, 19:45
Ответ Создать тему
Опции темы

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