Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.76/34: Рейтинг темы: голосов - 34, средняя оценка - 4.76
1 / 1 / 0
Регистрация: 19.10.2018
Сообщений: 27

Найти одинаковые числа в массиве

20.12.2018, 21:13. Показов 6817. Ответов 3
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Недавно я приблизился к теме указатели в С++. Не в радость, они дались мне очень трудно и я не до конца понял их принцип.

Я изучаю С++ по книге Герберта Шилдта "Руководство для начинающих". В книге к каждому модулю прилагаются всяческие задания, одно из этих заданий звучит так

Напишите программу, которая находит и отображает значения-дубликаты
в 10-элементном массиве целочисленных значений (если таковые в нем
присутствуют ).
Реализовать я решение этой задачи хочу с помощью указателей, для того чтобы опять же понять - как они работают.
Но в итоге у меня не получилось этого добиться.
В первых двух тестовых массивах когда я их ввожу ничего не происходит, в конце 0.
Кликните здесь для просмотра всего текста
9 8 4 5 3 1 11 17 7 4




0
Для продолжения нажмите любую клавишу . . .

В третьем массиве происходит вот такой вывод:
Кликните здесь для просмотра всего текста
1 3 1 3 5 6 7 8 1 3


121289281
121289281


2
Для продолжения нажмите любую клавишу . . .

В четвертом я получил такой результат:
Кликните здесь для просмотра всего текста
1 1 1 1 1 1 1 1 1 1


121289281
121289281
121289281
121289281
121289281
121289281
121289281
121289281
121289281


9
Для продолжения нажмите любую клавишу . . .


После этого я задался сразу несколькими вопросами:
  1. Почему ничего не работает?
  2. Почему в третьем и четвертом варианте выводятся непонятные значения?

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
#include <iostream>
#include <Windows.h>
using namespace std;
 
int main()
{
    SetConsoleOutputCP(1251);
    SetConsoleCP(1251);
 
    int arr[10];
    int *ptr = arr, *ptr2 = &arr[9];                //*ptr = arr - это значит что указатель ptr будет ссылаться на адрес первого элемента массива arr. *ptr2 в свою очередь будет ссылаться на последний элемент
    int count = 0;
 
    for (int i = 0; i < 10; i++) {
        cin >> arr[i];
    }
 
    cout << "\n\n";
 
    /*
    1 2 3 3 4 5 5 6 6 7 - тестовый массив первый.   9 8 4 5 3 1 11 17 7 4 - тестовый массив второй. 1 3 1 3 5 6 7 8 1 3 - тестовый массив третий:   1 1 1 1 1 1 1 1 1 1 - тестовый массив четвертый:
    Правильный вывод программы:                     Правильный вывод программы:                     Правильный вывод программы:                     Правильный вывод программы:
    1 2 3 3 4 5 5 6 6 7                             9 8 4 5 3 1 11 17 7 4                           1 3 1 3 5 6 7 8 1 3                             1 1 1 1 1 1 1 1 1 1
 
 
    3 | 3                                           4 | 4                                           1 | 1 | 1                                       Массив состоит из одинаковых чисел
    5 | 5                                                                                           3 | 3 | 3
    6 | 6
 
 
    Всего найдено 6 одинаковых числа             Всего найдено 2 одинаковых числа             Всего найдено 6 одинаковых чисел
    */
 
    while (ptr <= &arr[9])                              //этот цикл должен выполняться пока указатель ptr не присвоит адрес последнего числа массива
    {
        while (ptr2 > ptr)                              //этот цикл выполняется пока указатель ptr2 > указателя ptr
        {
            if (*ptr == *ptr2) {                        //если значение *ptr = *ptr2 , то
                cout << *ptr << ' | ' << *ptr2 << endl; //выводим значение *ptr и значение *ptr2
                count++;                                //счетчик увеличиваем на 1
            }
            ptr2--;                                     //ptr2 декрементируем на еденицу, чтобы он перешел к следующему числу 
                                                        //Например возьмем тестовый массив номер 2
                                                        //ptr в начале = 9, ptr2 = 4. Они не совпадают, значит адрес ptr2 уменьшается и получается 7. 9 (т.е. ptr) != 7 (т.е. ptr2), значит адрес уменьшается
        }
        ptr++;                                          //после того как мы проверили число 9, и получили нужные результаты, переходим к следующему числу, т.е. 8 и начинаем ту же самую процедуру что и с 9
    }
 
    cout << "\n\n";
 
    cout << count << endl;                              //выводим количество того, сколько раз наше условие дало истину (в будущем сколько найдено одинаковых чисел)
 
    system("pause");
    return 0;
}
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
20.12.2018, 21:13
Ответы с готовыми решениями:

