C program that removes comments - c

This was my first time posting so i apologize for poor format and or any unreasonable questions.
So i have been working on the "remove comments" program for some time and made progress but very minimal. I am new to C so I'm writing it using some basic functions and skills. The input file for the code does not require any functions to be read but instead is passed to the program using < in the terminal.
The text file that I'm using contains the following:
some/* crazy */stuff
some/* crazy */ stuff
some/*crazy /*crazy*/*/stuff
"some /* crazy */ stuff "
some/* "crazy" */ stuff
some/* crazy stuff
To test the different comment formats.
The code i have so far is:
#include <stdio.h>
#define IN_COMMENT 1
int main(int argc, char **argv)
{
int c;
while ((c=getchar())!=EOF)
{
if(c=='/'&&getchar()=='*')
{
while(c!='*' && getchar()!='/')
{
c = " ";
c= getchar();
}
}
if(c=='"')
{
c=getchar();
while(c!='"')
{
putchar(c);
c=getchar();
}
putchar(c);
}
}
putchar(c);
printf("done.\n");
return 0;
}
The thing is that i cannot figure out a way to set up a condition that would print out an error message when there is a case in which the comment is started but never closed, such as (some/* crazy stuff)
Another problem is that i cant seem to find the bug which when i run my program and input the text file omits the *, so when i input :
some/* crazy */stuff
some/* crazy */ stuff
some/*crazy /*crazy*/*/stuff
"some /* crazy */ stuff "
some/* "crazy" */ stuff
i end up getting the following:
some*stuff
some* stuff
some**/tuff
"some /* crazy */ stuff "
some* stuff
I cant figure out a way to fix the two issues. The professor suggested a different way of writing the program by defining different states, but when i tried that it was even more confusing.

Your description is focusing on the difference between operating on a stream and operating on a buffer. In both C and Java either technique is possible.
Here your task is to do the job in a stream situation, i.e. you cannot "look ahead" and you cannot "write backwards" - all you can do is retrieve the next character, update some variables if appropriate, and decide whether or not to output that character.
This is called a state machine; your main loop will read a character and then take different action based on what state your variables were in.
To get you started, you're going to need to store at least the following:
whether you are in a comment or not
If you're not in a comment, then whether you just read a /.
For example, if the latter state is set and you get a '*' then you would set the former state (and reset the latter).

Well, usual solution to this kind of problem is to make FSM. So, just make number of states and deаfine how each next letter will affect state, due to current state. Smth like
//#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
//#include <conio.h>
#include <string.h>
typedef enum states {
CODE,
HASH_START,
STAR_END,
COMMENT
} states;
void main() {
FILE *input = NULL;
char c;
states state;
state = CODE;
input = fopen("C:/c/code.txt", "r");
if (input == NULL) {
exit(EXIT_FAILURE);
}
while (fscanf(input, "%c", &c) == 1) {
switch (c) {
case '/' :
switch (state) {
case CODE:
state = HASH_START;
break;
case STAR_END:
//a bit ugly here, but require less states. You can omit read next
//if use more states
fscanf(input, "%c", &c);
state = CODE;
break;
}
break;
case '*' :
switch (state) {
case HASH_START:
state = COMMENT;
break;
case COMMENT:
state = STAR_END;
break;
}
break;
default:
if (state == HASH_START) {
state = CODE;
}
}
if (state == CODE) {
printf("%c", c);
}
}
//_getch();
}
this code deletes only /**/. Write bigger diagram and complete code.

