Не инициализируется переменная

AsNik
Offline
Зарегистрирован: 24.10.2020

Я не знаю как в яве, и не знаю как в питоне...

Ладно, реально уже путаница пошла.

Вот один Дед меня тока понимает) За что ему огромное спасибо) Да всем Спасибо!!!

С Делфи.... я пришел в си. 

[qoute]

Вот в Си даже строки так НЕ КОПИРУЮБТСЯ. Ок?

[/qoute]

Ок.)

AsNik
Offline
Зарегистрирован: 24.10.2020

DetSimen пишет:

Мошт, пожже найду у себя функцию центровки и вывода в 1602. 

В любом случае, даже если по прямому назначению не смогу использовать но в учебных целях посмотрел бы. Спасибо.

AsNik
Offline
Зарегистрирован: 24.10.2020

b707 пишет:

потому что Buff[] - это массив, а Buff - указатель на его первый (нулевой) элемент. Нельзя присвоить строку указателю....

Учите Си

Да знаю я... и  у указателя всегда фиксированный размер (например тут 2 байта (вроде:)) И в эти два байта точно ни одна литерная константа более двух символов(однобайтных) не влезет... Не говоря уж о строках...

Меня сбивают столку звезды) Ну не знаю почему... (((

Вот правда, не знаю как вы к этому привыкали, но...:
int value = 7;
const int *ptr1 = &value; // ptr1 указывает на "const int", поэтому это указатель на константное значение 
int *const ptr2 = &value; // ptr2 указывает на "int", поэтому это константный указатель на неконстантное значение
const int *const ptr3 = &value; // ptr3 указывает на "const int", поэтому это константный указатель на константное значение
 
int const.... const int... тут звездочка, там... Мой старый моск это очень плохо осваивает :(
А что такое указатель и что такое данные по этому указателю(переменная) я более менее знаю нормально
wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

AsNik пишет:

const int *ptr1 = &value; // ptr1 указывает на "const int", поэтому это указатель на константное значение 
int *const ptr2 = &value; // ptr2 указывает на "int", поэтому это константный указатель на неконстантное значение
const int *const ptr3 = &value; // ptr3 указывает на "const int", поэтому это константный указатель на константное значение
 
int const.... const int... тут звездочка, там... Мой старый моск это очень плохо осваивает :(
А что такое указатель и что такое данные по этому указателю(переменная) я более менее знаю нормально

Нет, не знаешь. Иначе бы не путался, но не это важно. Ща простому научу!

Читай прямо, как написано, по русски читай:

const int * ptr1 = &value;

На константу целую указатель ptr1, присвоить ему адрес переменной value;

--------------

int * const ptr2  = &value;

На целое указатель константа ptr2, присвоить ей адрес переменной value;

----------------

Немного коряво по русски выходит, и падежи нужно согласовать, но идея понятна?

AsNik
Offline
Зарегистрирован: 24.10.2020

wdrakula пишет:

Немного коряво по русски выходит, и падежи нужно согласовать, но идея понятна?

Спасибо большое. Идея понятна. У меня даже вот такая памятка есть:

Заключение
Подводя итоги, вам нужно запомнить всего лишь 4 правила:

   Неконстантный указатель можно перенаправить указывать на любой другой адрес.

   С помощью указателя на неконстантное значение можно изменить это же значение (на которое он указывает).

   Константный указатель всегда указывает на один и тот же адрес, и этот адрес не может быть изменен.

   Указатель на константное значение обрабатывает значение как константное (даже если оно таковым не является) и, следовательно, это значение через указатель изменить нельзя.

А вот с синтаксисом может быть немного труднее. Просто помните, что тип значения, на который указывает указатель, всегда находится слева (в самом начале):

int value = 7;
const int *ptr1 = &value; // ptr1 указывает на "const int", поэтому это указатель на константное значение 
int *const ptr2 = &value; // ptr2 указывает на "int", поэтому это константный указатель на неконстантное значение
const int *const ptr3 = &value; // ptr3 указывает на "const int", поэтому это константный указатель на константное значение

Указатели на константные значения в основном используются в параметрах функций (например, при передаче массива) для гарантии того, что функция случайно не изменит значение(я) переданного ей аргумента.

Вот не поверите. Я могу сейчас все это переварить и понять, но завтра снова могу путаться... ну не знаю с чем это связано, ну никак они до меня не доходят... точнее не задерживаются...

Тем более строки (которых нет)...

long MyVal;

long * PMyVal;

Вот в памяти лежат подряд четыре байта. Но в общем они один long. Так вот все четыре они MyVal. И sizeof(MyVal) = 4. A PMyVal - это указатель. Его размер в си МК 2 байта. И если сделать PMyVal = &MyVal то хоть он и будет ссылаться на longвскую переменную, но по сути это первый адрес MyVal и sizeof(PMyVal) = 2. И если в MyVal лежит например 2 367 135 - такое значение. То в PMyVal может быть максимальное значение двухбайтовое - это адрес в памяти. И его нельзя просто так придумать, его можно только взять &var

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

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

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

AsNik,

ну, я так понял нового скетча и вопроса (о котором я просил в #48) не будет. Ну, не нужно, так не нужно.

Но без вопроса мне непонятна, зачем и в каком контексте Вам нужно этому массиву что-то присваивать. Рискну предположить, что для восстановления содержимого после того, как в него нагадили. В связи с этим вопрос, Вы прочитали последний абзац в посте #44? Сделали то, что я просил обязательно сделать? И что, необходимость в присваивании не отпала?

AsNik
Offline
Зарегистрирован: 24.10.2020

ЕвгенийП пишет:

В связи с этим вопрос, Вы прочитали последний абзац в посте #44? Сделали то, что я просил обязательно сделать? И что, необходимость в присваивании не отпала?

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

AsNik
Offline
Зарегистрирован: 24.10.2020

ЕвгенийП пишет:

Сделали то, что я просил обязательно сделать?

Запустил. Евгений, тут же все просто как три копейки.

В первом случае мы меняем глобальную переменную, поэтому она и сохраняет предыдущие значения.

Во втором случае(перенесли ее в Test) она локальная и каждый раз инициализируется заново...

Тут нет указателей) Здесь все понятно.

AsNik
Offline
Зарегистрирован: 24.10.2020

ЕвгенийП пишет:

Но без вопроса мне непонятна, зачем и в каком контексте Вам нужно этому массиву что-то присваивать. Рискну предположить, что для восстановления содержимого после того, как в него нагадили.

Не совсем так... я тут где-то в середине темы выложил код функции, при написании которой у меня и возник вопрос данной темы... Собс-но вот этот код еще раз:

char Buff[15];

void setup() {
  Serial.begin(115200); Serial.println("Start");
  Serial.println(Test(11, Buff));
  Serial.println(Test(10, Buff));
  Serial.println(Test(9, Buff));
  Serial.println(Test(5, Buff));
  Serial.println(Test(4, Buff));
  Serial.println(Test(3, Buff));
  Serial.println(Test(2, Buff));
}

void loop() {}


char * Test(const byte aLen, char * aTxt) {
  char Str[aLen];
  strcpy_P(Str, PSTR("Txt"));
  byte L = strlen(Str);
  byte nPos;
  if (L >= aLen) strcpy(aTxt, Str);
  else {
    nPos = (aLen + 1 - L) / 2;
    memset(aTxt, 33, nPos);
    strcpy(aTxt + nPos, Str);
    memset(aTxt + nPos + L, 33, aLen - nPos - L);
  }
  aTxt[aLen] = '\0';
  return aTxt;
}

Вот вместо strcpy_P(Str, PSTR("Txt")); я и начал присваивать текстовую константу, ну и в итоге родилась данная тема.

Но сейчас вроде худо-бедно все встало на свои места... Вы мне скажите можно ли как-то оптимизировать мой вариант функции из этого сообщения. 

Подробнее в http://arduino.ru/forum/pesochnitsa-razdel-dlya-novichkov/ne-initsializiruetsya-peremennaya#comment-634997

и http://arduino.ru/forum/pesochnitsa-razdel-dlya-novichkov/ne-initsializiruetsya-peremennaya#comment-635001

А как вставляется решетка с номером поста в виде ссылки?

Upper
Offline
Зарегистрирован: 23.06.2020

>> А как вставляется решетка с номером поста в виде ссылки?

Выделить мышкой #59 и скопировать (Ctrl+C). Потом вставить в ответ (Ctrl+V).

sadman41
Offline
Зарегистрирован: 19.10.2016

Давно не брал я в руки шашек... Как-то вот так (но я в фаре набил, может и не работает):

const char STRING_text[] PROGMEM = "hello";
const char CHAR_padding = 0x20;


char * printOnCenter(char *_buffer, const uint8_t _bufferSize, const char* _message) {
  const uint8_t messageSize = strlen_P(_message);
  uint8_t printOffset, printSize;
  
  if (_bufferSize <= messageSize) {
    printOffset = 0x00;
    printSize   = _bufferSize;
  } else {
    memset(_buffer, CHAR_padding, _bufferSize);
    printOffset = (_bufferSize - messageSize) / 2;
    printSize   =  _bufferSize - printOffset;
  }

  //strlcpy_P(&_buffer[printOffset], _message, printSize);
  strlcpy_P(_buffer + printOffset, _message, printSize);
  return _buffer;
}

void setup() {
  char Buff[15];

  Serial.begin(115200); Serial.println("Start");
  Serial.println(printOnCenter(10, Buff, STRING_text));
}

void loop() {}

 

AsNik
Offline
Зарегистрирован: 24.10.2020

sadman41 пишет:

Serial.println(printOnCenter(10, Buff, STRING_text));

Перепутали местами. И вывод не верный

Start
!!hello
 
Я заменил пробел на ! что бы видно было результат
 
Код практически как и у меня. Но я идею понял. Тут нет второй "строковой" переменной. Соответственно нет дополнительного копирования. Но она передается из вне... Это немного не то) У меня эта "hello" будет генерироваться внутри данной функции...
 
А вот почему нет пробелов(!) в конце
 
Функция strlcpy копирует из строки src в буфер dst не более чем size - 1 символов и гарантированно устанавливает в конец строки нулевой символ.
 
Т.е. как и у меня когда я сначала тоже залил весь буфер пробелами, потом по центру вставил strcpy Txt и "задние" пробелы пропали..
sadman41
Offline
Зарегистрирован: 19.10.2016

Да, что-то я сглупил в последний момент - поставил терминирующую функцию вместо не терминирующей. Подумал, что ещё сэкономлю на aTxt[aLen] = '\0';

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

AsNik
Offline
Зарегистрирован: 24.10.2020

sadman41 пишет:

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

Имеете ввиду char *_buffer, а просто тупо в функции использовать  char Buff[15]; ?

Не, так тоже не пойдет. 

#41 Там в конце сообщения пояснения по этому поводу...

sadman41
Offline
Зарегистрирован: 19.10.2016
char * printOnCenter(char *_buffer, const uint8_t _bufferSize) {
  const uint8_t messageSize = strlen_P(STRING_text);
  uint8_t printOffset, printSize;

  if (_bufferSize < messageSize) {
    printOffset = 0x00;
    printSize   = _bufferSize;
  } else {
    memset(_buffer, CHAR_padding, _bufferSize);
    printOffset = (_bufferSize - messageSize) / 2;
    printSize   =  _bufferSize - printOffset;
  }

  //strlcpy_P(&_buffer[printOffset], _message, printSize);
  strncpy_P(_buffer + printOffset, STRING_text, printSize);
  return _buffer;
}

PSTR наплодит индивидуальных строк, даже если они будут одинаковыми. А вот такое применение объявления с PROGMEM даст возможность одно и то же слово/фразу использовать в нескольких местах без дополнительных расходов. Это то, что я хотел показать в примере.

Впрочем, я прочитал указанный выше пост и не понял, чем вариант с передачей указателя на PROGMEM не нравится. По мне так он как раз туда и подходит.

AsNik
Offline
Зарегистрирован: 24.10.2020

sadman41 пишет:

функцию вместо не терминирующей. 

А есть такие? Я вот не нашел, хотя именно про это и подумал в первую очередь, но ничего не нашел подходящего...

Цитата:

Подумал, что ещё сэкономлю на aTxt[aLen] = '\0';

А без этого не получится :) Ну если только правых пробелов нет, или когда длина выходной строки меньше, чем "hello"...

sadman41
Offline
Зарегистрирован: 19.10.2016

AsNik пишет:

sadman41 пишет:

функцию вместо не терминирующей. 

А есть такие? Я вот не нашел, хотя именно про это и подумал в первую очередь, но ничего не нашел подходящего...

The strncpy_P() function is similar to strcpy_P() except that not more than n bytes of src are copied. Thus, if there is no null byte among the first n bytes of src, the result will not be null-terminated.

In the case where the length of src is less than that of n, the remainder of dest will be padded with nulls.

AsNik
Offline
Зарегистрирован: 24.10.2020

sadman41 пишет:

PSTR наплодит индивидуальных строк, даже если они будут одинаковыми. 

....

Впрочем, я прочитал указанный выше пост и не понял, чем вариант с передачей указателя на PROGMEM не нравится. По мне так он как раз туда и подходит.

PSTR "случайно" попал в пример, извиняюсь.... но про Txt я же говорил, что эта строка будет генерироваться разной, по некоторым условиям и вставляться в выходную строку... А та в свою очередь подставиться на место в sprintf %s

Я подумал про глобальный буфер, что его вроде как не нужно передавать в функцию, а пользовать прямо напрямую... А так не пойдет, ибо в sprintf могут быть два %s %s (соответственно буфера тоже два должно быть)

AsNik
Offline
Зарегистрирован: 24.10.2020

sadman41 пишет:

In the case where the length of src is less than that of n, the remainder of dest will be padded with nulls.

Переводчик перевел: В случае, когда длина src меньше длины n, остаток dest будет заполнен нулями.

По моему тоже не подойдет.... Попробую позже

sadman41
Offline
Зарегистрирован: 19.10.2016

Не умею оптимизировать абстрактные функции, в которых через неделю начнёт генерироваться неведомое.

Предоставленную рутину я подрихтовал.

sadman41
Offline
Зарегистрирован: 19.10.2016

Если это тоже не подходит, можем взять:

The memcpy_P() function is similar to memcpy(), except the src string resides in program space.

Этой вообще все равно что копировать.

AsNik
Offline
Зарегистрирован: 24.10.2020

sadman41 пишет:
в которых через неделю начнёт генерироваться неведомое.

Ну не совсем так :) Там в общем т будет конечный автомат. Кое какие варианты, просто более чем один... Но не суть.. Ваш пример я не отрицаю и не критикую, все норм. Но значит и мой имеет право на жизнь... Посмотрю еще что можно сделать с memcpy... А так, в моем немного заточено под мои "хотелки" Они не явные, но всеж.... Например при делении на два, я добавляю единичку, для того, что бы пробел(если он один) добавлялся в начало(слева)... Но а в итоге это (мой и ваш код) завершающая и главная часть функции, а в начале будет генерация того самого "hello"....

Но если честно, то некоторые варианты, но здесь я их так и назову "hello" - да, хранятся в PROGMEM, а некоторые конвертируются из других типов в строку.... Но PSTR там не будет, а копирование c PROGMEM так же как и у Вас..

AsNik
Offline
Зарегистрирован: 24.10.2020

AsNik пишет:

Но PSTR там не будет, а копирование c PROGMEM так же как и у Вас..

В прочем не совсем как у Вас. В моих вариантах кода присутствуют указатели (( Признаюсь, что код не совсем полностью мой, ну т.е. код-то мой, сам написал, но посмотрел как это делается у других... ну и естественно с указателями я запутался.

Вот как у меня:

char TxtBuff1 [8];
char TxtBuff2 [8];
char TxtBuff3 [8];
char TxtBuff4 [4];
const char DashL[] PROGMEM = " ----- ";
const char is   [] PROGMEM = "-is-";
const char ns   [] PROGMEM = "-ns-";
const char nd   [] PROGMEM = "-nd-";
const char rs   [] PROGMEM = "-rs-";
const char TErr [] PROGMEM = "TErr";
const char HErr [] PROGMEM = "HErr";
const char PErr [] PROGMEM = "PErr";
//--------------------------------------
const char Inf1_L1[] PROGMEM = "Sens: %s";
const char Inf1_L2[] PROGMEM = "T: %s H:%s";
const char Inf1_L3[] PROGMEM = "Humi(ABS): %s gm3";
const char Inf1_L4[] PROGMEM = "Pressure: %s  mm";
const char * const SCRN_Inf1[] PROGMEM = {Inf1_L1, Inf1_L2, Inf1_L3, Inf1_L4};

const char Inf23_L1[] PROGMEM = "View Sens %d-%d";
const char Inf23_L2[] PROGMEM = "Sens:  S%d   S%d   S%d ";
const char Inf23_L3[] PROGMEM = "Temp: %s %s %s";
const char Inf23_L4[] PROGMEM = "Humi: %s %s %s";
const char * const SCRN_Inf2[] PROGMEM = {Inf23_L1, Inf23_L2, Inf23_L3, Inf23_L4};

const char Inf45_L1[] PROGMEM = "View Channels  %d-%d";
const char Inf45_L2[] PROGMEM = "ChN: Ch%d Ch%d Ch%d Ch%d";
const char Inf45_L3[] PROGMEM = "Stat:%s %s %s %s";
const char Inf45_L4[] PROGMEM = "Cnt: %s %s %s %s";
const char * const SCRN_Inf3[] PROGMEM = {Inf45_L1, Inf45_L2, Inf45_L3, Inf45_L4};

И использование:

....
PrintLCDLine(1, SCRN_Inf1, GetTempText(sens_ulica, 7, TxtBuff1), GetHumiText(sens_ulica, 7, TxtBuff2));
.....

const size_t PrintLCDLine(const byte aLine, const char * const aArr[], ...) {
  char szFormat[20];
  strcpy_P(szFormat, (char*)pgm_read_word(&(aArr[aLine])));
...

(В этом месте я считываю форматирующую строку, а вот дальше в ней будет будет та самая функция с центрованной, определенной длины строка.)

Кстати вот на Ваш код смотрю, и все понимаю.... там нет указателей... а вот мой у меня вызывает некоторый дискомфорт и непонимание :(

Как я понимаю его: Константные строки хранятся во флэш... Так же там "рядышком" хранятся и указатели(?) на  них в массиве... А указывают они куда, они же во флэше.... Или при чтении когда будут в ОЗУ эти указатели "заработают"? Головная боль у меня от них... 

sadman41
Offline
Зарегистрирован: 19.10.2016

А что, если они лежат во флеше, то в беспорядке свалены? Точно так же есть у каждой строки адрес ячейки, с которой она начинается. Следовательно - можно создать переменную-указатель, которая этот адрес содержит.

Что RAM, что FLASH - принцип доступа один и тот же. Только это разные части микросхемы, поэтому компилятор должен знать - куда ему лезть. Оттого часть функций работы с памятью снабжена постфиксом _P. Которые с ним - лезут во флеш, без него - в RAM.

...как в компутере: диск A и диск C - разные, а файлы там одинаковые.

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

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

AsNik пишет:

char Buff[15];

void setup() {
  Serial.begin(115200); Serial.println("Start");
  Serial.println(Test(11, Buff));
  Serial.println(Test(10, Buff));
  Serial.println(Test(9, Buff));
  Serial.println(Test(5, Buff));
  Serial.println(Test(4, Buff));
  Serial.println(Test(3, Buff));
  Serial.println(Test(2, Buff));
}

void loop() {}


char * Test(const byte aLen, char * aTxt) {
  char Str[aLen];
  strcpy_P(Str, PSTR("Txt"));
  byte L = strlen(Str);
  byte nPos;
  if (L >= aLen) strcpy(aTxt, Str);
  else {
    nPos = (aLen + 1 - L) / 2;
    memset(aTxt, 33, nPos);
    strcpy(aTxt + nPos, Str);
    memset(aTxt + nPos + L, 33, aLen - nPos - L);
  }
  aTxt[aLen] = '\0';
  return aTxt;
}

Вот вместо strcpy_P(Str, PSTR("Txt")); я и начал присваивать текстовую константу, ну и в итоге родилась данная тема.

Простите, я, возможно, совсем тупой, но вот не понимаю, что Вам мешает вместо строк №№ 18 и 19 просто написать

  char Str[aLen] = "Txt";

и не париться?

Да, это немного нестандартно, но Вы же не будете это ничем, кроме GCC компилировать.

В чём проблема? Попробуйте понятно сформулировать вопрос, только в одном месте, не заставляйте меня перепахивать всю тему.

b707
Offline
Зарегистрирован: 26.05.2017

AsNik - у вас задача какая? вставить строку в буфер, начиная с определенной позиции? - что мешает скопировать строку в буфер посимвольно в цикле? - и не надо будет обрабатывать конец строки и пробелы справа не исчезнут....

Скопировать можно "вручную", а можно сразу блоком через memcpy() -которая, впрочем, внутри себя представляет собой тот же  побайтовый цикл

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

Использовать сторонние функции не его дорога видимо. Всё и вся только вызовы стандартных функций !!!

AsNik
Offline
Зарегистрирован: 24.10.2020

sadman41 пишет:

Точно так же есть у каждой строки адрес ячейки, с которой она начинается. Следовательно - можно создать переменную-указатель, которая этот адрес содержит.

Что RAM, что FLASH - принцип доступа один и тот же. Только это разные части микросхемы, поэтому компилятор должен знать - куда ему лезть. Оттого часть функций работы с памятью снабжена постфиксом _P. Которые с ним - лезут во флеш, без него - в RAM.

...как в компутере: диск A и диск C - разные, а файлы там одинаковые.

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

Понятно. Просто у меня Flash ассоциируется с HDD а RAM(ОЗУ) она и в африке озу... К стати, о "в голове эту разницу" есть еще и EPROM который больше похож на HDD, но тоже так себе ассоциация.. Вот RAM четко определяется(ассоциируется), а Flash и eprom....

AsNik
Offline
Зарегистрирован: 24.10.2020

ЕвгенийП пишет:

Простите, я, возможно, совсем тупой, но вот не понимаю, что Вам мешает вместо строк №№ 18 и 19 просто написать

  char Str[aLen] = "Txt";

и не париться?

Простите?!... Извините, но тупой тут я :( У меня и в мыслях такого не было... Чуть  позже буду разбираться с char Str[aLen] = "Txt"; Как-то пока не укладывается это в голове... а попробовать сейчас не имею возможности.

Стоп... я не о том подумал :) Совсем уже запутался))) Это же элементарно.

А я почему то подумал что можно в середине строки на место очередного символа str[ch] = "Txt" вставить целиком строку :) Во дурак)

И да, так char Str[aLen] = "Txt";  не пойдет, потому что Txt - это просто подстрока, которая может быть и другой... я об этом уже неоднократно говорил, но понимаю, что тема растет и за всем не уследишь...

ЕвгенийП пишет:

В чём проблема? Попробуйте понятно сформулировать вопрос, только в одном месте, не заставляйте меня перепахивать всю тему.

Оно как-то не получается... Тема быстро развивается... Вопрос то был, но другие участники тоже не дремлют...

На данный момент пока все уложилось... но с указателями в моей голове, я думаю, особо лучше не стало... ((

AsNik
Offline
Зарегистрирован: 24.10.2020

b707 пишет:

AsNik - у вас задача какая? вставить строку в буфер, начиная с определенной позиции?

Да, вставить в одну строку другую с определенной позиции, и что бы в итоге получилась строка строго определенной длины.

b707 пишет:

что мешает скопировать строку в буфер посимвольно в цикле? - и не надо будет обрабатывать конец строки и пробелы справа не исчезнут....

Скопировать можно "вручную", а можно сразу блоком через memcpy() -которая, впрочем, внутри себя представляет собой тот же  побайтовый цикл

Komandir пишет:

Использовать сторонние функции не его дорога видимо. 

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

Но подумал, что есть более стандартные вещи и решил их найти. В итоге пришел к memset и strcpy... Но так как последняя вставляет ноль, пришлось два раза делать memset. Но, не то что бы два раза одно и тоже, а каждый вызов функций меняет только свою часть строки:

    nPos = (aLen + 1 - L) / 2;
    memset(aTxt, 33, nPos);
    strcpy(aTxt + nPos, Str);
    memset(aTxt + nPos + L, 33, aLen - nPos - L);

На данный момент, мне sadman41 первым подсказал про memcpy... так что попробую сократить немного свою функцию...

AsNik
Offline
Зарегистрирован: 24.10.2020

ЕвгенийП пишет:

В чём проблема? Попробуйте понятно сформулировать вопрос, только в одном месте, не заставляйте меня перепахивать всю тему.

Приношу свои извинения, но я наверное понял чем сбил всех с толку... Мой вопрос из кода:

char * Test(const byte aLen, char * aTxt) {
  char Str[aLen];
  strcpy_P(Str, PSTR("Txt"));
  byte L = strlen(Str);
  byte nPos;
  if (L >= aLen) strcpy(aTxt, Str);
  else {
    nPos = (aLen + 1 - L) / 2;
    memset(aTxt, 33, nPos);
    strcpy(aTxt + nPos, Str);
    memset(aTxt + nPos + L, 33, aLen - nPos - L);
  }
  aTxt[aLen] = '\0';
  return aTxt;
}

сводится наверно вот к этому участку:

    nPos = (aLen + 1 - L) / 2;
    memset(aTxt, 33, nPos);
    strcpy(aTxt + nPos, Str);
    memset(aTxt + nPos + L, 33, aLen - nPos - L);

вот его я имел ввиду, на сколько я сделал (не)оптимально....

Вечером попробую такой вариант

    memset(aTxt, 33, aLen);
    memcpy(aTxt + nPos, Str, L);

AsNik пишет:

Вечером попробую такой вариант

char * Test(const byte aLen, char * aTxt) {
  char Str[aLen];
//тут генерация подстроки Str, временно так:  
  strcpy_P(Str, PSTR("Txt"));
//--------------------------------------
  byte L = strlen(Str);
  byte nPos;
  if (L >= aLen) strcpy(aTxt, Str);
  else {
    nPos = (aLen + 1 - L) / 2;
    memset(aTxt, 32, aLen);
    memcpy(aTxt + nPos, Str, L);
  }
  aTxt[aLen] = '\0';
  return aTxt;
}

Все получилось с memcpy как нужно.