Найти в массиве одинаковые числа и заменить их на ноль
найти из массива одинаковые числа и заменить их на ноль с++

Как узнать есть ли в массиве одинаковые числа и как найти эти числа ?
Всем привет ,можете помочь как узнать есть ли в массиве одинаковые числа и как найти эти числа . Например массив с элементами 1 4 4 0 2 ....

Одинаковые цифры числа в массиве
Требуется найти первую и последнюю цифры чисел в массиве, и если они равны - вывести. В массиве уже есть значения Допустим int mas =...

3
Мозгоправ
 Аватар для L0M
1745 / 1039 / 468
Регистрация: 01.10.2018
Сообщений: 2,138
Записей в блоге: 2
21.12.2018, 00:12
Лучший ответ Сообщение было отмечено savaznatnov как решение

Решение

1. Попробуйте заменить в вашем коде строки 34-47 на следующий фрагмент:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
    ptr = arr;
    while (ptr < &arr[9])                               //этот цикл должен выполняться пока указатель ptr не получит адрес предпоследнего элемента массива
    {
        ptr2 = ptr + 1;                                 // устанавливаем в ptr2 адрес следующего элемента, за элементом, на который указывает ptr
        while (ptr2 <= &arr[9])                         // пока указатель не вышел за пределы массива...
        {
            if (*ptr == *ptr2) {                        //если значение *ptr == *ptr2 , то
                cout << *ptr << " | " << *ptr2 << endl; //выводим значение *ptr и значение *ptr2
                count++;                                //счетчик увеличиваем на 1
            }
            ++ptr2;                                     // переводим указатель ptr2 на следующий элемент массива
        }
        ++ptr;                                          // переводим указатель ptr на следующий элемент массива
    }
Это не 100%-ное решение задачи, но всё же...

2. Непонятные знаки создаёт строка
C++
1
cout << *ptr << ' | ' << *ptr2 << endl;
Неожиданно, да?
В выводе 121289281 первая и последняя единица - это *ptr и*ptr2 соответственно, а число 2128928 (0x207c20) - это ASCII-коды пробела, символа вертикальной черты и ещё одного пробела, упакованные в int. Достаточно странное поведение компилятора (msvc), которое я обнаружил не так давно. Раньше, если в одинарных кавычках указывалось больше одного символа, компилятор ругался. А сейчас - вот так. И даже предупреждений не выдаёт. В стандарте что ли что-то поменяли

Добавлено через 11 минут
А вот так будет честно считать числа, которые имеют дубли:
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
#include <iostream>
#include <Windows.h>
using namespace std;
 
