#1
  1. No Profile Picture
    .
    Devshed Newbie (0 - 499 posts)

    Join Date
    Dec 2002
    Posts
    296
    Rep Power
    13

    not breaking when EOF


    i'm not doing very well with these k&r exercises :(

    can anyone tell me what wrong here please? :

    the exercise is to do this loop:
    Code:
    for (i=0; i<lim-1 && (c=getchar()) != '\n' && c != EOF; i++)
    	s[i] = c;
    without any && or || 's. so here's my effort that does not work but i can't see why it doesn't work:
    Code:
    	while(i<lim-1) {
    		c=getchar();
    		if (c != '\n') {
    			if (c != EOF) {
    				s[i]=c;
    				i++;
    			}
    		} else
    			break;
    	}
    the problem with it is when i press control d to get the EOF character/sign it does not break out of the loop. or at least it does appear to. are if's considered loops? is that what is happening - the break only gets it out of the if? no, that's a complete guess and i don't think that's right. anyone?
  2. #2
  3. Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jun 2000
    Location
    Southern California
    Posts
    73
    Rep Power
    15
    In your snippet, if the char is not a newline, but it is EOF, i never gets incremented.

    You can modify it like this:

    Code:
    while (i<lim-1) {
        c=getchar();
        if (c != '\n') {
            if (c == EOF) {
                break;
            }
             else {
                s[i]=c;
                 i++;
            }
        } else
            break;
        }
    }
    Better yet, do something like this:

    Code:
    for (register int i=0; i < (lim-1); i++) {
      c = getchar();
    
      if (c == '\n') break;
      if (c == EOF)  break;
    
      s[i] = c;
    }
  4. #3
  5. No Profile Picture
    .
    Devshed Newbie (0 - 499 posts)

    Join Date
    Dec 2002
    Posts
    296
    Rep Power
    13
    the first version of those two still doesn't break out of the loop - same problem

    you did accidentally use an extra } so this is how i used it:

    Code:
    while (i<lim-1) {
    		c=getchar();
    		if (c != '\n') {
    			if (c == EOF) {
    				break;
    			}
    			else {
    				s[i]=c;
    				i++;
    			}
    		} else
            		break;
    }
    (so i've deleted a } from the end)

    so is an if {} considered a loop? is that why this structure isn't working? - it's only brekaing out of the if! but that would make your second version not work too.
    i ask/say that, but it doesn't feel right at all. but i can't see why it doesn't break out of the while loop having encountered an EOF in the above code.

    the second version you posted works fine, so thanks. but i would like to get to the bottom of why the first version isn't working. any ideas?
  6. #4
  7. No Profile Picture
    Junior Member
    Devshed Newbie (0 - 499 posts)

    Join Date
    Apr 2002
    Location
    Hyderabad
    Posts
    17
    Rep Power
    0
    Hi ,

    First getchar() function enables u to give to input to u r program from standard input stream . When getchar() encountered in for loop testing section , first it takes the whole input from u to standard input stream until u press Enter. Then for each iteration it reads the next character from STDIN ( standard input stream) , I n ur code u r cheking for '\n' to be encountered for loop break and u r input is also seeking for the same, that's why when u press enter , it satisfies the both conditions . U r code is also working with Ctrl D , if it's not working it will store that character in u r string s.
    Just test this statement

    printf("%s",s);
    and also

    for (i=0; i<lim-1 && (c=getchar()) != '\n' && c != EOF; i++)
    {
    printf("%u", c);
    s[i] = c;
    }
    After pressing Enter only it will display the Interger quivalents of u r typed characters.

    Then u will come to know.

    I hope this may help u.

    Suri
  8. #5
  9. No Profile Picture
    Junior Member
    Devshed Newbie (0 - 499 posts)

    Join Date
    Apr 2002
    Location
    Hyderabad
    Posts
    17
    Rep Power
    0
    Hi,

    u can use getch() which function prototype is in conio.h instead of getchar()
    because getchar() waits for ENTER to be pressed which is not a actual interactive way.


    Suri
  10. #6
  11. No Profile Picture
    .
    Devshed Newbie (0 - 499 posts)

    Join Date
    Dec 2002
    Posts
    296
    Rep Power
    13
    i still don't understand why it doesn't break out of this loop when crdl d is pressed:
    Code:
    while (i<lim-1) {
    		c=getchar();
    		if (c != '\n') {
    			if (c == EOF) {
    				break;
    			}
    			else {
    				s[i]=c;
    				i++;
    			}
    		} else
            		break;
    }
    if you follow the control through that code imagining c to hold eof, it goes into the if c!='\n' part as eof doesn't equal \n, then it should take the affirmative route from the if c equals eof, as c does equal eof. and the body of that if, is break so at that point the whole while loops should be broken out of - but it isn't and i can not see why :/ anyone?
    Last edited by balance; January 15th, 2003 at 06:41 PM.
  12. #7
  13. No Profile Picture
    Junior Member
    Devshed Newbie (0 - 499 posts)

    Join Date
    Apr 2002
    Location
    Hyderabad
    Posts
    17
    Rep Power
    0
    Just try ctrl-Z
  14. #8
  15. No Profile Picture
    .
    Devshed Newbie (0 - 499 posts)

    Join Date
    Dec 2002
    Posts
    296
    Rep Power
    13
    how does control z help me understand if if blocks are to be broken out of like loop blocks?! :)


    do if blocks get treated in the same way as while loops? so if you have an if in an if and you break out of the 2nd if block, you only break out as far as the 1st if. *but you're still in that 1st if?*. is that correct? cause that'll explain it. i guess it must be. that's the only explenation. i just didn't think if blocks were treated in quite the same way as a while or for block but i guess they are. thanks.
  16. #9
  17. Banned ;)
    Devshed Supreme Being (6500+ posts)

    Join Date
    Nov 2001
    Location
    Woodland Hills, Los Angeles County, California, USA
    Posts
    9,648
    Rep Power
    4248
    Firstly ^Z is the EOF character for DOS and ^D is for *nix. Secondly, ^D (or ^Z in DOS) is not considered as an EOF character by the terminal, unless it happens the first character of the new line (because terminals run in cooked mode by default -- google for "cooked mode" and "cooked mode ioctl" if you like). As a test, do the following:
    Code:
    cat > testfile
    this is the first line ^D [press enter]
    This is the second line [press enter]
    ^D
    Note that when you hit ctrl-d for the first line, the terminal did not recognize it as an end of file because it was not the first character in the line. DOS/Windoze users can perform the same test, using copy con testfile instead of cat > testfile and using ^Z instead of ^D. The results will be identical.

    Well, what does this cooked mode do? For one thing, it buffers the input and does not pass things on to your program immediately as you type them. The first time your program will get any of the input you typed in is when you press enter. Also, your code breaks out of the loop if the character is a newline or an EOF. Since the terminal does not consider it an EOF char, unless it is the first character on a new line, your program breaks after you hit enter. Let's alter your program to only break on EOF.
    Code:
    #include <stdio.h>
    int main(void) {
      char c;
      char s[100];
      int lim = 100, i = 0;
    
      printf("Enter a line\n");
    
      while (i<lim-1) {
        c=getchar();
        if (c != '\n') {
          if (c == EOF) {
            break;
          }
          else {
            s[i]=c;
            i++;
          }
        } /* else
                 break; */
      }
      s[i] = '\0';
      printf("%s\n", s);
      return 0;
    }
    Now compile and run this program. Now input something like this:
    Code:
    this is the first line ^D [press enter]
    This is the second line [press enter]
    ^D
    Note how your program works this time.

    Now to prove that your code does not read the characters until you hit enter, add this one line just under the line that reads c = getchar(); :
    printf("Bing!\n");

    Now run the program again. Note that your program will not print anything out unless you hit enter. This is because, in cooked mode, the terminal will buffer your input and not give it to your program immediately. The moment you hit enter, you'll see a series of "Bing!" being printed out, one for each character in your input.

    If you want to get your terminal to start passing your input to the program immediately after you press each key, you can set it to raw mode using ioctl commands. This holds true for DOS, Windoze and *nix. Hope this helps!
    Last edited by Scorpions4ever; January 16th, 2003 at 02:42 PM.
  18. #10
  19. No Profile Picture
    .
    Devshed Newbie (0 - 499 posts)

    Join Date
    Dec 2002
    Posts
    296
    Rep Power
    13
    right. i *think* i'm just about understanding this now :)

    i had already worked out that the programme only gets input a whole line at a time. but i had completely missed the fact that eof doesn't count if it's not the first character. that's the part that was missing for me.

    eof doesn't count unless it's the first character - this is just a terminal/console issue right? if you're not planning on using the console, other than for learning, then it's not something to think about too much about? or does this effect taking input from a higher level language? i guess not. or maybe it is? i'm thinking of in particular objective-c. doesn't matter - i'll find out.

    but yup, thanks very much for a good explenation :)
  20. #11
  21. Banned ;)
    Devshed Supreme Being (6500+ posts)

    Join Date
    Nov 2001
    Location
    Woodland Hills, Los Angeles County, California, USA
    Posts
    9,648
    Rep Power
    4248
    Originally posted by balance
    eof doesn't count unless it's the first character - this is just a terminal/console issue right? if you're not planning on using the console, other than for learning, then it's not something to think about too much about? or does this effect taking input from a higher level language? i guess not. or maybe it is? i'm thinking of in particular objective-c. doesn't matter - i'll find out.
    Yep, that's how the terminal works in cooked mode. It doesn't matter what language you're using, because the terminal works the same (unless someone writes an oddball language that overrides the default terminal settings).

    but yup, thanks very much for a good explenation :)
    You're welcome :)

IMN logo majestic logo threadwatch logo seochat tools logo