#include <stdio.h>
#if 0
Description :
To delete a comment by entering the C source from standard input.
// To delete a line break up (newline remain)
/**/ To allow the nest (standard does not allow)
also replaced with a single space(The request by the standard)
#endif
int main(void){
FILE *fp = stdin;
int ch, chn;
int nest_level=0;
#if 0
in_range_comment : /* this */
in_line_comment : //this
in_string : "this"
in_char_constnt : ' '
#endif
enum { none, in_line_comment, in_range_comment, in_string, in_char_constant } status;
status = none;
while(EOF!=(ch=fgetc(fp))){
switch(status){
case in_line_comment :
if(ch == '\n'){
status = none;
putchar(ch);
}
continue;
case in_range_comment :
if(ch == '*'){
chn = fgetc(fp);
if(chn == '/'){
if(--nest_level == 0){
status = none;
putchar(' ');
}
continue;
}
ungetc(chn, fp);
} else if(ch == '/'){
chn = fgetc(fp);
if(chn == '*'){
++nest_level;
continue;
}
ungetc(chn, fp);
}
continue;
case in_string :
if(ch == '\\'){
putchar(ch);
chn = fgetc(fp);
if(chn == '"'){
putchar(chn);
continue;
}
ungetc(chn, fp);
} else {
if(ch == '"')
status = none;
putchar(ch);
}
continue;
case in_char_constant :
if(ch == '\\'){
putchar(ch);
chn = fgetc(fp);
if(chn == '\''){
putchar(chn);
continue;
}
ungetc(chn, fp);
} else {
if(ch == '\'')
status = none;
putchar(ch);
}
continue;
case none :
switch(ch){
case '/':
if('/' == (chn = fgetc(fp))){
status = in_line_comment;
continue;
} else if('*' == chn){
status = in_range_comment;
++nest_level;
continue;
} else
ungetc(chn, fp);
putchar(ch);
break;
case '"':
status = in_string;
putchar(ch);
break;
case '\'':
status = in_char_constant;
putchar(ch);
break;
default:
putchar(ch);
}
}
}
return 0;
}

Related

Condition is always true. Bug in my code, or bug in my IDE?

