There's actually a builtin function, gets(), that does precisely what you want. However, for learning, there's no problem with reinventing a few wheels.
I don't see any huge problem with your code, other than the gaping hole that's present in gets() too. (see below) A few minor things:
A '\0' character is legal in a file and isn't an end or error return. It's not a legal character in a string, though, so I can see why you might want to filter those out. I'd do that with:
if (c != 0)
{ x[i++] = c; }
...inside the loop, though.
What you should be testing for in the while loop is end-of-file. The safest way to do that:
while ( c!='\n' && !feof(stdin) )
{
x[i++] = c; /* possibly add a '\0' filter here */
c = getchar();
}
The getchar() function is defined to return an int, so you might get warnings on "c = getchar();" calls. The return value allows for a non-char value, symbolically defined as EOF, to be returned instead of a char. The intent was that EOF was an int value that couldn't compare equal to any legitimate char value. The early implementations used -1, since the char type was unsigned on those implemenations, and an avalanche of bad coding made it impossible to choose any other value. Unfortunately, on a signed-char implemenation (legal and the natural choice on x86 machines), that's a legal char. So, you can convert c to an int variable and test for c!=EOF, if you like, but '\xFF' chars will be treated as end-of-file markers by your program. feof() might be slower, but always works.
The gaping hole is that you don't have a way to tell readString() how big the x buffer is. Since you don't know the maximum length of a line in advance, especially from stdin where the input device might be a keyboard with a cat sleeping on an auto-repeat key, it's easy to overrun any sensibly-sized buffer.
You should pass a buffer size (or a max string length, one less, but buffer size works better in practice for the caller) and never store anything beyond that length--not even the string terminator.
You should also return some sort of status that says whether this happened or not. The safer fgets() function in the standard library solves this by storing the '\n' that ended the line. If the trailing \n is missing, then the caller knows that either EOF or a string overflow ended the string.
You don't want the \n in the string, so you need another method. One is to never read more than n-1 characters ever. After you increment i to (n-1), stop storing without getting another character. A line-too-long will return a string of exactly (n-1) characters, and the \n will still be unread in the stdin buffer, so a subsequent call could try to get the rest of the line. Any full line will be n-2 chars or less, and the caller can use strlen to test if this happened.
Another approach (my choice) is to simply return status instead of the buffer pointer. That give up on being able to stack multiple things in a single expression statement, like:
len = strlen(strToLower(readString(linebuf)));
...assuming you have defined a strToLower() function.
The reason I'm typing so long about this is that unchecked buffers in C are the single largest source of software security holes and catastrophic system failures. C is a nice language, used properly, and a very nice alternative to assembler for embedded systems, kernels, drivers and the like. It can also be good for applications, if used properly. Just make safe array/buffer handling automatic now so you won't likely to slip later under deadline pressure. (aka "crunch time")