Introduction
hey all, I'm matt. I'm new to this forum and C. I hope to stick around and eventually be able to ANSWER questions instead of sit around being new to this.

but for now, new to this is what I am.

My Background
I've been learning from Dave Mark's "Learn C on a Macintosh" I have basic knowledge of java and full knowledge of JavaScript. My home turf is max/msp.

The Confusing Example
Everything was going fine until I hit this one function in the examples. now I'm completely confused.

void	ReadLine( char *line ) // line is a string
{
	while ( (*line = getchar() ) != '\n' )
		line++;
	
	*line = 0;
}

The Questions
Can someone tell me, step by step what this code does???
It's so compact that I really just don't understand it.
How does getchar know which char to get?
How can you assign and compare in the same expression?
Why increment a char?
all these questions and more, answered when you stay tuned to
"When Geeks Pull Out Their Remaining Hair"
after these messages....

-matt

It's not very good example especially for beginners.
You need to know that C strings are ordinary arrays of characters that ends with zero character '\0' or just 0.
for example if you define c string like:

char text[50];

It means it can store 49 character + zero character.
You can look to name of an array as a pointer to first element in an array (although it's not quite true).
You have a function that receive char pointer and that is just it a pointer to character. It can be incremented and decremented.
If you call function EeadLine(text) that means that pinter to the first character in array text is copied and thransfered to function. You can increment and decrement pointer in that function, so you can traverse your array.
getchar() function read from standard input and returns int, not char, and in your example there is truncation which is why I don't like this example very much, but this can serve to teach you more about C strings.
Line:

*line = getchar()

means this:
read character and place it in location where line points to i.e. change element on which line points with element that getchar read from input.
Every time you enter some text in console window and hit Enter a newline marker '\n' is placed in text.
So in loop you basicaly read one character at a time an store it on place to which line points to, next increment line (since this is pointer) to point to the next location, place another element and so on until you reach '\n' which denotes end of line. Last step is to place zero character '\0' or 0 to end string.
I hope this explanation helps.

thanks so much for your reply. I'm processing this info so let me confirm my findings.

**first of all, when evaluating an expression like so,

(a=b) != c
// pseudo code

first, b is assigned to a
then b=a evaluates to b ?
so the full expression returns b !=c ?


**Second, the equivalent would be (and I know this is bad form)

void	ReadLine( char *line )
{
	while(true)
		{
              //transfer elements of buffer to array 
              //beginning with array[0]
		*line=getchar(); 
		
		if(*line=='\n') //if you encounter a \n break out of the loop
			{break;}
			
		*line++; //point *line to the next array element
		}
	
	*line = 0; //put a 0 at the end of the array to make it a string
}

thanks so much for your reply. I'm processing this info so let me confirm my findings.

**first of all, when evaluating an expression like so,

(a=b) != c
// pseudo code

first, b is assigned to a
then b=a evaluates to b ?
so the full expression returns b !=c ?

You're right...
Expression returns 1 or 0 depending of result of comparision.

#include <stdio.h>

int main (void)
{
	int a = 10, b = 12, c = 15;

	printf ("%d", ( (a = b) != c ) );
	return 0;
}

change this:

*line++; //point *line to the next array element

to this:

line++; //point *line to the next array element

line is the pointer. *line is the value at the address being held in the pointer. You want to advance the pointer to the next element in array, not the value of the next element of the array.

As an aside, it seems to me, there is a logic problem here. That is, once you have used line to put the characters in the array how do you get back to where you started so you can use the information you entered? I suspect the author of the book doesn't care about that for now. Their goal in this example was likely to demonstrate some of the properties of arrays and pointers and they will address the logic error in this example down the road.

[LEFT]void	ReadLine( char *line ) // line is a string
{
	while ( (*line = getchar() ) != '\n' )
		line++;
	
	*line = 0;
}

This is a buffer overflow waiting to happen. What happens if someone passes an array of some arbitrary size, say 50 bytes, and the user enters 51 bytes? The function should really take a second argument that specifies the size of the string, and then it should stop reading characters if it reaches that mark.

> That is, once you have used line to put the characters in the array how do you get back to where you started so you can use the information you entered?

That shouldn't be a problem here, since the pointer local to the ReadLine function is changed, and the calling function's pointer/array is not.
[/LEFT]

change this:

*line++; //point *line to the next array element

to this:

line++; //point *line to the next array element

line is the pointer. *line is the value at the address being held in the pointer. You want to advance the pointer to the next element in array, not the value of the next element of the array.

It isn't incrementing the value -- it is evaluating the current value (and discarding the result) and then advancing the pointer.

Maybe I should post ALL of the code before you/we indict this guy. I swear this book was great unitl page 172. :lol:

:?: another question: Why does the program wait for the user to enter the data? If you uncomment the two printf()s that I inserted you'll see what I'm talking about.

#include <stdio.h>
#include <ctype.h> //This is to bring in the declaration of isspace()
#include <c.h>  //This is to bring in the define of true


#define kMaxLineLength		200
#define kZeroByte			0

void	ReadLine( char *line );
int		CountWords( char *line );


int main (int argc, const char * argv[])
{
	char	line[ kMaxLineLength ];
	int		numWords;
	
	printf( "Type a line of text, please:\n" );
	
	ReadLine( line );
	
	numWords = CountWords( line );
	
	printf( "\n---- This line has %d word", numWords );
	
	if ( numWords != 1 )
		printf( "s" );
	
	printf( " ----\n%s\n", line );
	
	return 0;
}


void	ReadLine( char *line )
{
//printf("moopants\n");
//printf("%d",getchar() );
	while ( (*line = getchar()) != '\n' )
		{
		line++;
		}
	
	*line = kZeroByte;
}


int	CountWords( char *line )
{
	int		numWords, inWord;
	
	numWords = 0;
	inWord = false;
	
	while ( *line != kZeroByte )
	{
		if ( ! isspace( *line ) )
		{
			if ( ! inWord )
			{
				numWords++;
				inWord = true;
			}
		}
		else
			inWord = false;
		
		line++;
	}
	
	return numWords;

}

Maybe I should post ALL of the code before you/we indict this guy. I swear this book was great unitl page 172. :lol:

Well, when authors haven't covered basic user input by the time they are having you (the user) enter input, I'd say [bad things].

And when they do stuff to make it uncompileable for folks trying to play along, it's a shortcut they need to explain better:

#include <c.h>  //This is to bring in the define of true

(We may not have this <c.h> -- which is coded to look like a standard header, but it isn't. So it's really not ALL of the code.)

:?: another question: Why does the program wait for the user to enter the data? If you uncomment the two printf()s that I inserted you'll see what I'm talking about.

Your printf is asking to wait for input:

void	ReadLine( char *line )
{
//printf("moopants\n");
//printf("%d",getchar() );
	while ( (*line = getchar()) != '\n' )
		{
		line++;
		}
	
	*line = kZeroByte;
}

But then again, without the header I can't compile it. So I can't build it. So I can't run it.

This article has been dead for over six months. Start a new discussion instead.