sscanf or How to split a number to 4 digit

After many trials and errors, I finally got the code for multiplexed a 4 digit 7 segment led display half working. It counts second now. but in the way, I got a problem. how do I split a number to 4 digit? I tried sccanf, but without luck;

Here was the line of code I used; given buffer is 1234, dg1 is not 1; dg2 is not 2;

sscanf (buffer,"%d%d%d%d", dg1, dg2, dg3, dg4);

then I simply moved on. I use math to parse the number to the LED display. It works, but I want to know how to do it the proper way.

 d1=dg[minn/10];
 d2=dg[minn%10];
 d3=dg[sec/10];
 d4=dg[sec%10];

here is the working code

    const byte dg[] =
    {
    B00111111, // 0
    B00000110, // 1
    B01011011, // 2
    B01001111, // 3
    B01100110, // 4
    B01101101, // 5
    B01111101, // 6
    B00000111, // 7
    B01111111, // 8
    B01101111, // 9
    B00000000, // BLANK
    B01000000, // DASH
    B10000000  }; //dot
    
int latchPin = 3;  //Pin connected to ST_CP(pin 12) of 74HC595
int clockPin = 4; //Pin connected to SH_CP(pin 11) of 74HC595
int dataPin = 5;

int counter=1;
int sec=0;
int minn=0;

unsigned long t1=0;
unsigned long t2=0;
unsigned long c1=0;
unsigned long c2=0;

byte d1=0;
byte d2=0;
byte d3=0;
byte d4=0;

int dg1=0;
int dg2=0;
int dg3=0;
int dg4=0;

void setup() {    
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
  
   pinMode(A1, OUTPUT);
   pinMode(A2, OUTPUT);
   pinMode(A3, OUTPUT);
   pinMode(A4, OUTPUT);   
}
void loop() 
{ 
  
  int buffer=(minn*100)+sec;
  
  
 d1=dg[minn/10];
 d2=dg[minn%10];
 d3=dg[sec/10];
 d4=dg[sec%10];

  if(sec==60){sec=0; minn++;} 
  if(minn==60){minn=0;}  
  
  c1=millis(); // second counter
  if (c1-c2>=1000){  
  sec++; 
  c2=c1;
  }
  
  t1=millis(); // multiplexed throught A1-A4 pins
  if (t1-t2>=1){
   
    counter++;
    if(counter==5) counter=1;
     
    if (counter==1){
    digitalWrite(latchPin, LOW); 
    shiftOut(dataPin, clockPin, MSBFIRST, d1);      
    digitalWrite(A1, LOW);    
    digitalWrite(A2, HIGH); 
    digitalWrite(A3, HIGH); 
    digitalWrite(A4, HIGH);     
    digitalWrite(latchPin, HIGH);     
    }
    
    if (counter==2){
    digitalWrite(latchPin, LOW); 
    shiftOut(dataPin, clockPin, MSBFIRST, d2);      
    digitalWrite(A2, LOW);  
    digitalWrite(A1, HIGH); 
    digitalWrite(A3, HIGH); 
    digitalWrite(A4, HIGH);    
    digitalWrite(latchPin, HIGH);     
    }    
    
    if (counter==3){
    digitalWrite(latchPin, LOW); 
    shiftOut(dataPin, clockPin, MSBFIRST, d3);      
    digitalWrite(A3, LOW); 
    digitalWrite(A2, HIGH); 
    digitalWrite(A1, HIGH); 
    digitalWrite(A4, HIGH);      
    digitalWrite(latchPin, HIGH);     
    }        

    if (counter==4){
    digitalWrite(latchPin, LOW); 
    shiftOut(dataPin, clockPin, MSBFIRST, d4);      
    digitalWrite(A4, LOW);
    digitalWrite(A2, HIGH); 
    digitalWrite(A3, HIGH); 
    digitalWrite(A1, HIGH);      
    digitalWrite(latchPin, HIGH);     
    }        
        
  t2=t1;
  }
    

}

