Увеличить определенный символ в строке

sonmax
Offline
Зарегистрирован: 30.06.2013

Всем привет!

Заморочился с такой проблемой и теперь немогу побороть ее:

Необходимо менять число по разрядам, например есть 

setPosition = 1234

надо по кнопке увеличить/уменьшить определенный разряд в общем числе (возьмем разряд my_pos=2 - сотни),

этот код не совсем рабочий 

 switch(my_pos){   // в зависимости от индекса увеличиваю на единицы, десятки, сотни, тысячи
  case 1: setPosition += 1000; if (setPosition > 9999) setPosition -= 10000; break;// тысячи
  case 2: setPosition += 100;  if (setPosition > 999) setPosition -= 1000;  break; // сотни
  case 3: setPosition += 10;   if (setPosition > 99) setPosition -= 100;   break;  // десятки
  case 4: setPosition += 1;    if (setPosition > 9) setPosition -= 10;    break;   // единицы
}

но предположим если число превышает 9 он должно равняться 0. а следующий разряд не должен увеличиваться.

Надеюсь понятно объяснил

пробовал число преобразовывать в char и менять по нужному индексу, но тоже как-то криво получается.

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

А тип setPosition?

sonmax
Offline
Зарегистрирован: 30.06.2013

Извиняюсь, int setPosition

byte my_pos 

sonmax
Offline
Зарегистрирован: 30.06.2013

вот так пробовал через char setPosition=1357 

1. const char char_pos[4];
2. sprintf(char_pos,"%04d", setPosition); // в char с нулями впереди
3. char char_1[1]; 
4. char_1[0] = char_pos[2];      
5. int intVar = atoi(char_1);      
6. intVar ++;
7. itoa (intVar, char_1, 10);
8. char_pos[2] = char_1[0];
9. setPosition = atoi(char_pos);
10. Serial.print("setPosition - "); Serial.println(setPosition);
     

само преобразование на мой взгляд не очень красивое и на 8 шаге должно было получиться

1367, но почемуто выдает 13576

OlegK
OlegK аватар
Offline
Зарегистрирован: 26.11.2014

sonmax пишет:
char setPosition=1357

Смотрите размерность типа char

fogary
Offline
Зарегистрирован: 05.03.2016

sonmax пишет:

но предположим если число превышает 9 он должно равняться 0. а следующий разряд не должен увеличиваться.

Например, разобрать число на разряды, изменить выбранный разряд, обратно собрать число из разрядов. Либо изначально хранить разряды в виде структуры или массива, а само число собирать по-требованию.

sonmax
Offline
Зарегистрирован: 30.06.2013

Второй вариант как раз это и делает. пока разбираюсь как измененную цифру обратно запихнуть.

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

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

'1' + 1 = '2'

'2' + 1 = '3'

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

char buffer[] = "1234";
byte pos = 2;
buffer[pos]++;
if (buffer[pos] > '9')
{
  buffer[pos] = '0';
}
Serial.println(buffer);

Данный код увеличит цифру в позиции 2 (счет с нуля) и отобразит число "1244".

 

fogary
Offline
Зарегистрирован: 05.03.2016

sonmax пишет:

Второй вариант как раз это и делает. пока разбираюсь как измененную цифру обратно запихнуть.

Как вариант.

void change_number(unsigned *number, uint8_t index, int8_t step) {
  int8_t digits[4];
  
  if (*number > 9999 || index = 0 || index > 4) return;

  digits[0] = *number / 1000;
  *number %= 1000;
  digits[1] = *number / 100;
  *number %= 100;
  digits[2] = *number / 10;
  *number %= 10;
  digits[3] = *number;
  
  index--;
  digits[index] += step;
  if (digits[index] > 9)
	digits[index] = 0;
  else (digits[index] < 0)
	digits[index] = 9;
	
  *number = digits[0] * 1000 + digits[1] * 100 + digits[2] * 10 + digits[3];
  
  return;
}

Пример.

unsigned number1 = 1234;

// увеличить значение сотен на 1
change_number(&number1, 3, 1);
// уменьшить значение десятков на 1
change_number(&number1, 2, -1);

 

sonmax
Offline
Зарегистрирован: 30.06.2013

Спасибо, оба варианта хорошие, 

 но второй вариант мне больше нравится т.к. нет преобразований

только вот ругается на if (*number > 9999 || index = 0 || index > 4) return;

пишет "lvalue required as left operand of assignment"

все разобрался

if ((*number > 9999) || (index = 0) || (index > 4)) return;

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

Так уберите assignment и поставьте нормальное сравнение. Это очевидная опечатка. Вы, похоже, не понимаете. что в этом коде написано. Так?

sonmax пишет:

все разобрался

if ((*number > 9999) || (index = 0) || (index > 4)) return;

Нет, не разобрался. Похоже, действительно не понимаете.

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016
// вот два макроса

