scanf() cookbook

I have been thinking scanf() awkward because I tried to understand scanf() as opposite to printf(). That was wrong in many ways.

  • In scanf() format, a space is not necessary between two “%<conversion>”s. For example, format “%d%d” matches input “100 200”.
  • In scanf() format, a space matches any number of any white space characters, such as tab and newline. For example, format “%d %d” matches input “100\n200”, format “%d\n%d” matches input “100 200”.

Once I learned that, scanf() started working as I expect. Here is some howto.

How to read data over newline:

 input:
 100
 200
 program:
 scanf("%d%d", &i1, &i2);
 printf("%d %d\n", i1, i2);
 output:
 100 200

scanf() does not care about the notion of line. “\n” is just one of the
white space character.

How to read data with leading white space:

 input:
  100
   200
 program:
 scanf("%d%d", &i1, &i2);
 printf("%d %d\n", i1, i2);
 output:
 100 200

“%<conversion>” skips the leading spaces.

In C++, istream (such as cin) skips the leading spaces in the same way.

How to skip until end of line:

 input:
 100 101 102
 200 201 202
 program:
 scanf("%d%*[^\n]", &i1);
 scanf("%d%*[^\n]", &i2);
 printf("%d %d\n", i1, i2);
 output:
 100 200

“%*” throws away the matched string.

 another way:
 scanf("%d", &i1);
 while (getchar() != '\n');
 scanf("%d", &i2);

How to read various floating numbers:

 input:
 1 0.1 1e-2
 program:
 scanf("%f%f%f", &f1, &f2, &f3);
 printf("%f %f %f\n", f1, f2, f3);
 output:
 1.000000 0.100000 0.010000

“%f” can read many formats.

How to skip lines that begins with comment character:

 input:
 # This is a comment.
   # This is a comment.
     # This is a comment.
 string-data
 program:
 while (scanf(" #%[^\n]", s));
 scanf("%s", s);
 printf("%s\n", s);
 output:
 string-data

” ” before “#%[^\n]” matches zero or more spaces.
If ” #%[^\n]” doesn’t match, no input is consumed.

Working with slow machine

We programmer have to wait for the response from the machine. When the machine is slow, such as, slow simulation or long compilation, it disturbes our rhythm.

During the waiting time, I tend to think what to do next, but most of the time I just wish the compilation ends sooner. Wishing is not my job, and know that I’m not doing right. Knowing that makes me stressed up.

So first thing I do is to stop seeing the progress. By looking at the scrolling screen,
I tend to go into wish mode, or spend time looking for warnings in the scrolling screen.

Unless you are like a chess master, you can prepare only one step ahead. Preparing two steps ahead takes more effort and sometimes turn out to be wrong.

So I do something else instead; the best thing is something unrelated, such as unrelated reading or short stretching. Sounds inefficient? But I found that I tend to accomplish more than I expect at the end of the day, and I get less stressed.

Title roll

In a movie, names of the important actors are shown at the beginning because knowing important actors helps the audience to appreciate the movie. Minor actors are not listed there because they don’t matter. The same thing applies to the local variables: You should list up the variables of important role at the beginning of the function to help readers of the function to understand it easier. And minor variables should not be listed here. For example,

    void search(.....) {
        int first;
        int last;  
        int mid;    
    .....
    }

Having those variables in mind (with appropriate names, please) helps to read the function. Sometimes knowing those variables makes the rest of the function even obvious.

One exception: In C, casual iterators may have to be listed at the top. This is due to the flaw of this language. However, I sometimes do something like this to avoid listing ‘i’ in the local variable list.

    {
        int i;
        for (i = 0; i < .....) .....
    }

Or

    { int i; for (i = 0; i < .....) {
          .....
    }}

In this way, the part of the program becomes independent, allowing you to cut and paste anywhere.

You can safely ignore

It sounds like professional way, probably because of the word “safely”.

– You can safely ignore the warnings.
– You can safely ignore the obsolete comments.
– You can safely ignore this part of the code which never executed.

Saying such is one of those amateur attitude. If there is something that can be really safely ignored, just remove it before showing to other people.

Best bringup tool

When I bring up a bare board, I have to fight without OS or libraries, or sometimes even without RAM. Most conservative solution in such case is ICE. But I do not like it because

– ICE is expensive.
– ICE is no use once debug monitor is up.
– ICE is usually hairy and buggy.

I use simple print to the serial I/O console because, to me, the most important information is where the program is and its status. In the boot code, the first thing I do is to initialize the serial I/O, and print at least one character, which shows the board got out of reset and started fetching instructions.

The boot code goes like this:

    #include "mydebug.h"

    // Initialize serial I/O.
    la         t0, SIO_BASE
    li         t1, .....        // baud rate, enable, etc.
    li         t2, .....
    sw         t1, PARAM1(t0)
    sw         t2, PARAM2(t0)

    // Show the first message.
    la         t0, SIO_TXFIFO
    li         t1, 'H'
    sw         t1, (t0)
    li         t1, 'i'
    sw         t1, (t0)
    li         t1, 0x0d
    sw         t1, (t0)
    li         t1, 0x0a
    sw         t1, (t0)

    // Test mydebug functions.
    MYPRINTS("MYPRINTS: Hello world.\r\n")
    MYPRINTS("MYPRINTD: ")
    MYPRINTD(1234567890)
    MYCRLF()
    MYMARKER()

The output looks like this:

    Hi
    MYPRINTS: Hello world.
    MYPRINTD: 1234567890
    [reset.S:32]

The last line is from MYMARKER() macro, which I think most useful.

Once the program jumps to C, I can use a bit better ones.

    #include "mydebug.h"

    int main()
    {
    MYPRINTS("MYPRINTS: Hello from C.\r\n");
    MYPRINTS("MYPRINTD: ")
    MYPRINTD(1234567890)
    MYCRLF()
    MYMARKER()
    }

The output looks like this:

    MYPRINTS: Hello from C.
    MYPRINTD: 1234567890
    [main.c:52 main()]

Here is mydebug.h. Use it at your own risk.

        //
        // For assembler program.
        //
        #ifdef __ASSEMBLER__

        #define MYPRINTC(C)                                             \
                li      t0, SIO_TXFIFO                                  \
                li      t1, C;                                          \
                sw      t1, (t0);                                       \

        #define MYCRLF()                                                \
                MYPRINTC(0x0d);                                         \
                MYPRINTC(0x0a)

        #define MYPRINTS(S)                                             \
                b       1111f;                                          \
                nop;                                                    \
        8888:   .asciz  S;                                              \
                .align  2;                                              \
        1111:   la      t2, 8888b;                                      \
                la      t0, SIO_TXFIFO                                  \
        2222:   lb      t1, (t2);                                       \
                beqz    t1, 9999f;                                      \
                nop;                                                    \
                sw      t1, (t0);                                       \
                addi    t2, 1;                                          \
                b       2222b;                                          \
                nop;                                                    \
        9999:   

        #define MYPRINTD(V)                                             \
                li      t0, SIO_TXFIFO                                  \
                li      t2, V           /* value */;                    \
                li      t3, 1000000000  /* divisor */;                  \
                li      t4, 10;                                         \
                li      t5, 1;          /* leading zero flag */;        \
        1111:   divu    t2, t3;                                         \
                mflo    t1              /* digit */;                    \
                mfhi    t2              /* mod */;                      \
                beqz    t5, 3333f;                                      \
                nop;                                                    \
                beqz    t1, 2222f;                                      \
                nop;                                                    \
                move    t5, zero;                                       \
        3333:   addi    t1, '0';                                        \
                sw      t1, (t0);                                       \
        2222:   divu    t3, t4;                                         \
                mflo    t3;                                             \
                bnez    t3, 1111b;                                      \
                nop

        #define MYMARKER()                                              \
                MYPRINTC('[');                                          \
                MYPRINTS(__FILE__);                                     \
                MYPRINTC(':');                                          \
                MYPRINTD(__LINE__);                                     \
                MYPRINTC(']');                                          \
                MYCRLF()

        //
        // For C program.
        //
        #else // #ifdef __ASSEMBLER__

        #define MYPRINTC(C) {                                                   \
            *(volatile unsigned int*)SIO_TXFIFO = C;                            \
        }
        #define MYPRINTD(V) {                                                   \
            char buf[20];                                                       \
            int n = 0;                                                          \
            unsigned int val = (V);                                             \
            do {                                                                \
                unsigned int digit = val % 10;                                  \
                buf[n++] = '0' + digit;                                         \
                val /= 10;                                                      \
            } while (val);                                                      \
            while (n > 0) MYPRINTC(buf[--n]);                                   \
        }
        #define MYPRINTS(S) {                                                   \
            const char* p = S;                                                  \
            while (*p) MYPRINTC(*p++);                                          \
        }
        #define MYMARKER() {                                                    \
                MYPRINTS("[");                                                  \
                MYPRINTS(__FILE__);                                             \
                MYPRINTS(":");                                                  \
                MYPRINTD(__LINE__);                                             \
                MYPRINTS(" ");                                                  \
                MYPRINTS(__PRETTY_FUNCTION__);                                  \
                MYPRINTS("()]\r\n");                                            \
        }

        #endif // #ifdef __ASSEMBLER__

Binary search if cause is far away

I talked about debugging as binary search.

What if the problem is caused far away, and the symptom shows up later? For example, in the following example, suppose function1() inadvertently writes beyond the end of buffer[] and breaks the value of globalp.

    char buffer[128];
    char* globalp;
    function1() { ... }
    function2() { ... }

Later the other function2() uses globalp and goes south. This type of bug is one of the hardest to find. First, the OK-NG chart goes likes this:

    --OK----------------------------------------------NG---------
                |<--function1-->|             |<--function2-->|

There are two reasons why this type of buf is hard. By knowing the nature of the hardness, we may be able to better handle the bug.

The first reason is the OK point. We don’t know when the OK condition is disturbed. So we cannot start the binary search yet.

The second reason is the NG point. In this case the NG point is not where the real bug is. Instead, it is where the symptom appears, such as segmentation fault. But because it is the only reference point, we have to treat it as an initial NG point, and we should not forget that the real bug is not there.

First, we have to look into the NG point closely and see what is causing the symptom, such as segmentation fault. Once we find that globalp is pointing wrong place, we can rewrite the OK-NG chart.

    --OK----------------------------------------------NG---------
                |<--function1-->|             |<--function2-->|

The chart looks exactly same as before. But it has different meaning. NG is where globalp is pointing wrong place. OK is where globalp is sane. Now we can start the bianry search just by looking at the value of globalp.

The important thing is, when you draw the first OK-NG chart in your mind, you should know that it is only temporary. And you should do what ever to take you to the second OK-NG chart.

The last element may not be it

I talked about debugging as binary search in
https://droid7c2.wordpress.com/2009/02/10/debugging-as-binary-searchdebugging-as-binary-search/

The bug was the kind which lives in time axis, on which we performed binary search.  This time, I would like to talk about a bug that lives in space. And in this case, we cannot do binary search.

Suppose you got a new USB device. You attached to your PC, and the device didn’t work.

    PC --- USBdevice

Probably you start to brame the USB device. If you have purchased the device
you may call the customer service. If you have built the device, you might start to debug the device. And this is a typical way to waste time.

In fact, there are two cases you have to look into fairly.

    PC --- USBdevice

            |
            V

    PC  --- USBdevice2
    PC2 --- USBdevice

My point is to swap an element at a time to get OK case. You try to (1) swap USBdevice with the second one, or (2) swap PC with the second one.
You may not have the second USB device, then you cannot do (1). But if you
have the second PC, (2) is easy to do. You should look at those possibilities equally to get OK point.

But is this all? No. If you see the setup in the following way, you may want to swap USB cable, too. By the way, this really happened to me. After tweaking USB device quite a while, I found the bad was the USB cable.

    PC --- USBcable --- USBdevice

And that is not the end. For example,

    PC --- USBdriver --- USBcable --- USBdevice
                                          |
                                      ACadapter

Because there are so many elements are involved, binary search is not suitable for this kind of debugging. I usually swap one element at a time.  However, one rule is still valid. Get OK and NG cases first.

How to move maximized window

I wanted to write JFrame that maximizes only horizontally, and move it up and down by using mouse drag.

Here is the initial version.

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

class MaxMove1 extends JFrame 
    implements WindowListener, WindowStateListener,
           MouseListener, MouseMotionListener
{
    static final int W = 200;
    static final int H = 100;

    private Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
    private Point startPoint;

    // WindowListener.
    public void windowClosing(WindowEvent e) {}
    public void windowStateChanged(WindowEvent e) {}
    public void windowActivated(WindowEvent e) {}
    public void windowDeactivated(WindowEvent e) {}
    public void windowIconified(WindowEvent e) {}
    public void windowDeiconified(WindowEvent e) {}
    public void windowOpened(WindowEvent e) {}
    public void windowClosed(WindowEvent e) {}

    // MouseListener.
    public void mousePressed(MouseEvent me) {
    startPoint = me.getPoint();
    }
    public void mouseReleased(MouseEvent me) {}
    public void mouseDragged(MouseEvent me) {
    Point loc = getLocation();
    int xx = loc.x + me.getX() - startPoint.x;
    int yy = loc.y + me.getY() - startPoint.y;
    if (getExtendedState() != NORMAL) xx = 0;
    setLocation(xx, yy);
    setMaximizedBounds(new Rectangle(0, yy, screen.width, H));
    }
    public void mouseMoved(MouseEvent me) {}
    public void mouseClicked(MouseEvent me) {}
    public void mouseEntered(MouseEvent me) {}
    public void mouseExited(MouseEvent me) {}

    // Appearance.
    class MyCanvas extends JComponent {
    public void paint(Graphics g) {
        g.setColor(Color.gray);
        g.fillRect(0, 0, getWidth(), getHeight());
    }
    }

    // Main program.
    public MaxMove1(){
    JComponent canvas = new MyCanvas();
    canvas.setVisible(true);
    add(canvas);

    addWindowListener(this);
    addWindowStateListener(this);
    addMouseListener(this);
    addMouseMotionListener(this);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    setSize(W, H);
    setMaximizedBounds(new Rectangle(0, 0, screen.width, H));
    setUndecorated(true);
    setVisible(true);
    }

    public static void main(String[] args) {
    new MaxMove1();
    }
}import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

class MaxMove1 extends JFrame 
    implements WindowListener, WindowStateListener,
           MouseListener, MouseMotionListener
{
    static final int W = 200;
    static final int H = 100;

    private Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
    private Point startPoint;

    // WindowListener.
    public void windowClosing(WindowEvent e) {}
    public void windowStateChanged(WindowEvent e) {}
    public void windowActivated(WindowEvent e) {}
    public void windowDeactivated(WindowEvent e) {}
    public void windowIconified(WindowEvent e) {}
    public void windowDeiconified(WindowEvent e) {}
    public void windowOpened(WindowEvent e) {}
    public void windowClosed(WindowEvent e) {}

    // MouseListener.
    public void mousePressed(MouseEvent me) {
    startPoint = me.getPoint();
    }
    public void mouseReleased(MouseEvent me) {}
    public void mouseDragged(MouseEvent me) {
    Point loc = getLocation();
    int xx = loc.x + me.getX() - startPoint.x;
    int yy = loc.y + me.getY() - startPoint.y;
    if (getExtendedState() != NORMAL) xx = 0;
    setLocation(xx, yy);
    setMaximizedBounds(new Rectangle(0, yy, screen.width, H));
    }
    public void mouseMoved(MouseEvent me) {}
    public void mouseClicked(MouseEvent me) {}
    public void mouseEntered(MouseEvent me) {}
    public void mouseExited(MouseEvent me) {}

    // Appearance.
    class MyCanvas extends JComponent {
    public void paint(Graphics g) {
        g.setColor(Color.gray);
        g.fillRect(0, 0, getWidth(), getHeight());
    }
    }

    // Main program.
    public MaxMove1(){
    JComponent canvas = new MyCanvas();
    canvas.setVisible(true);
    add(canvas);

    addWindowListener(this);
    addWindowStateListener(this);
    addMouseListener(this);
    addMouseMotionListener(this);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    setSize(W, H);
    setMaximizedBounds(new Rectangle(0, 0, screen.width, H));
    setUndecorated(true);
    setVisible(true);
    }

    public static void main(String[] args) {
    new MaxMove1();
    }
}

Try this:
– Drag by mouse.
– Maximize by using task bar menu.
– Restore by using task bar menu.
– Maximize again by using task bar menu.
– Drag by mouse. Nicely goes up and down.
– Restore by using task bar menu. (Oops.)

The problem is setLocation(). By doing this Windows is told that the Frame is not maximized any more. But Java still thinks it is maximized. Probably I went into a glitch on the spec or imprementation.

So I should avoid setLocation() when Frame is maximized, and I am probably supposed to use setMaximizedBounds() to tell where the Frame should go. setMaximizedBounds() doesn’t move Frame until the Frame is maximized again. I don’t want to perform Restore/Maximize combo because it may show a flicker.

So I decided as follows:

– Use setLocation() even if maximized.
– Remember the maximized state when I start dragging.
– Keep the non-maximized location in Frame.
– When the mouse is released, I restore the condition.
– When the Frame is un-maximized, I restore the condition.

Here is the final version:

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

class MaxMove2 extends JFrame 
    implements WindowListener, WindowStateListener,
           MouseListener, MouseMotionListener
{
    static final int W = 200;
    static final int H = 100;

    private Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
    private Point startPoint;
    private boolean startMaximized;
    private boolean dragged = false;
    private int x = 0;
    private int y = 0;
    private int w = W;
    private int h = H;

    // WindowListener.
    public void windowClosing(WindowEvent e) {}
    public void windowStateChanged(WindowEvent e) {
    if (e.getNewState() == NORMAL) {
        setLocation(x, y);
        setSize(w, h);
    }
    }
    public void windowActivated(WindowEvent e) {}
    public void windowDeactivated(WindowEvent e) {}
    public void windowIconified(WindowEvent e) {}
    public void windowDeiconified(WindowEvent e) {}
    public void windowOpened(WindowEvent e) {}
    public void windowClosed(WindowEvent e) {}

    // MouseListener.
    public void mousePressed(MouseEvent me) {
    startPoint = me.getPoint();
    startMaximized = (getExtendedState() != NORMAL);
    }
    public void mouseReleased(MouseEvent me) {
    if (startMaximized && dragged) {
        setExtendedState(NORMAL);
        setExtendedState(MAXIMIZED_BOTH);
    }
    dragged = false;
    }
    public void mouseDragged(MouseEvent me) {
    Point loc = getLocation();
    int xx = loc.x + me.getX() - startPoint.x;
    int yy = loc.y + me.getY() - startPoint.y;
    setLocation((getExtendedState() == NORMAL)? xx : 0, yy);
    setMaximizedBounds(new Rectangle(0, yy, screen.width, H));

    if (! startMaximized) x = xx;
    y = yy;
    dragged = true;
    }
    public void mouseMoved(MouseEvent me) {}
    public void mouseClicked(MouseEvent me) {}
    public void mouseEntered(MouseEvent me) {}
    public void mouseExited(MouseEvent me) {}

    // Appearance.
    class MyCanvas extends JComponent {
    public void paint(Graphics g) {
        g.setColor(Color.gray);
        g.fillRect(0, 0, getWidth(), getHeight());
    }
    }

    // Main program.
    public MaxMove2(){
    JComponent canvas = new MyCanvas();
    canvas.setVisible(true);
    add(canvas);

    addWindowListener(this);
    addWindowStateListener(this);
    addMouseListener(this);
    addMouseMotionListener(this);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    setLocation(x, y);
    setSize(w, h);
    setMaximizedBounds(new Rectangle(0, 0, screen.width, H));
    setUndecorated(true);
    setVisible(true);
    }

    public static void main(String[] args) {
    new MaxMove2();
    }
}

I had to do Restore/Maximize combo when the Frame is un-maximized. But it doesn’t cause flicker because the window is same as maximized size before the operation.

This is always the way when I program in Java: I find shortcomings or glitches in the spec or implementation, then I have to move the wrinkle caused by the glitch around to fit some place where it doesn’t matter.

Note with outline mode

Suppose your boss asks the result of the experiment performed about one year ago. Can you give him an answer within 10 minutes? – I can.

The reason is I have a note, which is written in plain text and saved in one giant file: ~/Note. The file is written in Emacs outline mode.

* 2/6 flash problem…
* 2/6 OHCI bringup note…
* 2/5 todo for project X…

Each section can be anything: a report, program snippet, session log, or even a memo of random thoughts. My rule is like this:

– Anything can be in ~/Note.
– Write a short section title with a date.
– It is OK to be dirty in a section.
– No memo should not be saved in other places.

Then whenever I want to remember something, I know that’s in ~/Note. And I can grep through it.

I don’t write on a paper because the power of paper notebook is too short for what we are doing. When I have to write on a paper, I type it later in ~/Note.

Binary serarch for two step bug

I talked about debugging as binary search in
https://droid7c2.wordpress.com/2009/02/10/debugging-as-binary-searchdebugging-as-binary-search/

What if the problem happens in two steps. For example, if your program goes south by performing action1 first, then action2?

The OK-NG chart would be like this.

    ----------OK------------------------------------- NG---------
                |<--action1-->|                |<--action2-->|

Now you have to divide this into two. One for looking into action1.

    -----------------------------------------OK------ NG---------
                |<--action1-->|                |<--action2-->|

We know that “OK” here is not actually OK because something is already caused by performing action1. But for the sake of binary search, we call it OK. Then you divide between OK and NG until you find what was really NG in action 2.

And the other for action2. This time you do not touch action 2, and look into action 1. We know that things were OK before action 1, and NG after action 1. You reduce the amount of code in action 1, and see when the symptom seen in action 2 happens or not.

    ----------OK---------------NG-------------------- NG---------
                |<--action1-->|                |<--action2-->|

You can start digging in either one of those two. However, do not forget that you have two OK-NG chart now. Otherwise, you might forget the other one and waste time.