0

Can someone please explain to me in layman's terms what's going on with this snippet of code? I understand it's a function used to get the first character then discard the remaining input but I am confused with the last while loop. When I googled it I found very complicated explanations which went way over my head. There was one explanation that kind of made sense but it was an assembly code explanation dealing with the input being on the stack in memory and then my pea brain went numb.

int get_First(void)
{
     int ch, garbage;

     do
     {
          ch = getchar();
     }while(isspace(ch));

    while((garbage = getchar()) != '\n' && garbage != EOF)
                ;
    return ch;
}
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
MAD
  • 31
  • 4

5 Answers5

4
while((garbage = getchar()) != '\n' && garbage != EOF) ;

is basically a very compressed version of:

garbage = getchar();
while ( garbage != '\n' && garbage != EOF )
  garbage = getchar();

Basically, read and discard any characters on standard input until we see a newline or end of file is signaled.

C condition expressions can contain an assignment:

while ( x = foo() ) // assign result of foo() to x, loop if non-zero
{
  // do something
}

Since a lot of people accidentally type = when they mean ==, most compilers will warn about an assignment expression in a condition expression unless that expression is wrapped in parentheses:

while ( (x = foo()) ) // assign result of foo() to x, loop if non-zero
{
  // do something
}

This tells the compiler "yes, I intend to assign the result of foo() to x and loop based on the result, shut up."

Assignment expressions in C can appear as part of a larger expression. The result of an assignment expression is the value stored in the target after any appropriate conversions. Thus, the result of an assignment expression can be compared against something else as well, so you can write

while ( (x = foo()) > 0 ) // assign result of foo() to x, loop while result is positive
{
  // do something
}

You can make multiple comparisons:

while ( (x = foo()) > 0 && x < 100 )
{
  // do something
}

The && operator forces left to right evaluation - (x = foo()) > 0 will be evaluated first, assigning a new value to x as a side effect. If the result is non-zero (x is positive), then x < 100 will be evaluated. Again, it's a compact way of writing:

x = foo();

if ( x > 0 && x < 100 )
{
  // do something
  x = foo();
}
John Bode
  • 119,563
  • 19
  • 122
  • 198
1

The second while loop keeps reading characters until it reads a newline char (\n) or reaches the end of file (EOF).

Stephen Docy
  • 4,738
  • 7
  • 18
  • 31
1

Your second while loop does not have any body and it will continuously reading from standard input. If you press Enter which is a new line character it will break because it will keep continuously checking whether entered value is not newline character and not a end of file character.

Abhijit Pritam Dutta
  • 5,521
  • 2
  • 11
  • 17
1

The while loop is not an infinite loop: it has an empty body but will keep executing its condition until it returns a zero value.

The condition will evaluate to 0 if either the first operand of && evaluates to 0 or if the second operand evaluates to 0.

The first operand (garbage = getchar()) != '\n first reads a byte from standard input and stores it to garbage and compares it to '\n', the newline character. If the byte read is indeed a newline, the loop stops, otherwise garbage (the byte read) is compared to EOF and the loop stops if the stream is at end of file, where the return value of getchar is the special value EOF.

The purpose of this while loop is simply to consume the rest of the current input line. Note however that the function may read one or more lines until it finds a non whitespace character.

chqrlie
  • 131,814
  • 10
  • 121
  • 189
  • The first loop will only read multiple lines if they're all empty. – Barmar Mar 07 '18 at 23:06
  • @Barmar: yes, but *empty* is not precise enough: the first loop will consume lines containing either no characters or only whitespace characters. the newline character '`\n`' is a whitespace character. – chqrlie Mar 07 '18 at 23:15
  • Since the purpose of this function seems be to return the first non-whitespace character, and then skip to the end of the line containing that character, skipping all-white lines seems to be appropriate. – Barmar Mar 07 '18 at 23:53
0

This function returns first not whitespace in the input. And then ignores everything until end of the line or end of file. It is very badly written as it will read the next line if there are no non whitespaces in the line or will cause an error if the first char after the whitespace the EOF.

chqrlie
  • 131,814
  • 10
  • 121
  • 189
0___________
  • 60,014
  • 4
  • 34
  • 74
  • ¿Que? The "very badly written" comment doesn't seem accurate to me. If the next character in the input is white space (including newline), it will be read until `ch` contains either EOF or a character that's not white space. If the character after the white space is EOF, it will return EOF; the gobbling loop will detect EOF immediately — assuming that `getchar()` continues to return EOF once it has reported it once. (Some versions of GlibC on Linux have seemed broken when the input comes from a terminal, but that's a different bug, and not a bug in the code in the question.) – Jonathan Leffler Mar 08 '18 at 00:30
  • I forgot that the \n is a whitespace as well. But as I understand the idea of this code - it should return first not wihite space in the line. This one will return will just return first not whitespace character which can be anywhere in the file. – 0___________ Mar 08 '18 at 00:35
  • Where does the code say "first non-white-space character in the line" in the job description? It returns the "first non-white-space character" period — regardless of how many lines it has to read to find it. Your hypothetical requirement is a plausible alternative specification; it just isn't what the code implements, and the question is about what the code implements, not what it should implement. – Jonathan Leffler Mar 08 '18 at 00:37