#define   incDecPlace(x,d)  (((x)/(d))%10 < 9)?((x)+(d)):((x)-9*(d))
#define   decDecPlace(x,d)  (((x)/(d))%10 > 0)?((x)-(d)):((x)+9*(d))

// Вот так пользоваться

   printf ("%d %d \n", incDecPlace(aaa,1),decDecPlace(aaa,1));
   printf ("%d %d \n", incDecPlace(aaa,10),decDecPlace(aaa,10));
   printf ("%d %d \n", incDecPlace(aaa,100),decDecPlace(aaa,100));
   printf ("%d %d \n", incDecPlace(aaa,1000),decDecPlace(aaa,1000));

Да! Забыл добавить, что критики могут идти в жопу... ну ка всегда. ;)

sonmax
Offline
Зарегистрирован: 30.06.2013

Пришлось поправить

void change_number(int *number, int8_t index, int8_t step) {
  int8_t digits[4];
  if ((*number > 9999) || (index == 0) || (index > 4)) return;
  digits[0] = *number / 1000;
  *number %= 1000;
  digits[1] = *number / 100;
  *number %= 100;
  digits[2] = *number / 10;
  *number %= 10;
  digits[3] = *number;
  //index --;
  digits[index] += step;
  if (digits[index] > 9)  digits[index] = 0;
  //else digits[index] = 9;
  *number = digits[0] * 1000 + digits[1] * 100 + digits[2] * 10 + digits[3];
  return;
}

в принципе if тоже можно убрать

Пишут printf  сильно нагружает ардуину, но вариант клевый.

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

printf() не от ардуины, а для примера. Какая связь ардуины и printf() в Вашем варианте мозгового вещества?

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

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

sonmax
Offline
Зарегистрирован: 30.06.2013

Полагаю в Ардуино используется эта функция sprintf() 

вот например что про нее пишут:

Конвертирование данных в строку с помощью функции sprintf.

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

int sprintf( char *string, const char *format , argument1, argument2 ... )

судя по этому "Да! Забыл добавить, что критики могут идти в жопу... ну ка всегда. ;)" У вас наверное мания величия.

Я например владею 5 языками программирования, а ардуино занимаюсь время от времени ради удовольствия. Но спорить не собираюсь. Вам гуру виднее.  

 

 

 

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

да причеи тут строки? Вы слепой или туповаты? Я вам макросы написал для целых чисел. Не для строк.

Не нужно брехать про 5 языков, если Вы мудацкие вопросы задаете. Тут не дети сидят, а старые дядьки.

Письками меряться со мной не стоит точно, мне 47 лет, очень хорошее образование и очень плохой характер.

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

Либо слушайте, что говорят, и кланяйтесь, либо сразу нахер.

Дискуссия тут у него, итить в сраку!

sonmax
Offline
Зарегистрирован: 30.06.2013

характер - да.

Logik
Offline
Зарегистрирован: 05.08.2014

kisoft пишет:

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

'1' + 1 = '2'

'2' + 1 = '3'

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

char buffer[] = "1234";
byte pos = 2;
buffer[pos]++;
if (buffer[pos] > '9')
{
  buffer[pos] = '0';
}
Serial.println(buffer);

Данный код увеличит цифру в позиции 2 (счет с нуля) и отобразит число "1244".

 

)))

Что, kisoft, убедились что короткий верный код новичкам не нравится? Они его не понимают и тупо игорят, как бы его и небыло! Они не верят что их сверхсложную задачу (понятно суперсложную ИИ вобще отдыхает)  можна в 3 строки  решить  )))

Вот если бы классы позабористей, да оптронов побольше)))

Дикари-с...

ПС. спасибо, поржал..

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

Фигасе!

sonmax пишет:

Я например владею 5 языками программирования

и от того же автора

sonmax пишет:

только вот ругается на if (*number > 9999 || index = 0 || index > 4) return;

пишет "lvalue required as left operand of assignment"

все разобрался

if ((*number > 9999) || (index = 0) || (index > 4)) return;

Херасе!

И ведь человек настолько "владеет", что даже не понимает комизма ситуации!

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

sonmax
Offline
Зарегистрирован: 30.06.2013

Я понимаю, что теперь к концу работы можно и поржать.

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

Ваш код помог, но такие ошибки (index = 0) тоже можно на лузера списать.

fogary
Offline
Зарегистрирован: 05.03.2016

sonmax пишет:

Пришлось поправить

Прошу прощение за допущенные досадные ошибки.
При допустимых значениях входные аргументов проверка не нужна.

Если эту строку закоментировать,

//index --;

 то значения index должны быть от 0 до 3, а не от 1 до 4.

В конце функции допустил еще одну ошибку. Планировалось так:

  if (digits[index] > 9)
    digits[index] = 0;
  else if (digits[index] < 0)
    digits[index] = 9;