Рубрики
Без рубрики

Современный вызов C++ на мобильных устройствах – Первая проблема

Привет! Меня зовут Ксавье Жувено, и это первая часть длинной серии статей о современных вызовах C++. I… С тегами android, cpp, java, themoderncppchalleng.

Привет! Я Ксавье Жувено, и вот первая часть длинной серии о Современный вызов C++ .В этой статье я собираюсь объяснить, как я решил первую проблему на C++ и как я интегрировал решение в проект Android.

Цель этой первой задачи проста. Мы должны вычислить сумму всех натуральных чисел, делящихся либо на 3, либо на 5, с точностью до некоторого предела, заданного пользователем, и мы должны распечатать ее. Решение будет вычислено на C++, а интерфейс для получения пользовательского ввода и отображения результата будет обрабатываться с помощью Android Studio Framework.

Решение на C++

Как вы, возможно, видели в моем предыдущем сообщении в блоге об установке Android Studio с C++ . Мы можем использовать C ++ 17 в Android Studio, так что это то, что я собираюсь использовать. 😉

Когда я начинаю свой путь в разработке Android, я интегрировал свое решение непосредственно в файл native-lib.cpp создается по умолчанию Android Studio. А вот как выглядит эта функция:

[[nodiscard]] constexpr auto sumOf3and5MultipleUpTo(const unsigned int limit)
{
    size_t sum = 0;
    for(auto number = limit; number >= 3; --number)
    {
        if(number % 3 == 0 || number % 5 == 0)
        {
            sum += number;
        }
    }
    return sum;
}

Давайте подробнее рассмотрим эту функцию, чтобы убедиться, что мы все понимаем, как она работает и почему это так. Во-первых, давайте посмотрим на прототип и на то, что он дает нам в качестве информации:

[[nodiscard]] constexpr auto sumOf3and5MultipleUpTo(const unsigned int limit)

Эта функция constexpr , поскольку вычисление может быть выполнено во время компиляции, если мы захотим. Возвращаемый тип автоматически вычитается с помощью ключевого слова auto . Это также как атрибут [[nodiscard]] что означает, что результат этой функции должен быть использован программой. И, наконец, у нас есть один входной сигнал, который является положительным натуральным числом, поскольку он имеет тип unsigned int .

Одним из ограничений, определяемых этой функцией, является то, что ввод никогда не должен заканчиваться 4294967295 который является пределом типа unsigned int . .Это ограничение можно преодолеть, используя size_t

После прототипа эта функция объявляет и инициализирует переменную для результата вычисления:

size_t sum = 0;

Это переменная size_t , чтобы быть уверенным, что мы можем сохранить максимально возможное число, вплоть до 18446744073709551615 .Если мы хотели иметь возможность получать еще большие числа, нам пришлось бы использовать реализацию biginteger.

Затем у нас есть вычисление результата:

for(auto number = limit; number >= 3; --number)
{
    if(number % 3 == 0 || number % 5 == 0)
    {
        sum += number;
    }
}

Цикл идет вниз от предела, заданного пользователем, до 3 .Нет необходимости проверять, чтобы 0 , потому что ни 1 ни 2 или делится на 3 или 5 , и даже если 0 делится на них, добавляя 0 к сумме не изменит результат.

С помощью number % 3 мы проверяем , делится ли число на 3 , и с помощью number % 5 мы проверяем , делится ли число на 5 . И если одна из этих проверок верна, мы добавляем номер к текущему компьютеру сумма .

И, наконец, мы возвращаем результат:

return sum;

Итак, вот мое решение этой проблемы, давайте посмотрим, как интерфейс выполнен в Android Studio.

Пользовательский интерфейс в Android Studio

Поскольку на данный момент это единственная проблема, которую решает это приложение, у нас есть только один экран в вашем приложении, поэтому я указал элементы пользовательского интерфейса непосредственно в файле activity_main.xml создается по умолчанию Android Studio.

Отказ от ответственности: поскольку я только начинаю свое путешествие в Android Studio и мобильную разработку, то, что я узнаю здесь и в будущем посте, может быть для вас тривиальным. Возможно, даже есть несколько лучших способов, чем мое личное решение, достичь того же самого. Если у вас есть какой-либо из этих способов на примете, пожалуйста, сообщите мне в комментариях, чтобы я мог улучшить себя. Заранее благодарю вас 🙂

Чтобы создать наш пользовательский интерфейс, нам понадобятся два вида элементов: Текстовое представление и EditText .The EditText позволит пользователю предоставить нам входные данные, а TextView позволит нам отобразить результат пользователю. Вот как выглядит xml этих элементов:




Давайте копнем немного глубже в этих элементах.

Во-первых, Редактировать текст .У него есть атрибут android: id , который указывает идентификатор, который будет полезен, когда нам нужно будет получить входные данные, введенные пользователем в Редактировать текст .Атрибут android:inputType имеет значение number , что заставляет пользователя вводить числа в EditText .И, наконец, последний атрибут, о котором я хочу с вами поговорить, атрибут android:hint , который отображает текст для отправки инструкции или сообщения пользователю, когда EditText пуст

Теперь давайте посмотрим на TextEdit .Как и EditText , он имеет атрибут android:id , который указывает идентификатор, который будет полезен, когда потребуется отобразить результат, найденный алгоритмом cpp. И у нас также есть атрибут android:text , который представляет собой текст TextView , отображаемый пользователю. Это атрибут, который мы изменим с помощью результата вычисления, выполненного на C++. На данный момент он отображает только “Результат:”.

Мы не будем рассматривать другие элементы, поскольку они не имеют отношения к цели этого сообщения в блоге, поскольку они в основном определяют размер и положение элементов.

Использование собственного кода C++

Чтобы связать и использовать функцию C++, которую мы создали ранее, нам нужно сделать несколько вещей. Во-первых, нам нужно объявить в файле C++ то, что мы хотим сделать доступным для остальной части программы. Это выглядит как следующий код:

extern "C" JNIEXPORT jstring JNICALL
Java_com_example_themoderncppchallenge_MainActivity_Sum3And5Multiples(
        JNIEnv* env,
        jobject /* this */, const jint i) {
    auto sum = sumOf3and5MultipleUpTo(i);
    return env->NewStringUTF(std::to_string(sum).c_str());
}

Этот пример кода определяет функцию Сумма 3 и 5 кратных , которая будет использоваться в Java. Эта функция принимает параметр joint in, который будет вводиться пользователем, передает параметр функции out C++ и получает вычисленный результат, прежде чем возвращать его в виде строки. Вот как в коде Java выглядит прототип этой функции:

public native String Sum3And5Multiples(int i);

Теперь давайте посмотрим, как эта функция используется для отображения результата в TextView после получения ввода пользователя с помощью |/Edit Text .Поскольку наше приложение пока решает только одну проблему, этот код написан непосредственно в методе MainActivity::onCreate внутри MainActivity.java файл. Вот как это выглядит:

EditText et = findViewById(R.id.plain_text_input);
et.addTextChangedListener(new TextWatcher() {
    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {

    }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {
        int limit = 0;
        if(count != 0)
        {
            limit = Integer.parseInt(s.toString());
        }
        TextView tv = findViewById(R.id.result);
        tv.setText("Result: " + Sum3And5Multiples(limit));
    }

    @Override
    public void afterTextChanged(Editable s) {

    }
});

В этом коде мы получаем EditText , используя его идентификатор, и прикрепляем прослушиватель к его тексту.

EditText et = findViewById(R.id.plain_text_input);
et.addTextChangedListener(new TextWatcher() {

Затем мы указываем, что мы хотим сделать, когда текст внутри EditText изменение, когда пользователь изменяет входные данные. Мы начинаем с проверки, есть ли какие-либо входные данные для получения, если нет, мы вычисляем сумму для 0 в качестве входных данных.

int limit = 0;
if(count != 0)
{
    limit = Integer.parseInt(s.toString());
}

Как только у нас есть ввод пользователя, мы получаем TextView .И, наконец, мы вызываем метод C++ и выводим его результат.

TextView tv = findViewById(R.id.result);
tv.setText("Result: " + Sum3And5Multiples(limit));

И вуаля, мы связали все в программу, которая решает первую проблему Современный вызов C++ .Лично , я добавил некоторые TextView для предоставления дополнительной информации пользователю. Вот как это выглядит:

Вывод

Эта первая проблема и первая реальная программа в Android Studio стали для меня отличным опытом обучения. Я действительно много узнаю об Android Studio и о том, как работают различные части программы на родном C++.

Я знаю, что мне есть чему поучиться, и я рад этому так же сильно, как мне понравилось изучать то, что я изложил в этой статье 🙂 Пожалуйста, скажите мне, есть ли у вас какие-либо предложения или комментарии по поводу некоторых элементов или по поводу предложенного мной решения.

Спасибо вам всем за то, что прочитали эту статью, И до моей следующей статьи желаю вам отличного дня 😉

Интересные ссылки

Оригинал: “https://dev.to/10xlearner/the-modern-c-challenge-on-mobile-the-first-problem-3no9”