int main() {
    SetConsoleOutputCP(1251);
    SetConsoleCP(1251);
 
    int arr[10];
    bool dbbl[10];
    int *ptr = arr, *ptr2 = &arr[9];                //*ptr = arr - это значит что указатель ptr будет ссылаться на адрес первого элемента массива arr. *ptr2 в свою очередь будет ссылаться на последний элемент
    int count = 0;
 
    for (int i = 0; i < 10; i++) {
        cin >> arr[i];
        dbbl[i] = false;
    }
 
    cout << "\n\n";
 
    ptr = arr;
    while (ptr < &arr[9])                               //этот цикл должен выполняться пока указатель ptr не получит адрес предпоследнего элемента массива
    {
        ptr2 = ptr + 1;                                 // устанавливаем в ptr2 адрес следующего элемента, за элементом, на который указывает ptr
        while (ptr2 <= &arr[9])                         // пока указатель не вышел за пределы массива...
        {
            if (*ptr == *ptr2) {                        //если значение *ptr == *ptr2 , то
                cout << *ptr << " | " << *ptr2 << endl; //выводим значение *ptr и значение *ptr2
                *(dbbl + (ptr - arr)) = *(dbbl + (ptr2 - arr)) = true;
            }
            ++ptr2;                                     // переводим указатель ptr2 на следующий элемент массива
        }
        ++ptr;                                          // переводим указатель ptr на следующий элемент массива
    }
 
    for (int i = 0; i < 10; i++) {
        if (dbbl[i])
            ++count;                                    //счетчик увеличиваем на 1
    }
 
    cout << "\n\n";
 
    cout << count << endl;                              //выводим количество того, сколько раз наше условие дало истину (в будущем сколько найдено одинаковых чисел)
 
    system("pause");
    return 0;
}
1
1 / 1 / 0
Регистрация: 19.10.2018
Сообщений: 27
21.12.2018, 13:55  [ТС]
L0M, а в вашем варианте происходит почти то же самое что и в моем, НО! я заметил тут массив dbbl[10].
Вопроси:
  1. Я так понял - массив dbbl[10] отвечает за список чисел которые совпали?
  2. Что происходит в строке 29?
C++
1
*(dbbl + (ptr - arr)) = *(dbbl + (ptr2 - arr)) = true;
По моим предположениям это выражение означает вот что (например дан массив чисел 9 8 4 5 3 1 11 17 7 4):

типо программа
Условие совпало. 4 = 4
С помощью оператора '*' мы делаем так, чтобы в этом выражении на выходе были значения, а не адреса
Далее массив dbbl складывается с значением ptr - arr. В нашем случае dbbl + ( 4 - arr )
А потом этому значению присваивается истина.
  1. Как понять 4 вычесть массив arr? Берётся адрес числа 4 и из него вычитается адрес массива arr?
  2. Как понять dbbl + (4 - arr)? К адресу массива dbbl прибавляется адрес полученного выражения ( 4 - arr )?

Просто я ни разу из массивов не вычитал и не складывал каких то чисел, как написано у вас. Да что не вычитал, я даже не знал о том что такая запись вообще возможна!
Может я туплю или о таком в книге я все таки не читал?)

Кстати ваш первый вариант решения мне помог, он аналогичен по функционалу второго варианта, благодарю, я оставлю так, пока не пойму в чем суть 2 варианта

Добавлено через 9 минут
L0M, совсем забыл вас поблагодарить за развернутый и доступный ответ на счёт одинарных кавычек. Было конечно интересно и в то же время удивительно почему так происходит, странно еще было то - что как вы сказали компилятор то ошибок никаких не выдает!
0
Мозгоправ
 Аватар для L0M
1745 / 1039 / 468
Регистрация: 01.10.2018
Сообщений: 2,138
Записей в блоге: 2
21.12.2018, 14:36
Лучший ответ Сообщение было отмечено savaznatnov как решение

Решение

В массиве dbbl отмечаются (true) те числа, которые совпали. А в строке 29 как раз и происходит установка таких пометок.

В начале ptr устанавливается на начало массива arr. (ptr - arr) - это смещение между текущим положением ptr и началом массива, выраженное в количестве элементов массива. Т.е. ptr == &arr[ptr - arr]. Соответственно (dbbl + (ptr - arr)) == &dbbl[ptr - arr], т.е. это адрес элемента массива dbbl, который отстоит от начала массива на (ptr - arr) элементов. А выражение *(dbbl + (ptr - arr)) - это значение элемента массива по этому адресу.

Если переписать строки 24-34 в форме обращения к элементам массива с помощью индексов, то получится следующее:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
    int i = 0, j;
    while (i < 9)
    {
        j = i + 1;
        while (j < 10)
        {
            if (arr[i] == arr[j]) {
                cout << arr[i] << " | " << arr[j] << endl;
                dbbl[i] = dbbl[j] = true;
            }
            ++j;
        }
        ++i;
    }
