Відповісти

Введіть повідомлення і натисніть Надіслати
Параметри

Назад

Огляд теми (нові повідомленні вгорі)

dimich
Сьогодні 12:23:38
dimich пише:

Просто і зрозуміло - це std::array та std::vector. А в ардуіно - що маємо, те маємо.

Доречі, Determining the Number of Elements of Arrays.

dimich
2025-08-05 17:58:29
jokeR пише:

sizeof(data)/sizeof(data[0]) часто зустрічаю.

data[0] - це те ж саме, що *(data + 0), тобто *(data), тобто *data

jokeR
2025-08-05 17:18:39

Бо не домовились що робити з пустими полями.
Взагалі без розуміння задумки автора - складно.

dimich
2025-08-05 16:44:21
filat18 пише:

А от що цікаво: код дає різну кількість отриманих груп для повідомлення 4/5 і для 4/5/

Так, тому що між розділювачем / та кінцем рядка пусто. atoi() для пустого рядка повертає 0.

dimich
2025-08-05 16:38:30
jokeR пише:

Але в такому записі легко допустити помилку, і компілятор її нормально пропустить.

Компілятор взагалі багато чого нормально пропускає. Для того і потрібна прокладка між стільцем та клавіатурою.

#define ARRAY_SIZE(x)  (sizeof(x)/sizeof(*(x)))

Або взагалі std::array без кофеіну:

template <typename T, size_t N>
struct array
{
    T data[N];
    constexpr size_t size() const noexcept { return N; }
};

А там можна і оператор [] перевантажити, і ітератори прикрутити.

filat18
2025-08-05 16:31:00

dimich, дякую за варіант коду - дуже цікаво! З затиранням даних зрозуміло. А от що цікаво: код дає різну кількість отриманих груп для повідомлення 4/5 і для 4/5/

jokeR
2025-08-05 16:19:33

sizeof(data)/sizeof(data[0]) часто зустрічаю. Теж не люблю.  А так.. Неочевидно трохи. Я здогадуюсь що в С масив і вказівник майже синоніми, і так теж можна. Але в такому записі легко допустити помилку, і компілятор її нормально пропустить. І фіг потім знайдете що не так wink

dimich
2025-08-05 16:07:24
jokeR пише:
sizeof(data)/sizeof(*data)

Не люблю.

Не смію вам перешкоджати щось не любити, маєте на це повне право wink

jokeR пише:

І щось мені здається що там помилка wink

Аргументуйте, в чому саме помилка.

jokeR пише:
#define DATA_SIZE 10
int data[DATA_SIZE];

Просто і зрозуміло.

Просто і зрозуміло - це std::array та std::vector. А в ардуіно - що маємо, те маємо.

dimich
2025-08-05 15:59:33
filat18 пише:

1 Якщо приходить повідомлення в вигляді цислового масива не визначеної довжини (від 1 до до 5, наприклад: 1/24/35 або 759/ або1/0/245/657/841 або...) треба занесті відповідні числа у масив rArr.

А якщо приходить більше ніж 5 чисел, решта має ігноруватись?
Чи потрібно передати 5 уже отриманих чисел, а решту розглядати як наступний рядок?
Чи весь такий рядок має ігноруватись до наступного?

filat18 пише:

2. після отриманя числовиго массина та розкладання його у rArr, потрібно викликати зовнішний void.

Спробую вгадати, що "викликати зовнішний void" - це передати масив у іншу функцію?

filat18 пише:

3. ящо у повідомленні є символи, що не належать числовому масиву, всі значення rArr потрібно перетворити у 0  і перейти до очикування наступного сповіщення.

Тобто ігнорувати цей рядок.
А якщо число 32768 чи більше, яке не влазить в AVR'івський int? Яке максимально допустиме значення, і що програма має робити зі значеннями, які його перевищують?

jokeR
2025-08-05 15:41:38
sizeof(data)/sizeof(*data)

Не люблю. І щось мені здається що там помилка wink

