Update single digit in an int

Hello,

Been struggling with this for a while now.

I'm trying to create a function like:

unsigned int setDigit(unsigned int inputNumber, byte newDigit, byte loc, byte exponent)

It should basically accept an unsigned int, a byte, a location and the exponent. It should then update whatever number is at location loc to the newDigit byte that's passed in.

I'm using this on a display 4x7 segment display that will show a number either in dec or hex (hence the exponent parameter) and the user can change a single digit that's being displayed by pressing a button to move the "cursor" left or right, and then press a number on a keypad to set that digit.

I do have a semi working version of this code, but having problems dealing with the edge cases. For example, when the address is 0 all my logic fails.

I've tried breaking the number up into a string and setting the index to the passed byte, but this also fails.

Here are my 2 attempts at it:

Non-string version:

unsigned int setDigit(unsigned int inputNumber, byte newDigit, byte loc, byte exponent) {
  const byte maxSize = 32;

  byte numberSize = (inputNumber == 0 ? 1 : 0);
  unsigned int nSize = inputNumber;
  while (nSize != 0 && numberSize < maxSize) {
    nSize /= exponent;
    numberSize++;
  }
  
  if (loc > maxSize || loc > numberSize || loc < 0) {
    return inputNumber;
  }
  
  char *numberArray = calloc((int)numberSize, sizeof(char));

  unsigned int i = 0;
  unsigned int nCount = inputNumber;
  
  while (nCount != 0 && i < numberSize) {
    numberArray[i] = nCount % exponent;
    nCount /= exponent;
    i++;
  };

  numberArray[loc] = (newDigit % exponent);

  int output = 0;
  
  for (byte j = 0; j < numberSize; j++) {
    output = exponent * output + numberArray[j];
  }
  
  if (numberArray) {
    free(numberArray);
  }
  
  return output;
}

String version:

unsigned int setDigit(unsigned int inputNumber, byte newDigit, byte loc, byte exponent) {
  const byte maxSize = 32;

  String inputString = "";

  if (loc > maxSize || loc < 0) {
    if (SERIAL_ERRORS && Serial) {
      Serial.print("\nsetDigit(): Error: Index out of bounds.\n");
    }
    return inputNumber;
  }

  char temp[maxSize] = {0};
  sprintf(temp, "%d", inputNumber);
  inputString.concat(temp);

  char replaceNum[maxSize] = {0};
  sprintf(replaceNum, "%01d", (newDigit % exponent));
  
  
  inputString[loc] = replaceNum;
  unsigned int output = 0;

  output = strtol(inputString.c_str(), NULL, exponent + 1);
  return output;
}

For example, when the address is 0 all my logic fails.

The term "address" never appears in your code, so it isn't clear what you are talking about.

If you have a value, such as 12345, and you wish to change the 3 to a 7, simply subtract 3 * x * x and add 7 * x * x, where x is either 10 or 16.

I have no idea why you appear to be using the term exponent when you mean base.

There may be a better way to do it, but here's my attempt at implementing setDigit (lightly tested):

unsigned int setDigit(unsigned int inputNumber, byte newDigit, byte pos, byte radix) {
        unsigned int posValue = 1;
        while (pos > 0) {
                posValue *= radix;
                --pos;
        }
        return inputNumber + ((int)newDigit - (int)((inputNumber / posValue) % radix)) * posValue;
}

Hey @PaulS, sorry for the confusion. I typed it after working on it for a few hours before bed. The address is the input number. I'm passing the address in as the inputNumber when calling this function. The return of the function is then set as the address.

The main issues I'm having with this is say the address is an int of address 0, but the user wants to change the second digit.

Thank you @christop! I'm going to give your code a try once I get home. Going to go back over mine to see what I was missing too.

The Arduino integers are binary, not decimal, so I don't get what you are trying to accomplish.

Paul

I agree with @Paul_KD7HB. The concept of "single digit in an int" is meaningless.

If the data was text in a char array it would be easy to change any of the characters - for example

myCharNumber[] = "12345";

myCharNumber[2] = '7';

will change it to 12745

...R

Edit .. added single quotes around the 7 - apologies for any confusion.

Robin2:

myCharNumber[] = "12345";

myCharNumber[2] = 7;




will change it to 12745

No! It changes to what is shown in the following screenshot.
SM1.png

SM1.png

Robin2:
I agree with @Paul_KD7HB. The concept of "single digit in an int" is meaningless.

If the data was text in a char array it would be easy to change any of the characters - for example

myCharNumber[] = "12345";

myCharNumber[2] = 7;




will change it to 12745

...R

@ Robin
I think you meant:

myCharNumber[2] = '7'; //will change it to 12745 if myCharNumber is printed to serial monitor

:wink:

sherzaad:
@ Robin
I think you meant:

myCharNumber[2] = '7'; //will change it to 12745 if myCharNumber is printed to serial monitor

No! @Rabin2 has not written 'myCharNumber[2] = 7;' to mean 'myCharNumber[2] = '7';'. Wait and see what @Rabin2 says about it.

GolamMostafa:
@Rabin2

@Rabin2

Oy vey...

GolamMostafa:
No! It changes to what is shown in the following screenshot.

Thank you for spotting my mistake - I have corrected it.

Please note that a comment such as that made by @sherzaad in Reply #7 is more helpful for other readers.

...R

Robin2:
Thank you for spotting my mistake - I have corrected it.

Please note that a comment such as that made by @sherzaad in Reply #7 is more helpful for other readers.

@Rabin2 is one of the helpful posters of this Forum from both qualitative and quantitative point of views; therefore, we have to be patient to hear from him first before any 'hard comment/message' is passed onto him.

Thank you for the reply.

GolamMostafa:
@Rabin2

Robin2....

GolamMostafa:
@Rabin2 is one [...].

neiklot:
Robin2....

This is not a problem for @Robin2; it is a forumName; I will write it properly next time.

GolamMostafa:
@Rabin2 is one of the helpful posters of this Forum from both qualitative and quantitative point of views; therefore, we have to be patient to hear from him first before any 'hard comment/message' is passed onto him.

Just because I post frequently does not mean that I am less likely to make silly mistakes. I appreciate it when people point them out early and clearly so I can correct them.

...R

Edit to insert "mean"

Robin2:
Just because I post frequently does not that I am less likely to make silly mistakes. I appreciate it when people point them out early and clearly so I can correct them.

...R

"does not mean" :slight_smile:

johnwasser:
"does not mean" :slight_smile:

Much appreciated.

I don't know whether it is an age related thing but in the last year or two I have found myself skipping words when typing - as if my brain is running ahead of itself. I try to make a habit of careful proof reading but mistakes still get through :slight_smile:

...R

Robin2:
Much appreciated.

I don't know whether it is an age related thing but in the last year or two I have found myself skipping words when typing - as if my brain is running ahead of itself. I try to make a habit of careful proof reading but mistakes still get through :slight_smile:

...R

Similar here. I find I make lots of typos. Sometimes three is a single post! Sometimes I fix them. Sometimes I just let them go.