Very complex C infinite loop debugging -


i want color stand alone digits, not preceded alphabetical character , terminated numeric one.

can guess why when use program write existing text file text file, several megabytes in size in seconds? there infinite loop occurring.

char ch; _bool finished = true; void color(); void skip();  int main() {     while (finished)     {         ch = getchar();         if (ch == -1) {             finished = false;         }         if ( (ch >= 'a' && ch <= 'z') || (ch >= 'a' && ch <= 'z') ) {             skip();         }         else if (ch >= '0' && ch <= '9'){             color();         }         else {             printf("%c", ch);         }     }     return 0; }  void color() // color characters numbers {     printf("\e[31m%c\e[0m", ch); }  void skip() // skip whole words , still print them {     putchar(ch);     while ((ch = getchar()) != ' ') {         printf("%c", ch);     } } 

infinite loops

the infinite loop report caused incorrect handling of eof in posted code. plain char may signed or unsigned, , may not able hold value of eof, typically -1.

the skip() function fails account possibility eof may encountered. here, if eof encountered before space, e.g., in last word of file, infinite loop result.

header files

the posted code missing header files. @ least #include <stdio.h> , #include <stdbool.h> needed. stdio.h needed obvious reasons, stdbool.h needed also, true , false macros defined. _bool type can still used, better use typedef bool defined in stdbool.h.

function declarations

empty parentheses in function prototype indicates unspecified number of arguments. void must used specify no arguments taken. usage of empty parentheses in function declarators obsolescent feature of language, , should not used anyway.

ansi escape codes

the ability print colors in c dependent upon platform , terminal emulator. tutorials use \e stand-in escape character, generate character in c should use \x1b (the ascii hexadecimal value esc character; use \033, ascii octal value esc). reading of standard \e not valid character constant, , using generates compiler warning:

warning: non-iso-standard escape sequence, '\e'

but, appear work me in gcc on linux, suspect extension.

logic problems

the skip() function fails check eof, fails print spaces when encountered. further, newline character should able precede digit, since signals line-ending. not handling correctly leads failure highlight initial digits on lines following first line of input. these problems can resolved testing eof , \n in loop condition, , printing character caused loop terminate if space or newline.

void skip(void) // skip whole words , still print them {     putchar(ch);     while ((ch = getchar()) != ' ' && ch != '\n' && ch != eof) {         printf("%c", ch);     }     if (ch == ' ' || ch == '\n') {         putchar(ch);     } } 

there similar problem in main(). when eof encountered in main loop, final printf() still executed, printing character when none should printed. 1 solution place statements after eof test in else block, though there better solutions.

while (finished) {     ch = getchar();     if (ch == eof) {   // use eof instead of -1         finished = false;     } else {           // need avoid printing character eof         if ( (ch >= 'a' && ch <= 'z') || (ch >= 'a' && ch <= 'z') ) {             skip();         } else if (ch >= '0' && ch <= '9') {             color();         }         else {             printf("%c", ch);         }     } } 

here program far. works expected, far can tell description of expected behavior:

#include <stdio.h> #include <stdbool.h>  int ch; bool finished = true;  void color(void); void skip(void);  int main(void) {     while (finished)     {         ch = getchar();         if (ch == eof) {             finished = false;         } else {             if ( (ch >= 'a' && ch <= 'z') || (ch >= 'a' && ch <= 'z') ) {                 skip();             } else if (ch >= '0' && ch <= '9') {                 color();             }             else {                 printf("%c", ch);             }         }     }     return 0; }  void color(void) // color characters numbers {     printf("\x1b[31m%c\x1b[0m", ch); }  void skip(void) // skip whole words , still print them {     putchar(ch);     while ((ch = getchar()) != ' ' && ch != '\n' && ch != eof) {         printf("%c", ch);     }     if (ch == ' ' || ch == '\n') {         putchar(ch);     } } 

improvements

there number of improvements can made code.

there no need bool @ all. break statement terminate main loop when eof encountered. in case, main loop need execute indefinitely, while (1) {}, or better, for (;;) {}. better, test ch in loop condition while ((ch = getchar()) != eof) {}.

having removed global variable finished, can make ch local main(). may require passing value of ch both color() , skip(), in case function signatures need changed. but, note there no reason pass character skip(), since character can printed in main() before calling skip(). further, there no need color() function, since one-line function manually inlined.

there no need use printf() putchar() do.

it nice #define couple of escape code macros. easier read, , easier modify.

finally, better use functions in ctype.h check whether character digit, or alphabetic character, or whitespace character. more portable, , less error-prone, direct comparisons in posted code. using isspace() in skip() function, \n character automatically checked for, avoiding earlier issue forgetting test line-endings. handles other whitespace characters, such \t. note functions in ctype.h expect arguments can represented unsigned char values, cast needed here.

here improved code:

#include <stdio.h> #include <ctype.h>  #define red    "\x1b[31m" #define reset  "\x1b[0m"  void skip(void);  int main(void) {     int ch;     while ((ch = getchar()) != eof) {         if (isalpha((unsigned char) ch)) {             putchar(ch);             skip();         } else if (isdigit((unsigned char) ch)) {             printf(red "%c" reset, ch);         } else {             putchar(ch);         }     }     return 0; }  void skip(void) // skip whole words , still print them {     int c = getchar();     while (!isspace((unsigned char) c) && c != eof) {         putchar(c);         c = getchar();     }     if (isspace((unsigned char) c)) {         putchar(c);     } } 

here sample program output. colors don't show here, have put parentheses around numbers highlighted in red on terminal:

(1) test testing123 (456) test (2) second line test (3) (4) (5) (3)rd line test (4) (5) (6) (789) 

Comments

Popular posts from this blog

angular - Ionic slides - dynamically add slides before and after -

minify - Minimizing css files -

Add a dynamic header in angular 2 http provider -