#define DATA_SIZE 10
int data[DATA_SIZE];

Просто і зрозуміло.

dimich
2025-08-05 15:35:57

UPD: запостив приклад до того як побачив ваші наступні повідомлення з описом задачі.

filat18 пише:

Ділянки масиву, що не отримали новид даних, повинні отримати 0.

Так обнуліть їх перед тим як передавати кудись той масив.

Якщо так вже кортить обнуляти весь масив перед отриманням нового рядка, то

memset(rArr, 0, sizeof(rArr));

Або, те ж саме:

for (auto &it : rArr) {
    it = 0;
}

Або, те ж саме:

for (auto *p = rArr; p < rArr + sizeof(rArr)/sizeof(*rArr);) {
    *p++ = 0;
}

Або, те ж саме:

for (size_t i = 0; i < sizeof(rArr)/sizeof(*rArr); i++) {
    rArr[i] = 0;
}

Можна навигадувати ще багато способів обнулити масив в C++.

jokeR
2025-08-05 15:26:15

розділення на масив має буте швидше, ниж займатися розділом після отримання...

Число операцій приблизно однакове. Розпихувати операції з розбором окремих полів має смисл, якщо одна велика операція в ваші обмеження не влізе. Ну, зробите це окремою функцією, будете викликати після кожного розділювача. Головне - не робити суперфункцій з суперциклами і глобальними суперзмінними. Робіть функції прості і зрозумілі.

dimich
2025-08-05 15:17:58
filat18 пише:

!? як що закоментувати позначений рядок - маю наступну відповідь, при однаковому сповіщєнні

Тому що rIndex=0 у вас не там де він повинен бути.

filat18 пише:

Але чи не простіше було б просто надрукувати уривок коду, що дійсно працює?

Та мабуть, простіше. Тільки розуміння того, що таке "дійсно працює", у нас з вами, мабуть, дуже різне.
Ось вам приклад. Написав якомога простіше, по-ардуінівськи. Ніякої обробки помилок у вхідних даних нема: що не влазить, те ігнорується, що atoi() повертає, те і записується. Обробка помилок на вході - то вже на ваc.

void setup()
{
    Serial.begin(115200);
}

size_t idx { 0 };
size_t str_idx { 0 } ;

int data[10];
char str[7];

void push_number()
{
    if (idx < sizeof(data)/sizeof(*data)) {
        str[str_idx] = '\0';
        data[idx++] = atoi(str);
    }
}

void loop()
{
    for (int c; (c = Serial.read()) != -1;)
    {
        switch (c) {
            case '/':
                push_number();
                str_idx = 0;
                break;

            case '\n':
            case '\r':
                if (idx == 0 && str_idx == 0) {
                    break;
                }
                push_number();

                for (size_t i = 0; i < idx; i++) {
                    Serial.print(F("data["));
                    Serial.print(i);
                    Serial.print(F("] = "));
                    Serial.println(data[i]);
                }

                idx = 0;
                str_idx = 0;
                break;

            default:
                if (str_idx < sizeof(str)/sizeof(*str) - 1) {
                    str[str_idx++] = c;
                }
                break;
        }
    }
}
filat18
2025-08-05 15:12:32

Мав меркування, що розділення на масив має буте швидше, ниж займатися розділом після отримання...
Но ті результати, що отримую та Ваші зауваження - підтвержують хибність моїх меркувань...

jokeR
2025-08-05 14:22:55

Ви намагаєтесь робити складно. Робіть просто.
1. просто приймайте символи в буфер. Коли приймете n - обробіть весь буфер зразу. Якщо буфер переповниться - ну, придумайте щось. Це помилка в даних.
2. обробка буфера. знаходите розділювачі полів, викусюєте частини з цифрами, перетворюєте в int. int кидаєте в масив.
Весь алгоритм.
Не треба придумувати байто@0bства на рівному місці. Не треба економити рядки коду. Не треба придумувати саморобні парсери. atoi нормально працює.

Підвал форуму