/** * numbers.c - A simple program for extracting the numbers from an input file. * Each number is printed on a separate line. */ // +--------+---------------------------------------------------------- // | Design | // +--------+ /* In essence, there are four possible "states" of the program. We can be * outside of a number, * in the portion of a number before the decimal point, * at the decimal point, * after the decimal point, but still in the number. Our action at each character is therefore a simple decision based on the kind of character (digit, decimal, other) and the current state. * (outside,digit) => print; state = before * (outside,point) => ignore * (outside,other) => ignore * (before,digit) => print * (before,point) => state = decimal * (before,other) => "ended the number" print a newline; state=outside * (decimal,digit) => "there's something after the decimal point" print the decimal point; preinct the digit; state = after * (decimal,point) => "the decimal point was meaningless"; print newline; state=outside * (decimal,other) => "the decimal point was meaningless"; print newline; state=outside * (after,digit) => print * (after,point) => "ended the number" print a newline; state=outside * (after,other) => "ended the number" print a newline; state=outside We can represent the states with constants (as in the example in K&R) or as an enum (which Gnu Coding Guidelines suggest). We can determine the type of a character using isdigit. */ // +---------+--------------------------------------------------------- // | Headers | // +---------+ #include // For printf, getchar, and such #include // For isdigit() // +-------+----------------------------------------------------------- // | Types | // +-------+ /** * The states of our program. */ enum state { OUTSIDE, BEFORE, DECIMAL, AFTER }; // +------+------------------------------------------------------------ // | Main | // +------+ int main () { int ch; // The input character enum state state; // The state of the program // Initially, we seem to be outside a number. state = OUTSIDE; // Repeatedly read a character and process. while ((ch = getchar ()) != EOF) { // Handle digits if (isdigit (ch)) { // Update the state if (state == DECIMAL) { printf("."); state = AFTER; } // if (state == DECIMAL) else if (state == OUTSIDE) state = BEFORE; // Print the character printf("%c", ch); } // if it's a digit // Handle decimal points else if (ch == '.') { if (state == BEFORE) state = DECIMAL; else if (state != OUTSIDE) { state = OUTSIDE; printf ("\n"); } } // if it's a decimal point // Handle everything else else { if (state != OUTSIDE) { state = OUTSIDE; printf ("\n"); } } // everything else } // while // On the slight chance that we ended in the middle of a line, make // sure that we don't have a newline left to print if (state != OUTSIDE) printf ("\n"); // And we're done return 0; } // main