d1,d2,d3,d4 should be an array, d[4].

Hint about finding the digits - integer division discards the remainder. So 789/10 is 78. You have already found the method for determining the low digit. Put those two facts together.

Find the minutes and seconds separately and display them as two different 2 digit numbers.

Some of your digit driver writes are redundant (you are setting them HIGH when they are already HIGH).

As was indicated by another poster in another thread, you should factor your digit code because it does essentially the same thing four times. If your data is in an array (d[4]), it will be easy because you can index it.

Extra points to you for following the forum guidelines without even being asked to do so.

aarg:
d1,d2,d3,d4 should be an array, d[4].

Hint about finding the digits - integer division discards the remainder. So 789/10 is 78. You have already found the method for determining the low digit. Put those two facts together.

Find the minutes and seconds separately and display them as two different 2 digit numbers.

Some of your digit driver writes are redundant (you are setting them HIGH when they are already HIGH).

As was indicated by another poster in another thread, you should factor your digit code because it does essentially the same thing four times. If your data is in an array (d[4]), it will be easy because you can index it.

Extra points to you for following the forum guidelines without even being asked to do so.

is it possible to use sscanf fo this?

I got it working now. by adding |B10000000 to it, I can even enable the dot. Sweet!!

 d1=dg[buffer/1000]|B10000000;
 d2=dg[(buffer/100)%10] | B10000000;
 d3=dg[(buffer/10)%10]|B10000000;
 d4=dg[(buffer%10)]|B10000000;

sscanf( ) is going to deal with information in a char array or the equivalent.

Doing integer divisions by 1000 or 100 with integer results, is going to work if what you started with was a binary number, as an int or a long.

None of the code fragments you posted, show what type "buffer" is.

sscanf (buffer,"%d%d%d%d", dg1, dg2, dg3, dg4);

You didn't have a type declaration for dg1, dg2, dg3, dg4 either.

If they are ints, which your use of %d would seem to suggest, then you need to use

sscanf (buffer,"%d%d%d%d", &dg1, &dg2, &dg3, &dg4);

I am surprised that the compiler even let you compile what you wrote.

After many trials and errors .... I got a problem. how do I split a number to 4 digit? I tried sccanf, but without luck;

int buffer = 1234 ;

and

char buffer[ ] = { '1', '2', '3', '4' } ;

are two fundamentally different types of data, a distinction that many beginners have trouble comprehending.

The first one consists of two bytes containing the 16 bit binary number 0000010011010010 which is the binary number corresponding to 1234 in conventional decimal numbers.

The second one is an array of 4 single-byte characters, containing the ascii representation of the characters '1', '2', '3' and '4'.

Instead of making "many trials and errors", and expecting "luck" to solve your problem while writing random nonsense, your time might be more productively spent reading a good basic textbook or studying some online tutorials.

michinyon:

sscanf (buffer,"%d%d%d%d", dg1, dg2, dg3, dg4);

You didn't have a type declaration for dg1, dg2, dg3, dg4 either.

If they are ints, which your use of %d would seem to suggest, then you need to use

sscanf (buffer,"%d%d%d%d", &dg1, &dg2, &dg3, &dg4);

I am surprised that the compiler even let you compile what you wrote.

actually, I have used sprintf to convert the digit to char, then use sscanf (buffer,"%d%d%d%d", dg1, dg2, dg3, dg4);


it gave me errors: extern int sscanf(const char *__buf, const char *__fmt, ...); when the buffer is int;

 int buffer=(minn*100)+sec;  // turns minute and sec into 4 digit number
  sscanf (buffer,"%d%d%d%d", &dg1, &dg2, &dg3, &dg4) ;

errors on LED display when do it like this:

 char buffer[5];
  sprintf (buffer, "%02d%02d", minn, sec);
  sscanf (buffer,"%d%d%d%d", &dg1, &dg2, &dg3, &dg4) ;

michinyon:
int buffer = 1234 ;

and

char buffer[ ] = { '1', '2', '3', '4' } ;

