Проблемы с сортировкой

Я не задавал 1000 вопросов , вопросов было всего 3-5 , . у меня была задача и я хотел довести ее до конца, чтобы в следующий раз не спотыкаться, тем более , что она сама по себе затронула аспекты с которыми я не работал и в них все равно надо разбираться даже и без сортировки. Это не методом тыка это последовательное решение проблем…методом тыка это когда не получилось так перескочил на другое - авось по другому получится… …
Да я неспорю сортировка по индексам в массиве без самих строк мне не пришла сразу в голову…странно конечно если учесть что связи между таблицами как раз на них и построенны… Тут большое спасибо за тычек… я понял и так и делаю… Но при этом бросить незавершенный вопрос , ну как то не в моих правилах… Да возможно для скорости исполнения проекта это очень плохо , но с другой стороны мой проект - для себя ,соответственно я могу позволить себе растянуть время его завершения в угоду новым знаниям… как решил задачу сразу взялся за ту что предложили… незнаю имхо все последовательно

по поводу стыдно… да стыдно поэтому стараюсь как можно меньше спрашивать . если посмотрите я задал всего 6 вопросов (тем) 2 из которых относились к методам отладки и оптимизации а не к программированию.

Нормальный ТС. Неконфликтный, учится. Немного страдает от коммуникативной депривации, но это уже черта характера. Не нужно человека прессовать.

ТС! Ты с сортировкой отдельный пример напиши. Просто на компе или в эмуляторе на вокви. Просто для тренировки. И тебя отпустит.

romansochi, вот без обид, вы нытика напоминаете, второй день вам говорят выкинуть нахрен ваш код, начать все с нуля, по уму, а вы че то там пытаетесь доказать что вы молодец.

Че то не заметно.
Добрый вы сегодня :slight_smile:

я вопрос с тем кодом решил , о чем написал выше .(118 сообщение 5часов назад )… (вопрос по qsort снят), сейчас начну заниматся тем что подсказали.

Решение в лоб. Так себе, есть где чо пооптимизировать. Да и спрасони мог где-нить накосячить, сам проверяй. К строкам можно обращаться так же, по порядковому номеру, а от него берется уже правильный индекс позиции строки в 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() {
  
}

В том то и беда, что не снят, а отброшен ввиду невозможности разобраться и победить. А уметь ею пользоваться совсем не вредно.

Вы не правы . код сортирует, что я неправильно делал я нашел … Может конечно не на таком уровне как Ваш… но всеже… Единственное просил указать если я криво использовал выше указаные куски кода…:slight_smile:

Да, я знаю. Я также знаю кто прав в этой теме в полтораста постов. Я уже писал Вам об этом выше.

Ох, зря я сюда влез …

DetSimen спасибо большое… нечто подобное я накропал ночью но еще не успел проверить . я тоже решил что 2 байта на индекс в массиве многовато и использовал лишь дельту от него , ну и со стеком я пока не работал , как Вы … у меня все в куче
единственное вопрос

uint8_t* fromAddr = (uint8_t *)(GetStringAddr(idx));

а байта не маловато , этож живой адрес …

ну и про
constexpr с inline пока пытаюсь понять с чем едят и для чего оно , я просто дефайны использовал

Спойлер
#define KOL_STR 5    // 40
#define SIZE_STR 20  //15
#define ADRES 0x20

#include <EEPROM.h>
uint8_t list[KOL_STR];
void setup() {
  Serial.begin[19200];
  for (uint8_t i = 0; i < KOL_STR; i++) list[i] = i;
  sort();
}

void loop() {
  // put your main code here, to run repeatedly:
}

char* readstr(char* strstr, uint8_t n_list) {
  char fd[SIZE_STR];
  char* tmpAdr[SIZE_STR];
  uint8_t adrEEP = ADRES + n_list * SIZE_STR;
  EEPROM.get(adrEEP, fd);
  strcpy(strstr, fd);
  return strstr;
}

void sort(void) {
  uint8_t flg;
  char* str1 = (char*)malloc(SIZE_STR + 1);
  char* str2 = (char*)malloc(SIZE_STR + 1);
  memset(str1, 0, SIZE_STR + 1);  // на всякий случай пусть в жопе ЗА строкой лежит 0x00
  memset(str2, 0, SIZE_STR + 1);
  do {
    flg = 0;
    for (uint8_t i = 0; i < KOL_STR - 1; ++i) {
      str1 = readstr(i);
      str2 = readstr(i + 1);
      if ((strcmp(str1, str2)) > 0) {
        uint8_t tmp = i;
        list[i] = list[i + 1];
        list[i + 1] = tmp;
        flg++;
      }
    }

  } while (flg != 0);
 free(str1);
  free(str2);
}

memset подглядел у Вас … а то я просто строкой инициализировал…:slight_smile:

Это УКАЗАТЕЛЬ на байт. Адрес, по которому лежит начало строки в EEPROM

а… понятно

… и размер его вовсе не байт

я про это… я нашел свои ошибки и кода заработал, но так как дали пинок в более рентабельном варианте , то соответственно почему бы и нет

может будет время и просветите как вы это умеете делать, доходчиво, в разделе для этого предназначенном?!

Разделы для этого предназначенные читают те, кто и без меня умеет. А те, кто не умеет: “У меня простой вопрос, на который надо получить ответ, я что, обязан для этого весь форум перекапывать?

Желательно, начинать с “ПАМАГИТИ!!!”