Я не задавал 1000 вопросов , вопросов было всего 3-5 , . у меня была задача и я хотел довести ее до конца, чтобы в следующий раз не спотыкаться, тем более , что она сама по себе затронула аспекты с которыми я не работал и в них все равно надо разбираться даже и без сортировки. Это не методом тыка это последовательное решение проблем…методом тыка это когда не получилось так перескочил на другое - авось по другому получится… …
Да я неспорю сортировка по индексам в массиве без самих строк мне не пришла сразу в голову…странно конечно если учесть что связи между таблицами как раз на них и построенны… Тут большое спасибо за тычек… я понял и так и делаю… Но при этом бросить незавершенный вопрос , ну как то не в моих правилах… Да возможно для скорости исполнения проекта это очень плохо , но с другой стороны мой проект - для себя ,соответственно я могу позволить себе растянуть время его завершения в угоду новым знаниям… как решил задачу сразу взялся за ту что предложили… незнаю имхо все последовательно
по поводу стыдно… да стыдно поэтому стараюсь как можно меньше спрашивать . если посмотрите я задал всего 6 вопросов (тем) 2 из которых относились к методам отладки и оптимизации а не к программированию.
romansochi, вот без обид, вы нытика напоминаете, второй день вам говорят выкинуть нахрен ваш код, начать все с нуля, по уму, а вы че то там пытаетесь доказать что вы молодец.
Решение в лоб. Так себе, есть где чо пооптимизировать. Да и спрасони мог где-нить накосячить, сам проверяй. К строкам можно обращаться так же, по порядковому номеру, а от него берется уже правильный индекс позиции строки в ROM.
Спойлер
/*
Name: ROM_SORT.ino
Created: 28.01.2023 21:34:13
Author: DtS
*/
// Допущения:
// под все строки выделяется одинаковое кол-во байт, например, 20
// вместе с завершающим нулём. Строки идут подряд, друг за другом.
//
// Ну, т.е сама строка может быть и 5 символов, но в EEPROM всёрно
// занимать будет 20, можно переделать при желании, просканировав
// EEPROM на завершающие нули и присвоив реальные адреса начала
// строк массиву, но, хранить тогда придёцца не индексы (1 байт),
// а адреса. Кстати, этот массив можно тоже хранить в EEPROM,
// единожды отсортировавши. Да много чо можно
#include <Arduino.h>
#include <alloca.h>
#include <eeprom.h>
constexpr uint8_t NUM_STRINGS = 30; // максимальное кол-во строк для сортировки
constexpr uint8_t MAX_STRING_SIZE = 20; // максимальный размер строки, с терминатором #0 в конце
constexpr uint16_t START_ADDR = 0x0010; // адрес в EEPROM, начиная с которого лежат строки, подставить свой
uint8_t StringIdx[NUM_STRINGS]; // массив индексов сортируемых строк. Первоначально содержит 0,1,2 ... NUM_STRINGS-1
// "Заполняем" массив строками. Вернее пишем в него начальные индексы
//
void InitArray(void) {
for (uint8_t i = 0; i < NUM_STRINGS; ++i)
StringIdx[i] = i;
}
//
// Читает в ОЗУ строку из EEPROM по НОМЕРУ
// т.е сначала по номеру берется индекс строки
// потом по нему вычисляется адрес
//
char* ReadStringNum(char* ADestAddr, const uint8_t AStrNum) {
uint8_t idx = StringIdx[AStrNum]; // получаем индекс строки с номером AStrNum
uint8_t* fromAddr = (uint8_t *)(GetStringAddr(idx)); // Преобразуем его в адрес, где она лежит
for (uint8_t i = 0; i < MAX_STRING_SIZE; ++i) {
char ch = eeprom_read_byte(fromAddr++);
ADestAddr[i] = ch;
if (ch == 0x00) break; // копируем из ROM в RAM до символа 0x00, включая его
}
return ADestAddr;
}
inline uint16_t GetStringAddr(const uint8_t AStringIndex) {
return START_ADDR + AStringIndex * MAX_STRING_SIZE;
}
void Sort() {
char* firstString = alloca(MAX_STRING_SIZE+1); // Память для 2х сравниваемых строк
char* secondString = alloca(MAX_STRING_SIZE+1); // суммарно 2*MAX_STRING_SIZE + 2 байт
// If the allocation causes stack overflow, program behaviour is undefined.
memset(firstString, 0x00, MAX_STRING_SIZE + 1); // на всякий случай пусть в жопе ЗА строкой лежит 0x00
memset(secondString, 0x00, MAX_STRING_SIZE + 1);
uint8_t N_Changes; // число перестановок в массиве
do {
N_Changes = 0; // на этом проходе мы еще ничо не переставляли
for (uint8_t i = 0; i < NUM_STRINGS - 1; ++i) {
firstString = ReadStringNum(firstString, i); // читаем строки с НОМЕРАМИ i и i+1
secondString = ReadStringNum(secondString, i + 1); // НЕ ИНДЕКСАМИ!!!
int8_t cmpResult = strcmp(firstString, secondString);
if (cmpResult > 0) { // если первая строка БОЛЬШЕ второй
uint8_t tmp = StringIdx[i];
StringIdx[i] = StringIdx[i + 1]; // меняем местами индексы в таблице
StringIdx[i + 1] = tmp;
++N_Changes; // и число перестановок теперь не ноль
}
}
} while (N_Changes > 0); // конец, когда переставлять больше нечего
}
void setup() {
InitArray();
Sort();
}
void loop() {
}
Вы не правы . код сортирует, что я неправильно делал я нашел … Может конечно не на таком уровне как Ваш… но всеже… Единственное просил указать если я криво использовал выше указаные куски кода…
DetSimen спасибо большое… нечто подобное я накропал ночью но еще не успел проверить . я тоже решил что 2 байта на индекс в массиве многовато и использовал лишь дельту от него , ну и со стеком я пока не работал , как Вы … у меня все в куче
единственное вопрос
Разделы для этого предназначенные читают те, кто и без меня умеет. А те, кто не умеет: “У меня простой вопрос, на который надо получить ответ, я что, обязан для этого весь форум перекапывать?”