are two fundamentally different types of data, a distinction that many beginners have trouble comprehending.

The first one consists of two bytes containing the 16 bit binary number 0000010011010010 which is the binary number corresponding to 1234 in conventional decimal numbers.

The second one is an array of 4 single-byte characters, containing the ascii representation of the characters '1', '2', '3' and '4'.

Instead of making "many trials and errors", and expecting "luck" to solve your problem while writing random nonsense, your time might be more productively spent reading a good basic textbook or studying some online tutorials.

I see. I understand the difference. then how do I convert that 4 digits int to 4 single digit int using sscanf? or is it impossible? I read the article about sscanf already: http://www.cplusplus.com/reference/cstdio/ but don't really get it.

buffer[3] = min/10; // upper minutes digit
buffer[2] = min%10;  //lower minutes digit
buffer[1] = sec/10; // upper seconds digit
buffer[0] = sec%10; // lower seconds digit

Now isn't that simpler?

if you have an int to start with, then don't use any characters at all.

int  min_and_sec = 1234 ;

int min1 = min_and_sec/1000 ;                             //  result will be the number 1
int remainder = min_and_sec - ( 1000*min1 ) ;        //  this will be an int with the value 234
int min2 = remainder/100 ;                                   //  this will be the number 2
remainder = remainder - ( min2 * 100 ) ;                //  this will be the number 34
int sec1 = remainder/10 ;                                    //  this will be the number 3
int sec2 = remainder - ( 10*sec1 ) ;                     //  this will be the number 4

how do I convert that 4 digits int to 4 single digit int using sscanf? or is it impossible?

It is possible, but stupid. This should work.

int min_and_sec = 1234 ;

char buffer[5] ;
sprintf( buffer,"%d",  min_and_sec ) ;

char c1,c2,c3,c4 ;

sscanf( buffer, "%c%c%c%c",  &c1, &c2, &c3, &c4 );

int d1,d2,d3,d4 ;
d1 = c1-'0' ;
d2 = c2-'0' ;
d3 = c3-'0' ;
d4 = c4-'0' ;

But then you would be faced with the task of converting separate minutes and seconds into a single integer, e.g.
30 minutes and 7 seconds has to become integer 3007 somehow. See my point?

You will almost certainly have to keep them separate anyway because of the rollover from 59 to 00. Why put them together just to take them apart?

The display device the OP is presumably using, required a single-digit number to be sent to each digit of the display.

So he or she doesn't need the number 3007 at all.

michinyon:
The display device the OP is presumably using, required a single-digit number to be sent to each digit of the display.

So he or she doesn't need the number 3007 at all.

Exactly my point. In the poster's scheme, the variable "buffer" does contain an integer value like that.

michinyon:
It is possible, but stupid. This should work.

int min_and_sec = 1234 ;

char buffer[5] ;
sprintf( buffer,"%d",  min_and_sec ) ;

char c1,c2,c3,c4 ;

sscanf( buffer, "%c%c%c%c",  &c1, &c2, &c3, &c4 );

int d1,d2,d3,d4 ;
d1 = c1-'0' ;
d2 = c2-'0' ;
d3 = c3-'0' ;
d4 = c4-'0' ;

sometimes I may need to use float, and need to convert float to char first, then to int.

Your code works, but sprintf( buffer,"%02d%02d", minn, sec ) gives me 0000; why is that?

 char buffer[6] ={'1','2','3','4'};
//sprintf( buffer,"%02d%02d",  minn, sec ) ;

      Serial.print(buffer);
      Serial.println();
char c1,c2,c3,c4 ;

sscanf( buffer, "%c%c%c%c",  &c1, &c2, &c3, &c4 );

int e1,e2,e3,e4 ;
e1 = c1-'0' ;
e2 = c2-'0' ;
e3 = c3-'0' ;
e4 = c4-'0' ;

d1 = dg[e1] ;
d2 = dg[e2] ;
d3 = dg[e3] ;
d4 = dg[e4] ;