Цитата Сообщение от savaznatnov Посмотреть сообщение
Как понять dbbl + (4 - arr)?
ptr - это адрес, а не значение. А число 4 (в вашем примере) лежит по этому адресу.

Цитата Сообщение от savaznatnov Посмотреть сообщение
Просто я ни разу из массивов не вычитал и не складывал каких то чисел
Это называется адресная арифметика. Посмотрите в книгах. Там оно есть.

Цитата Сообщение от savaznatnov Посмотреть сообщение
первый вариант решения мне помог, он аналогичен по функционалу второго варианта
Не совсем. Попробуйте на десяти одинаковых числах.

Цитата Сообщение от savaznatnov Посмотреть сообщение
совсем забыл вас поблагодарить
Для спасибы есть специальные кнопочки
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
21.12.2018, 14:36
Помогаю со студенческими работами здесь

Проверить есть ли в массиве одинаковые числа
Как можно проверить есть ли в массиве числа с одинаковым значением? числа вводяться с клавиатуры.

Узнать, все ли числа в массиве одинаковые
Обработать массив из целых чисел А (не больше 100 эл-тов), вначале предусматривая заполнение массива числами. Узнать, все ли числа в...

Выяснить есть ли одинаковые числа в массиве
Выясните, есть ли одинаковые числа в массиве или же массив содержит только разные. Сосчитайте количество различных чисел в массиве.

Определить, есть ли в массиве одинаковые числа.
Дан массив из 10 вещественных чисел. Определить, есть ли в массиве одинаковые числа.

Выяснить есть ли одинаковые числа в двумерном массиве
Выясните есть ли одинаковые числа в двумерном массиве или же массив содержит только разные. Заранее спасибо.


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

Или воспользуйтесь поиском по форуму:
4
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
Установка Qt-версии Lazarus IDE в Debian Trixie Xfce
volvo 10.02.2026
В общем, достали меня глюки IDE Лазаруса, собранной с использованием набора виджетов Gtk2 (конкретно: если набирать текст в редакторе и вызвать подсказку через Ctrl+Space, то после закрытия окошка. . .
SDL3 для Web (WebAssembly): Работа со звуком через SDL3_mixer
8Observer8 08.02.2026
Содержание блога Пошагово создадим проект для загрузки звукового файла и воспроизведения звука с помощью библиотеки SDL3_mixer. Звук будет воспроизводиться по клику мышки по холсту на Desktop и по. . .
SDL3 для Web (WebAssembly): Основы отладки веб-приложений на SDL3 по USB и Wi-Fi, запущенных в браузере мобильных устройств
8Observer8 07.02.2026
Содержание блога Браузер Chrome имеет средства для отладки мобильных веб-приложений по USB. В этой пошаговой инструкции ограничимся работой с консолью. Вывод в консоль - это часть процесса. . .
SDL3 для Web (WebAssembly): Обработчик клика мыши в браузере ПК и касания экрана в браузере на мобильном устройстве
8Observer8 02.02.2026
Содержание блога Для начала пошагово создадим рабочий пример для подготовки к экспериментам в браузере ПК и в браузере мобильного устройства. Потом напишем обработчик клика мыши и обработчик. . .
Философия технологии
iceja 01.02.2026
На мой взгляд у человека в технических проектах остается роль генерального директора. Все остальное нейронки делают уже лучше человека. Они не могут нести предпринимательские риски, не могут. . .
SDL3 для Web (WebAssembly): Вывод текста со шрифтом TTF с помощью SDL3_ttf
8Observer8 01.02.2026
Содержание блога В этой пошаговой инструкции создадим с нуля веб-приложение, которое выводит текст в окне браузера. Запустим на Android на локальном сервере. Загрузим Release на бесплатный. . .
SDL3 для Web (WebAssembly): Сборка C/C++ проекта из консоли
8Observer8 30.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru