HiveBrain v1.2.0
Get Started
← Back to all entries
snippetcMinor

Filter leading zeroes from numbers using only character operations for input and output

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
leadingoperationsnumbersandcharacteroutputinputfilterusingfor

Problem

Problem: to eliminate initial zeroes from numbers besides those followed by '.' or alone. For example if we input a-000123+bc+0000.0008-0000+0001.07 , we will get a-123+bc+0.0008-0+1.07).

Using putchar and getchar only. No strings and pointers involved. I have working code, but I think it's confusing and overloaded. Can someone suggest how it might be simplified or an easier algorithm?

char curr_char = 0, prev_char = 0,flag=0;
while ((curr_char = getchar()) != '&')
{

    if (isdigit(curr_char) && !(isdigit(prev_char))) 
        flag = 1;
    if (flag)
    {
        while (true)
        {
            if (curr_char=='0'); else break; 
            curr_char = getchar(); 
        }

        if (curr_char == '.')putchar('0'); 

        while (true) 
        {
            if (isdigit(curr_char))putchar(curr_char); else break;
            curr_char = getchar(); 
        }

        if (curr_char == '.') 
        {
            putchar('.'); 
            while (isdigit(curr_char = getchar()))putchar(curr_char);
        }
        flag = 0;
    }
    else putchar(curr_char);
    prev_char = curr_char;
}

Solution

I see a number of things that could be improved here.

Include the appropriate headers

The code as posted is just a fragment, but only a few additional lines would make it into a complete program. It's usually best to provide a complete program for review. With that said, the missing headers are these:

#include 
#include 
#include 
#include 


Check for EOF

The code currently looks for the & character, but that's not in the specification. It would probably make more sense to look for the end of file which is EOF.

Restructure your code

Any time you find yourself writing while (true) and then putting a conditional break within the loop, this should be a strong indication that something is not quite right. Also, lines like this:

if (curr_char=='0'); else break;


are really quite awful. That could easily have been written instead as:

if (curr_char != '0')
    break;


which makes it much easier to understand. Even better would have been to write the loop as:

while (cur_char != '0') 
    curr_char = getchar();


Eliminate unneeded variables

The code defines curr_char, prev_char and flag but it's possible to rework the algorithm to eliminate at least one of these. Also, curr_char and prev_char are good names, but flag is not. It's entirely too generic and doesn't say what it's intended to flag.

Fix your algorithm

If we feed a03+0.0g to this code, it should print a3+0.0g but what it actually prints is a30.0 which is clearly not correct. Part of the problem here is that the implementation of the algorithm is quite convoluted and difficult to follow. For that reason, I would recommend a different approach.

Start with a state machine

Starting with a state machine is a very good way to work out what a program should do in advance of writing any code. Having a design first and then writing code is essential to good programming practice. For example, this state machine can be easily implemented in code. I used an enum to represent the state and then a switch statement to drive the code. In it, each transition is labelled as condition/action.

As an example of how to code this, here's the first part of the code including the code for the nonNum state:

int main() 
{
    enum { nonNum, inInt, inDec, zeroSupp } state = nonNum;
    int ch;
    while ((ch = getchar()) != EOF) {
        switch (state) {
            case nonNum:
                if (ch == '0') {
                    state = zeroSupp;
                } else if (ch > '0' && ch <= '9') {
                    state = inInt;
                    putchar(ch);
                } else {
                    putchar(ch);
                }
                break;
      /* the rest of the state machine goes here */

Code Snippets

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <stdbool.h>
if (curr_char=='0'); else break;
if (curr_char != '0')
    break;
while (cur_char != '0') 
    curr_char = getchar();
int main() 
{
    enum { nonNum, inInt, inDec, zeroSupp } state = nonNum;
    int ch;
    while ((ch = getchar()) != EOF) {
        switch (state) {
            case nonNum:
                if (ch == '0') {
                    state = zeroSupp;
                } else if (ch > '0' && ch <= '9') {
                    state = inInt;
                    putchar(ch);
                } else {
                    putchar(ch);
                }
                break;
      /* the rest of the state machine goes here */

Context

StackExchange Code Review Q#73595, answer score: 7

Revisions (0)

No revisions yet.