I've been doing some exercises from the "The C Programming language" (second edition), and I'm at 1-23, where you need to develop a program that strips out the comments.
This what I have so far:
#include <stdio.h>
#define CODE 0
#define START_COMMENT 1
#define END_COMMENT 2
#define COMMENT 3
#define INQUOTE 4
/* this is a test */
/* this is a *** comment maybe / but still testing */
main() {
char c;
char state=CODE;
while ((c = getchar()) != EOF) {
if(state == CODE) {
if (c == '/') {
state = START_COMMENT; /* this works? */
}
else if (c == '"' || c == '\'') {
state = INQUOTE;
putchar(c);
}
else {
putchar(c);
}
}
else if(state == INQUOTE) {
if (c == '"' || c == '\'') {
state = CODE;
putchar(c);
}
else {
putchar(c);
}
}
else if(state == START_COMMENT) {
if (c == '*') {
state = COMMENT;
}
else {
putchar('/');
putchar(c);
state = CODE;
}
}
else if(state == COMMENT) {
if (c == '*') {
state = END_COMMENT;
}
}
else if(state == END_COMMENT) {
if (c == '/') {
state = CODE;
}
else
state = COMMENT;
}
}
}
I'm using CLion on Mac, and it complains that line 54 always evaluates to "true". Which is this line at the bottom:
else if(state == END_COMMENT) {
Despite this remark, the program seems to work so far...
Does that line always evaluates to true, and if so, why? Because I don't see anything wrong with it.
As stated in the comments, this is much easier to debug as a switch statement. I converted it to a switch and the issues with the final if/else conditions went away.
I also am using CLion on a mac and saw the warnings that you were seeing.
Despite the comments above, your code handles the c style '/* .... */ comments correctly.
I think it is helpful to let people know that this a preprocessor that simply strips old-style c comments /*..*/ not //... from code and then puts out the stripped code.
The state machine is MUCH easier to read as a switch statement, and easier to debug as well.
Note that in one place, you were checking for one of two characters, which allowed the fallthrough style in one of the switch statements.
Sometimes, when it is easier to write the code more 'simply' rather than to figure out why the compiler feels that a condition will always be true, it is best to follow best practices and simplify.
#include <stdio.h>
const char CODE = 0;
const char START_COMMENT = 1;
const char END_COMMENT = 2;
const char COMMENT = 3;
const char INQUOTE = 4;
// Preprocessor which discards comments
int main() {
int c;
char state = CODE;
while (EOF != (c = getchar())) {
switch (state) {
case CODE:
switch (c) {
case '/': // If we are in a comment, we will strip this section of the code
// check if this is the start of a comment:
state = POTENTIAL_COMMENT;
break;
case '"':
case '\'':
state = INQUOTE;
putchar(c);
break;
default:
putchar(c);
}
break;
case INQUOTE:
if (c == '"' || c == '\'') {
state = CODE;
}
putchar(c);
break;
case POTENTIAL_COMMENT:
switch (c) {
case '*': // We saw the '/', so now we se the '*' and we are in a comment, just eat the char
state = COMMENT;
break;
case '/':
state = LINE_COMMENT;
break;
default:
putchar('/'); // we saw a '/' before, but it wasn't really the start of a comment, so put the '/' back and the current char
putchar(c);
state = CODE;
}
case COMMENT:
if (c == '*') {
state = END_COMMENT;
}
break;
case LINE_COMMENT:
if (c == '\n')
state = CODE;
break;
case END_COMMENT:
if (c == '/') {
state = CODE;
} else
state = COMMENT;
}
}
}

Lexical Analysis in C Language - How to make the asterisk be read and output it in detection of Multi-Line Comment?

I am working on a Lexical Analysis program , everything works fine when detecting a single line comment. This is my code for single line comment detection.
//Single Comment
if ((Current_Character == '/') && (fgetc(File_Input) == '/')){
printf("%c", Current_Character);
do{
printf ("%c", Current_Character);
Current_Character = fgetc (File_Input);
}while(Current_Character != '\n');
printf("\b \t | COMMENT\n", Current_Character);
i = -1;
Lexeme_Count++;
Comment_Count++;
}
But when i am trying to detect the Multi-Line comment it got a logical error which it cannot detect the opening asterisk. here is my code for Multi-Line comment detection:
//Multi-Line Comment
if((Current_Character == '/') && (fgetc(File_Input) == '*')){
printf ("%c", fgetc(File_Input));
do{
printf ("%c", Current_Character);
Current_Character = fgetc(File_Input);
}while(Current_Character != '/');
printf("\b | COMMENT\n", Current_Character);
i = -1;
Lexeme_Count++;
Comment_Count++;
}
Current character is for the first character for multi-line comment which is backslash and second character which is (fgetc(File_Input) (getting the next latest character from file) is for opening askterisk.
This is the content of the file I inputted:
#include <conio.h>
{
int a[3],t1,t2;
t1=2; a[0]=1; a[1]=2; a[t1]=3;
t2=
-
(a[2]+t1*6)/(a[2]
-
t1);
if t2>5 then
print(t2);
else {
int t3;
t3=99;
t2=
-
25;
print(
-
t1+t2*t3); // this is a comment on 2 lines
} endif /* THIS IS A MUTLI-LINE COMMENT ON 2 LINES
*/ }
This is my current output
You have:
if((Current_Character == '/') && (fgetc(File_Input) == '*')){
printf ("%c", fgetc(File_Input));
do{
printf ("%c", Current_Character);
Current_Character = fgetc(File_Input);
}while(Current_Character != '/');
The first printf() should be printing the character returned by the fgetc(), which you know to be a *, so you could use putchar('*'); or (if you really insist) printf("%c", '*') or printf("*").
Note that you've got another problem lurking:
x = a/b;
It isn't clear which of your comment blocks executes first, but both of them lose the b after the division. There are numerous other subtleties in comment detection in C — I won't bore you with them all, but suffice to say "it is hard work removing comments in C" (and harder still in C++). One of the issues you're not addressing is unexpected EOF (end of file).
You probably need a peek() function to look at the next character without consuming it:
int peek(FILE *fp)
{
int c = fgetc(fp);
if (c != EOF)
ungetc(c, fp);
return c;
}
this code snippet skips all the chars until you detect the */, considering the special cases where you have endings like ***/:
int state = 0;
while((c = getchar()) != EOF) {
switch(state) {
case 0:
switch(c) {
case '*': state = 1; continue;
default: /* process as comment char, but ignore */
continue;
} /* NOTREACHED */
case 1:
switch(c) {
case '*': continue;
case '/': /* end comment processing and return */
state = 0;
return COMMENT; /* or continue, depending on scanner */
default: /* any other char returns to state 0 */
state = 0;
/* process comment char */
continue;
} /* NOTREACHED */
} /* switch */
} /* while */

A program with "getchar/putchar" which takes lines of text and prints it each sentence from a new line

I'm trying to write a simple program using getchar/putchar operators. It must get text in lines and print it out every sentence from the new line.
I wrote this code but it works unexpectedly for me, for example I wrote
"I can't program. Help me. Please."
it prints out:
I can't program.
. Help me.
. Please.
Why it's duplicating "."???
My code is:
#include <stdio.h>
#include <stdio.h>
int main(void) {
int stop=0;
int i;
printf("enter your text: ");
while((i=getchar())!=EOF){
if(i=='.')
{
stop=1;
putchar(i);
putchar('\n');
}
if(i==' ')
{
if(stop==0) putchar(i);
}
else if(i!=' '||i!='.')
{
putchar(i);
stop=0;
}
}
return 0;
}
Thank you in advance.
A but of reformatting would help to understand the error
if(i == '.') {
stop = 1; // part A
putchar(i);
putchar('\n');
}
if(i == ' ') {
if(stop == 0) { // Part B
putchar(i);
}
} else if(i != ' ' || i != '.') {
putchar(i); // Part C
stop = 0;
}
When char i contains a dot,
part A is executed (and the dot is printed)
the test against space fails
and then the else part is executed
In the else part, the test always succeeds, because you write an "or" instead of an "and". So the dot is printed again. by part C.
How to fix it : in your problem there are 3 cases (dot, space, others) and you should avoid to express the same comparaison twice.
A possibility is a series of if/else-if/...
if (i == '.') {
// process dot
} else if (i == ' ') {
// process space
} else {
// process other
}
A better solution is to use a switch
switch (i) {
case '.':
// process dot
break;
case ' ':
// process space
break;
default:
// process other
break;
}
This:
else if(i!=' '||i!='.')
makes no sense, you meant
else if(i != ' ' && i != '.')

Reading a C source file and skipping /**/ comments

I managed to write code to skip // comments in C source:
while (fgets(string, 10000, fin) != NULL)
{
unsigned int i;
for (i = 0; i < strlen(string); i++)
{
if ((string[i] == '/') && (string[i + 1] == '/'))
{
while (string[i += 1] != '\n')
continue;
}
//rest of the code...
I've tried to do similar thing for /**/ comments:
if ((string[i] == '/') && (string[i + 1] == '*'))
{
while (string[i += 1] != '/')
continue;
}
if ((string[i] == '*') && (string[i + 1] == '/'))
{
while (string[i -= 1])
continue;
}
But it reads line by line and if I have, for example,
/*
text*/
then it counts the text.
How do I fix this?
Even your supposedly-working code has several problems:
It does not recognize any context, so it will treat // appearing within a string constant or within a /* ... */ comment as the beginning of a comment.
In the unlikely event that you happen to have very long lines, they will be truncated (including their terminating newlines).
In the end, C is a stream-oriented language, not a line-oriented language. It should be parsed that way (character by character). To do the job right, you really need to implement a much more sophisticated parser. If you're up for learning a new tool, then you could consider basing your program on the Flex lexical analyzer.
A simple regular expression for a C comment is:
/\*([^\*]|\*[^\/])*\*\//
(Sorry for the escape characters) This allows any sequence inside a comment except */. It translates to the following DFA (four states):
state 0, input /, next state 1, output none
state 0, input other, next state 0, output read char
state 1, input *, next state 2, no output
state 1, input /, next state 1, output /
state 1, input other, next state 0, output / and read char
state 2, input *, next state 3, output none
state 2, input other, next state 3, output none
state 3, input /, next state 0, output none
state 3, input *, next state 3, output none
state 3, input other, next state 2, output none
The possible inputs are /, * and any other character. The possible outputs are output read char, output / and output *.
This translates to the following code:
file uncomment.c:
#include <stdio.h>
int main()
{
int c, st = 0;
while ((c = getchar()) != EOF) {
switch (st) {
case 0: /* initial state */
switch (c) {
case '/': st = 1; break;
default: putchar(c); break;
} /* switch */
break;
case 1: /* we have read "/" */
switch (c) {
case '/': putchar('/'); break;
case '*': st = 2; break;
default: putchar('/'); putchar(c); st = 0; break;
} /* switch */
break;
case 2: /* we have read "/*" */
switch (c) {
case '*': st = 3; break;
default: break;
} /* switch */
break;
case 3: /* we have read "/* ... *" */
switch (c) {
case '/': st = 0; break;
case '*': break;
default: st = 2; break;
} /* switch */
break;
} /* switch */
} /* while */
} /* main */
In case you want to exclude both types of comments, we need to switch to a fifth state when receiving a second /, resulting in the following code:
file uncomment2.c:
#include <stdio.h>
int main()
{
int c, st = 0;
while ((c = getchar()) != EOF) {
switch (st) {
case 0: /* initial state */
switch (c) {
case '/': st = 1; break;
default: putchar(c); break;
} /* switch */
break;
case 1: /* we have read "/" */
switch (c) {
case '/': st = 4; break;
case '*': st = 2; break;
default: putchar('/'); putchar(c); st = 0; break;
} /* switch */
break;
case 2: /* we have read "/*" */
switch (c) {
case '*': st = 3; break;
default: break;
} /* switch */
break;
case 3: /* we have read "/* ... *" */
switch (c) {
case '/': st = 0; break;
case '*': break;
default: st = 2; break;
} /* switch */
break;
// in the next line we put // inside an `old' comment
// to illustrate this special case. The switch has been put
// after the comment to show it is not being commented out.
case 4: /* we have read "// ..." */ switch(c) {
case '\n': st = 0; putchar('\n'); break;
} // switch (to illustrate this kind of comment).
} /* switch */
} /* while */
} /* main */
This simple code can ignore the comment /* */ ( doesn't treat all the cases for instance writing /* inside a string between quotes for a variable in c code )
#include <stdio.h>
#include <string.h>
typedef enum bool // false = 0 and true = 1
{ false,true}bool;
int main(int argc, char *argv[])
{
FILE* file=fopen("file","r"); // open the file
bool comment=false;
char str[1001]; // string that will contain portion of the file each time
if (file!=NULL)
{
while (fgets(str,sizeof(str),file)!=NULL)
{
int i=0;
for (i=0;i<strlen(str);i++)
{
if (str[i]=='/' && str[i+1] == '*')
{
comment=true; // comment true we will ignore till the end of comment
i++; // skip the * character
}
else if (str[i]=='*' && str[i+1] == '/')
{
comment=false;
i++; // skip the / character
}
else if (comment==false)
{
printf("%c",str[i]); // if the character not inside comment print it
}
}
}
fclose(file);
}
return 0;
}
(It is not very clear what your program is trying to do.)
Using flex to count the number of characters outside comments:
%option noyywrap
%%
int i = 0;
\"([^\\"]|\\.)*\" { i += yyleng ; } // treatment of strings
\/\/.* { } // C++ comments
\/\*([^*]|\*[^/])*\*\/ { } // C comments
.|\n { i += yyleng ; } // normal chars
<<EOF>> { printf("%d\n",i); return;}
%%
int main(){
yylex();
return 0;}
and
$ flex count-non-com.fl
$ cc -o count-non-com lex.yy.c
$ count-non-com < input
One last example: flex code to remove comments (thanks #LuisColorado)
%option noyywrap
%%
\"([^\\"]|\\.)*\" { ECHO; } // treatment of strings
\/\/.* { } // C++ comments
\/\*([^*]|\*[^/])*\*\/ { } // C comments
.|\n { ECHO; } // normal chars
%%
int main(){
yylex();
return 0;}
Make an int variable.
Scan the characters and store the index if you get /*.
Continue scanning until you get */.
If the variable !=0 at that time, then assume this is the closing comment token and ignore the characters in between.
As user279599 just said,use an integer variable as flag,whenever you get '/' & '' consecutively set flag up(flag=1),then flag value remains 1 until get '' & '/' consecutively. Ignore every character when the flag is 1.

C program, problem with newlines & tabs next to each other

Here was my original code:
#include <stdio.h>
#define IN 1 // inside a word
#define OUT 0 // outside a word
// program to print input one word per line
int main(void)
{
int c, state;
state = OUT;
while ((c = getchar()) != EOF) {
if (c == ' ' || c == '\n' || c == '\t') {
state = OUT;
printf("\n");
}
else if (state == OUT) {
state = IN;
}
if (state == IN) {
putchar(c);
}
}
return 0;
}
But the problem was if there were multiple blanks (spaces) or multiple tabs next to each other a newline would be printed for both. So I used a variable (last) to keep track of where I was:
#include <stdio.h>
#define IN 1 // inside a word
#define OUT 0 // outside a word
// program to print input one word per line, corrected bug if there was
// more than one space between words to only print one \n
int main(void)
{
int c, last, state;
last = EOF;
state = OUT;
while ((c = getchar()) != EOF) {
if (c == ' ' || c == '\n' || c == '\t') {
if (last != c) {
state = OUT;
printf("\n");
}
}
else if (state == OUT) {
state = IN;
}
if (state == IN) {
putchar(c);
}
last = c;
}
return 0;
}
That solved it, except now if there is [blank][tab] next to each other, a newline gets printed for both.
Could someone please help?
Your problem with your original code is that you will output your newline for every whitespace character. You only want to do it when transitioning from word to non-word:
Change:
if (c == ' ' || c == '\n' || c == '\t') {
state = OUT;
printf("\n");
}
to:
if (c == ' ' || c == '\n' || c == '\t') {
if (state == IN) printf("\n");
state = OUT;
}
In fact, what I originally thought I'd suggest would be an enumeration for the states along the lines of:
enum eState {IN, OUT};
:
enum eState state = OUT;
but, for a simple finite state machine with only two states, you can just use an boolean:
#include <stdio.h>
#define FALSE (1==0)
#define TRUE (1==1)
// Or: enum eBoolean {FALSE = 0, TRUE = 1};
int main (void) {
int ch;
int inWord = FALSE; // Or: enum eBoolean inWord = FALSE;
// Process every character.
while ((ch = getchar()) != EOF) {
// Check for whitespace.
if (ch == ' ' || ch == '\n' || ch == '\t') {
// Check if transitioning nonwhite to white.
if (inWord) {
printf("\n");
}
// Mark white no matter what.
inWord = FALSE;
} else {
// Mark non whitespace.
inWord = TRUE;
}
// If not whitespace, output character.
if (inWord) {
putchar(ch);
}
}
return 0;
}
As paxdiablo said, your program is a typical finite state automata (FSA). You have to print a new line in transitions from state OUT to state IN and only then.
Below is how I would write such code. In this particular case it can be made simpler, but the structure is interesting because typical and it applies to any FSA. You have a big external switch with a case for each state. Inside each case, you get another one that materialize transitions, here transition event are input characters. All is left to do is think about what should be done for each transition. Also this structure is quite efficient.
You should keep it in mind, it's really a very common one to have in your toolkit of pre-thought program structures. I certainly do it.
#include <stdio.h>
#define IN 1 // inside a word
#define OUT 0 // outside a word
// program to print input one word per line
int main(void)
{
int c, state;
state = OUT;
while ((c = getchar()) != EOF) {
switch (state){
case OUT:
switch (c){
case ' ': case '\n': case '\t':
break;
default:
putchar(c);
state = IN;
}
break;
case IN:
switch (c){
case ' ': case '\n': case '\t':
putchar('\n');
state = OUT;
break;
default:
putchar(c);
}
break;
}
}
return 0;
}
See when you check in your second code
if (last != c) {
You are not checking for all conditions.last could be equal to space, tab or new line. In all such cases it should not print new line. Lets call the set of these three special characters as X.
Now when printing new line, you need to make sure that last character printed does not bring to set X. But you check that last!=current. Now current could be space, tab or new line. But it is only one value. It does not serve our need, our purpose.
So instead replace it with
if (last != ' ' && last != '\n' && last != '\t' ) {
You can see the code here:
#include <stdio.h>
#define IN 1 // inside a word
#define OUT 0 // outside a word
// program to print input one word per line, corrected bug if there was
// more than one space between words to only print one \n
int main(void)
{
int c, last, state;
last = 0; // We need it to make sure that a newline is not printed in case first
// char is space, tab or new line.
state = OUT;
while ((c = getchar()) != EOF) {
if (c == ' ' || c == '\n' || c == '\t') {
// if (last != c)
if (last != ' ' && last != '\n' && last != '\t' && last != 0 )
{
state = OUT;
printf("\n");
}
} else if (state == OUT) {
state = IN;
}
if (state == IN) {
putchar(c);
}
last = c;
}
return 0;
}
Edit
Fixed the bug paxdiablo pointed out in comments.
#include<stdio.h>
#define OFF 0
#define ON 1
main()
{
int c,state=ON;
while((c=getchar())!=EOF)
{
if(c=='\n'||c==' '||c=='\t')
{
if(state==OFF)putchar('\n');
state=ON;
}
else if(state==ON)
{
putchar(c);
state=OFF;
}
else if(state==OFF)
{
putchar(c);
}
}
}
Here's one way of approaching the problem, which was used above:
Where, STE=Space, tab or enter.
<STE><WORD>---->TYPE<WORD>
<STE><STE>----->DO NOTHING
<WORD><SPACE>-->TYPE<WORD><ENTER/NEWLINE>
<WORD><WORD>--->TYPE<WORD>
You can replace and with ON and OFF, as illustrated above.

Resources