In K&R 1.9 longest line example, what is getchar() doing? - c

I seem to understand the program now, except the getline function is not very intuitive as it seems to copy everything getchar() returns to a character array s[] which is never really used for anything important.
int getline(char s[], int lim)
{
int c, i;
for(i=0; i < lim - 1 && (c = getchar()) != EOF && c != '\n'; ++i)
s[i] = c;
if(c == '\n')
{
s[i] = c;
++i;
}
s[i] = '\0';
return i;
}
The function could just as easily ignore the line s[i] = c; because all the function is really doing is counting the number of characters until it reaches EOF or '\n' returns from getchar()
What I really do not understand is why the program progressed forward as the main loop is as follows:
main()
{
int len; /* current line length */
int max; /* maximum length seen so far */
char line[MAXLINE]; /* current input line */
char longest[MAXLINE]; /* longest line saved here */
max = 0;
while ((len = getline(line, MAXLINE)) > 0)
if (len > max)
{
max = len;
copy(longest, line);
}
if (max > 0) /* there was a line */
printf("%s", longest);
return 0;
}
The only explanation would be that the getchar() function does its magic after the user has entered in a full line of text, and hits the enter key. So it would appear to work during run-time is my guess.
Is this how the program progresses? Does the program first enter the while loop, and then wait for a user to enter a line of text, and once the user hits enter, the getline function's for-loop is iterated? I feel like this would be the case, since the user can enter backspace during input.
My question is, how exactly does the program move forward at all? Is it all because of the getchar() function?
When I hit ctrl-D in the terminal, some other confusing stuff happens. If I hit ctrl-D at the start of a newline, the program will terminate. If I hit ctrl-D at the end of a line filled with some text, it does not terminate and it does not act the same way as hitting enter. If I hit ctrl-D a few times in a line with text, the program will finally end.
Is this just the way my terminal is treating the session, or is this all stuff I should not be worrying about if I just want to learn C?
The reason why I ask is that I like to trace the program to get a good understanding of it, but the getchar() function makes that tricky.

In a parameter declaration (and only in that context), char s[] really means char *s. The way the C standard describes this is that:
A declaration of a parameter as "array of type" shall be adjusted to
"qualified pointer to
type".
So s really is a pointer, of type char*, and when the function modifies s[i] it's modifying the ith element of line.
On the call:
getline(line, MAXLINE)
line is an array, but in most contexts an array expression is implicitly converted to a pointer to the array's first element.
These two rules almost seem to be part of a conspiracy to make it look like arrays and pointers are really the same thing in C. They most definitely are not. A pointer object contains the address of some object (or a null pointer that doesn't point to any object); an array object contains an ordered sequence of elements. But most manipulation of arrays in C is done via pointers to the array's elements, with pointer arithmetic used to advance from one element to the next.
Suggested reading (I say this a lot): section 6 of the comp.lang.c FAQ.

getchar reads a character from standard input. So if that's you sitting at the terminal, it blocks the program until it receives a character you've typed, then it's done. But standard input is line buffered when its interactive, so what you type isn't processed by the program until you press enter. That means that getchar will be able to keep reading all the characters you typed, as they're read from the buffer.
You're mistaken about the function. The array is passed to the function*, and it stores each character read by getchar (except for EOF or newline) in successive elements. That's the point of it - not to count the characters, but to store them in the array.
(*a pointer is actually passed, but the function here can still treat it like an array.)

The array is used for something important: it is provided by the caller and returned modified with the new content. From a reasonable point of view, filling in the array is the purpose of calling the function.

That array (an array reference) is actually a pointer, char s[] is the same as char *s. so it's building its result in that array, which is why it's copied later in main. there is rarely any "magic" in K&R.

Related

if my scanf variable is a float and a user inputs a character how can i prompt them to input a number? assuming the scanf is inside a do while loop

i have tried to use k = getchar() but it doesn't work too;
here is my code
#include<stdio.h>
int main()
{
float height;
float k=0;
do
{
printf("please type a value..\n");
scanf("%f",&height);
k=height;
}while(k<0);// i assume letters and non positive numbers are below zero.
//so i want the loop to continue until one types a +ve float.
printf("%f",k);
return 0;
}
i want a if a user types letters or negative numbers or characters he/she should be prompted to type the value again until he types a positive number
Like Govind Parmar already suggested, it is better/easier to use fgets() to read a full line of input, rather than use scanf() et al. for human-interactive input.
The underlying reason is that the interactive standard input is line-buffered by default (and changing that is nontrivial). So, when the user starts typing their input, it is not immediately provided to your program; only when the user presses Enter.
If we do read each line of input using fgets(), we can then scan and convert it using sscanf(), which works much like scanf()/fscanf() do, except that sscanf() works on string input, rather than an input stream.
Here is a practical example:
#include <stdlib.h>
#include <stdio.h>
#define MAX_LINE_LEN 100
int main(void)
{
char buffer[MAX_LINE_LEN + 1];
char *line, dummy;
double value;
while (1) {
printf("Please type a number, or Q to exit:\n");
fflush(stdout);
line = fgets(buffer, sizeof buffer, stdin);
if (!line) {
printf("No more input; exiting.\n");
break;
}
if (sscanf(line, " %lf %c", &value, &dummy) == 1) {
printf("You typed %.6f\n", value);
continue;
}
if (line[0] == 'q' || line[0] == 'Q') {
printf("Thank you; now quitting.\n");
break;
}
printf("Sorry, I couldn't parse that.\n");
}
return EXIT_SUCCESS;
}
The fflush(stdout); is not necessary, but it does no harm either. It basically ensures that everything we have printf()'d or written to stdout, will be flushed to the file or device; in this case, that it will be displayed in the terminal. (It is not necessary here, because standard output is also line buffered by default, so the \n in the printf pattern, printing a newline, also causes the flush.
I do like to sprinkle those fflush() calls, wherever I need to remember that at this point, it is important for all output to be actually flushed to output, and not cached by the C library. In this case, we definitely want the prompt to be visible to the user before we start waiting for their input!
(But, again, because that printf("...\n"); before it ends with a newline, \n, and we haven't changed the standard output buffering, the fflush(stdout); is not needed there.)
The line = fgets(buffer, sizeof buffer, stdin); line contains several important details:
We defined the macro MAX_LINE_LEN earlier on, because fgets() can only read a line as long as the buffer it is given, and will return the rest of that line in following calls.
(You can check if the line read ended with a newline: if it does not, then either it was the final line in an input file that does not have a newline at the end of the last line, or the line was longer than the buffer you have, so you only received the initial part, with the rest of the line still waiting for you in the buffer.)
The +1 in char buffer[MAX_LINE_LEN + 1]; is because strings in C are terminated by a nul char, '\0', at end. So, if we have a buffer of 19 characters, it can hold a string with at most 18 characters.
Note that NUL, or nul with one ell, is the name of the ASCII character with code 0, '\0', and is the end-of-string marker character.
NULL (or sometimes nil), however, is a pointer to the zero address, and in C99 and later is the same as (void *)0. It is the sentinel and error value we use, when we want to set a pointer to a recognizable error/unused/nothing value, instead of pointing to actual data.
sizeof buffer is the number of chars, total (including the end-of-string nul char), used by the variable buffer.
In this case, we could have used MAX_LINE_LEN + 1 instead (the second parameter to fgets() being the number of characters in the buffer given to it, including the reservation for the end-of-string char).
The reason I used sizeof buffer here, is because it is so useful. (Do remember that if buffer was a pointer and not an array, it would evaluate to the size of a pointer; not the amount of data available where that pointer points to. If you use pointers, you will need to track the amount of memory available there yourself, usually in a separate variable. That is just how C works.)
And also because it is important that sizeof is not a function, but an operator: it does not evaluate its argument, it only considers the size (of the type) of the argument. This means that if you do something silly like sizeof (i++), you'll find that i is not incremented, and that it yields the exact same value as sizeof i. Again, this is because sizeof is an operator, not a function, and it just returns the size of its argument.
fgets() returns a pointer to the line it stored in the buffer, or NULL if an error occurred.
This is also why I named the pointer line, and the storage array buffer. They describe my intent as a programmer. (That is very important when writing comments, by the way: do not describe what the code does, because we can read the code; but do describe your intent as to what the code should do, because only the programmer knows that, but it is important to know that intent if one tries to understand, modify, or fix the code.)
The scanf() family of functions returns the number of successful conversions. To detect input where the proper numeric value was followed by garbage, say 1.0 x, I asked sscanf() to ignore any whitespace after the number (whitespace means tabs, spaces, and newlines; '\t', '\n', '\v', '\f', '\r', and ' ' for the default C locale using ASCII character set), and try to convert a single additional character, dummy.
Now, if the line does contain anything besides whitespace after the number, sscanf() will store the first character of that anything in dummy, and return 2. However, because I only want lines that only contain the number and no dummy characters, I expect a return value of 1.
To detect the q or Q (but only as the first character on the line), we simply examine the first character in line, line[0].
If we included <string.h>, we could use e.g. if (strchr(line, 'q') || strchr(line, 'Q')) to see if there is a q or Q anywhere in the line supplied. The strchr(string, char) returns a pointer to the first occurrence of char in string, or NULL if none; and all pointers but NULL are considered logically true. (That is, we could equivalently write if (strchr(line, 'q') != NULL || strchr(line, 'Q') != NULL).)
Another function we could use declared in <string.h> is strstr(). It works like strchr(), but the second parameter is a string. For example, (strstr(line, "exit")) is only true if line has exit in it somewhere. (It could be brexit or exitology, though; it is just a simple substring search.)
In a loop, continue skips the rest of the loop body, and starts the next iteration of the loop body from the beginning.
In a loop, break skips the rest of the loop body, and continues execution after the loop.
EXIT_SUCCESS and EXIT_FAILURE are the standard exit status codes <stdlib.h> defines. Most prefer using 0 for EXIT_SUCCESS (because that is what it is in most operating systems), but I think spelling the success/failure out like that makes it easier to read the code.
I wouldn't use scanf-family functions for reading from stdin in general.
fgets is better since it takes input as a string whose length you specify, avoiding buffer overflows, which you can later parse into the desired type (if any). For the case of float values, strtof works.
However, if the specification for your deliverable or homework assignment requires the use of scanf with %f as the format specifier, what you can do is check its return value, which will contain a count of the number of format specifiers in the format string that were successfully scanned:
§ 7.21.6.2:
The [scanf] function returns the value of the macro EOF if an input failure occurs
before the first conversion (if any) has completed. Otherwise, the function returns the
number of input items assigned, which can be fewer than provided for, or even zero, in
the event of an early matching failure.
From there, you can diagnose whether the input is valid or not. Also, when scanf fails, stdin is not cleared and subsequent calls to scanf (i.e. in a loop) will continue to see whatever is in there. This question has some information about dealing with that.

K&R - section 1.9: understanding character arrays (and incidentally buffers)

Let's start with a very basic question about character arrays that I could not understand from the description in the book:
Does every character array end with '\0'?
Is the length of it always equal to the number of characters + 1 for '\0'?
meaning that if I specify a character array length of 10 I would be able to store only 9 characters that are not '\0'?
or does the '\0' come after the last array slot, so all 10 slots could be used for any character and an 11th non-reachable slot would contain the '\0' char?
Going further into the example in this section, it defines a getline() function that reads a string and counts the number of characters in it.
you can see the entire code here (in this example getline() was changed to gline(), since getline() is already defined in newer stdio.h libraries)
Here's the function:
int getline(char s[], int lim) {
int c, i;
for (i = 0; i < lim - 1 && (c = getchar()) != EOF && c != '\n'; ++i) {
s[i] = c;
}
if (c == '\n') {
s[i] = c;
++i;
}
s[i] = '\0';
return i;
}
It is explained that the array stores the input in this manner:
[h][e][l][l][o][\n][\0]
and the function will return a count of 6, including the '\n' char,
but this is only true if the loop exits because of a '\n' char.
If the loop exits because it has reached it's limit, it will return an array like this (as I understand this):
[s][n][a][z][z][y][\0]
now the count will also be 6.
Comparing both strings will return that they're equal when clearly "snazzy" is a longer word than "hello",
and so this code has a bug (by my personal requirements, as I would like to not count '\n' as part of the string).
Trying to fix this I tried (among many other things) to remove adding the '\n' char to the array and not incrementing the counter,
and I found out incidentally that when entering more characters than the array could store, the extra characters wait in the input buffer,
and would later be passed to the getline() function, so if I would enter:
"snazzy lolz\n"
it would use it up like this:
first getline() call: [s][n][a][z][z][y][\0]
second getline() call: [ ][l][o][l][z][\n][\0]
This change also introduced an interesting bug, if I try to enter a string that is exactly 7 characters long (including '\n') the program would quit straight away because it would pass a '\0' char to the next getline() call which would return 0 and would exit the while loop that calls getline() in main().
I am now confused as to what to do next.
How can I make it not count the '\n' char but also avoid the bug it created?
Many thanks
There is a convention in C that strings end with a null character. On that convention, all your questions are based. So
Does every character array end with '\0'?
No, It ends with \0 because the programmers put it there.
Is the length of it always equal to the number of characters + 1 for '\0'?
Yes, but only because of this convention. Thereto, for example you allocate one more byte (char) than the length of the string to accommodate this \0.
Strings are stored in character arrays such as char s[32]; or char *s = malloc(strlen(name) + 1);
Does every character array end with '\0'?
No; strings are a special case - they are character arrays with a nul (\0) terminator. This is more a convention than a feature of the language, although it is part of the language in-so-far that literal constant strings have a nul terminator. Moreover in a character string, the nul appears at the end of the string, not the end of the array - the array holding the string may be longer that the string it holds.
So the nul merely indicates the end of a string in a character array. If the character array represents data other than a string, then it may contain zero elements anywhere.
Is the length of it always equal to the number of characters + 1 for '\0'?
Again you are conflating strings with character arrays. They are not the same. A string happens to use a character array as a container. A string requires an array that is at least the length of the string plus one.
meaning that if I specify a character array length of 10 I would be
able to store only 9 characters that are not '\0'?
You will be able to store 10 characters of any value. If however you choose to interpret the array as a string, the string comprises only those characters up-to and including the first nul character.
or does the '\0' come after the last array slot, so all 10 slots could
be used for any character and an 11th non-reachable slot would contain
the '\0' char?
The nul is at the end of the string, not the end of the array, and certainly not after the end of the array.
Comparing both strings will return that they're equal when clearly
"snazzy" is a longer word than "hello",
In what world are those strings equal? They have equal length, not equal content.
and so this code has a bug (by my personal requirements, as I would
like to not count '\n' as part of the string).
Someone else's code not doing what you require is hardly a bug; that implementation is by design and is identical to the behaviour of the standard library fgets() function. If you require different behaviour, then you are of course free to implement to your needs; just omit the part:
if (c == '\n') {
s[i] = c;
++i;
}
To explicitly flush any remaining characters in the buffer the removed code above may be replaced with:
while(c != '\n') {
c = getchar() ;
}
One reason why you might not do that is that the data may be coming from a file redirected to stdin.
One reason for retaining the '\n' is that enables detection of incomplete input, which may be useful in some cases. For example you may want all the data in the line, regardless of length and despite a necessarily finite buffer length, a string returned without a newline would indicate that there is more day to be read, so you could then write code to handle that situation.

getchar() keeps reading a '\n'. What is going on?

I have a small program I'm writing to practice programming in C.
I want it to use the getchar(); function to get input from the user.
I use the following function to prompt for user input, then loop using getchar() to store input in an array:
The function is passed a pointer referencing a struct's member.
getInput(p->firstName); //The function is passed an argument like this one
void getInput(char * array)
{
int c;
while((c=getchar()) != '\n')
*array++ = c;
*array = '\0'; //Null terminate
}
This function is called multiple times, as it is a part of a function that creates a structure, and populates it's array members.
However when the program executes, The first two calls to it work fine, but any subsequent calls to this function will cause every-other call to getchar() to not wait for keyboard input.
After some debugging I traced the bug to be that getchar(); was for some reason reading in the '\n' character instead of waiting for input, the while loop test fails, and the function returns essentially an empty string.
I have done some research and keep finding to use
while(getchar() != '\n');
at the end of the function in order to properly flush stdin, however, this produces undesirable results, as the program will prompt again for more input after I type ENTER. Pressing ENTER again continues the program, but every-other subsequent calls continue to read in this mysterious '\n' character right off the bat, causing the test to fail, and resulting in empty strings whenever it comes time to print the contents of the the structure.
Could anyone explain to me what is going on here? Why does getchar() keep fetching a '\n' even though I supposedly cleared the input buffer? I have tried just placing a getchar(); statement at the beginning and end of the function, tried 'do while' loops, and taken other jabs at it, but I can't seem to figure this out.
The code you have written has several drawbacks. I'll try to explain them as it is unclear where your code is failing (probably outside the function you posted)
First of all, you don't check for EOF in getchar() result value. getchar(3) doesn't return a char precisely to allow to return al possible char values plus an extra one, EOF, to mark the end of file (this can be generated from a terminal by input of Ctrl-D in unix, or Ctrl-Z on windows machines) That case must be explicitly contempled in your code, as you'll convert the result to a char and will lose the extra information you received from the function. Read getchar(3) man page to solve this issue.
Second, you don't check for input of enough characters to fill all the array and overflow it. To the function you pass only a pointer to the beginning of the array, but nothing indicates how far it extends, so you can be overfilling past the end of its bounds, just overwritting memory that was not reserved for input purposes. This normally results in something called U.B. in the literature (Undefined Behaviour) and is something you must care of. This can be solved by passing a counter of valid positions to fill in the array and decrementing it for each valid position filled. And not allowing more input once the buffer has filled up.
On other side, you have a standar function that does exactly that, fgets(3) just reads one string array from an input file, and stores it on the pointer (and size) you pass to it:
char *fgets(char *buffer, size_t buffer_size, FILE *file_descriptor);
You can use it as in:
char buffer[80], *line;
...
while (line = fgets(buffer, sizeof buffer, stdin)) {
/* process one full line of input, with the final \n included */
....
}
/* on EOF, fgets(3) returns NULL, so we shall be here after reading the
* full input file */

K&R Exercise 1.16 - Limitation on line length

I'm learning C from K&R's "The C Programming Language" book. I'm doing the exercises specified in the book. I'm on exercise number 1.16, but I don't understand it.
Exercise 1.16:
Revise the main routine of the longest-line program so it will
correctly print the length of arbitrarily long input lines, and as
much as possible of the text.
My questions:
"...as much as possible of the text..." - is there some limitation on string length? Maybe in standard headers there's a variable with the max allowed value of string length?
"...the length of arbitrarily long input lines..." - but in the code MAXLINE is defined as 1000. It is limited size too. I see some solutions here, but in my opinion it is not solution decision, since on the former there is a restriction on length of a line (1000 characters).
Maybe I don't understood the task. My understanding is I must remove the 1000-character limitation.
It's a pretty early exercise in K&R, you're just supposed to do some minor changes to the code, not a total redesign of the code.
"...as much as possible of the text..."
is up to you to interpret. I'd do it by printing what's stored in the longest buffer. i.e. print out up to 1000 characters of the line. Again, it's an early exercise, with little introduction to dynamically allocated memory yet. And at the time K&R was written, storing away arbitrarily long text lines wasn't as feasible as it is today.
"...the length of arbitrarily long input lines..."
Is a hard requirement. You're supposed to find the correct length no matter how long it is (at least within the bounds of an int. )
One way to solve this problem is:
After the call to getline(), check if the last character read into the line buffer is a newline ('\n')
If it is, you read a complete line. The len variable is the correct length of the line(the return value of getline(), and no special consideration is needed compared to to original code.
If it is not , you did not read the entire line, and need to hunt for the end of this line. You add a while loop, calling getchar() until it returns a newline (or EOF), and count the number of characters you read in that loop. Just do len++ to count.
When the while loop is done, the new len is now the actual length of the line, but our buffer just has the first 999 characters of it.
As before, you store away (the copy() function call) the current line buffer (max 1000 chars) if this line is the longest so far.
When you're done, you print out the stored line as before (the longest buffer) and the max variable for the length.
Due to the above mentioned while loop that max length is now correct.
If the longest line indeed was longer than 1000 chars. you at least print out those first 999 chars - which is "as much as possible".
I'll not spoil it and post the code you need to accomplish this, but it is just 6 lines of code that you need to add to the longest-line program of exercise 1-16.
On modern machines "as much as possible of the text" is likely to be all of the text, thanks to automatically line-wrapping terminal programs. That book was written when teletype terminals were still in use. There is no limitation on string length other than perhaps memory limitations of the machine you're working on.
They're expecting you to add some kind of loop to read characters and look for newlines rather than assuming that a read into the MAXLINE sized buffer is going to contain a newline for sure.
here is my version:
int getline(char s[],int lim)
{
int c,i;
for(i=0;i<lim-1&&(c=getchar())!=EOF&&c!='\n';++i)
s[i]=c;
if(c=='\n')
{
s[i]=c;
++i;
}
if(c!=EOF)
{
while((c=getchar())!=EOF&&c!='\n')
i++;
}
s[i]='\0';
return i;
}
#define MAXLINE 1000
int len;
int max;
char line[MAXLINE];
char longest[MAXLINE];
max=0;
while((len=getline(line,MAXLINE))>1)
{
if(len>max)
{
max=len;
copy(longest,line);
}
}
if(max>0)
{
printf("%d:%s",max,longest);
}
return 0;
for some unknown reasons ,the example code doesn't work in my pc
particularly,when the condition is 'len>0',the loop won't end
i think the main reason is that when you type nothing,but you still have to press enter,so it is received as '\n',and the len is 1;
i think it satisfy the requirement that print the length of arbitrarily long input lines, and as much as possible of the text.
And it works like this
#include
main()
{
long tlength = 0;
short input, llength = 1;
while (llength > 0) {
llength = 0;
while ((input = getchar()) != EOF) {
++llength;
if (input == '\n')
break;
}
tlength = tlength + llength;
printf("\nLength of just above line : %5d\n\n", llength);
}
printf("\n\tLength of entire text : %8ld\n", tlength);
return 0;
}
According to me, This question only wants the length of each arbitrarily line + At last the length of entire text.
Try to run this code and tell me is it correct according to question because i too confuse in this problem.
I want to offer that this exercise actually makes more sense if imagine that the limit of the number of characters you can copy is very small -- say, 100 characters -- and that your program is supposed to judge between lines that are longer than that limit.
(If you actually change the limit so that it's very small, the code becomes easier to test: if it picks out the first line that hits that small limit, you'll know your code isn't working, whereas if it returns the first however-many characters of the longest line, it's working.)
Keep the part of the code that copies and counts characters until it hits a newline or EOF or the line-size-limit. Add code that picks up where this counting and copying leaves off, and which will keep counting even after the copying has stopped, so long as getchar() still hasn't returned an EOF or a newline.
My solution: just below the call to getLine
if ( line[len-1] != '\n' && line[len-1] != EOF) //if end of line or file wasnt found after max length
{
int c;
while ( ( c = getchar() ) != '\n' && c != EOF )
len++; //keep counting length until end of line or file is found
}
to test it, change MAXLINE to 25

Cannot create a program which will invert string

I am using Linux.
I am trying to write a program in c that will print a string backward.
Here is my code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main (){
char string[100];
printf ("Enter string:\n");
gets (string);
int length = strlen (string)-1;
for (length = length; length>=0; length--){
puts (string[length]);
}
}
And here is the error:
a.c:10: warning: passing argument 1 of ‘puts’ makes pointer from integer without a cast
/usr/include/stdio.h:668: note: expected ‘const char *’ but argument is of type ‘char’
/tmp/cc5rpeG7.o: In function `main':
a.c:(.text+0x29): warning: the `gets' function is dangerous and should not be used.
What should I do?
Forget that the function gets() exists - it is lethal. Use fgets() instead (but note that it does not remove the newline at the end of the line).
You want to put a single character at a time: use putchar() to write it to stdout. Don't forget to add a newline to the output after the loop.
Also, for (length = length; length >= 0; length--) is not idiomatic C. Use one of:
for ( ; length >= 0; length--)
for (length = strlen(string) - 1; length >= 0; length--)
for (int length = strlen(string) - 1; length >= 0; length--)
The last alternative uses a feature added to C99 (which was available in C++ long before).
Also, we could debate whether length is the appropriate name for the variable. It would be better renamed as i or pos or something similar because, although it is initialized to the length of the input, it is actually used as an array index, not as the length of anything.
Subjective: Don't put a space between the name of a function and its parameter list. The founding fathers of C don't do that - neither should you.
Why is gets() lethal?
The first Internet worm - the Morris worm from 1988 - exploited the fingerd program that used gets() instead of fgets(). Since then, numerous programs have been crashed because they used gets() and not fgets() or another alternative.
The fundamental problem is that gets() does not know how much space is available to store the data it reads. This leads to 'buffer overflows', a term which can be searched for in your favourite search engine that will return an enormous number of entries.
If someone types 150 characters of input to the example program, then gets() will store 150 characters in the array which has length 100. This never leads to happiness - it usually leads to a core dump, but with carefully chosen inputs - often generated by a Perl or Python script - you can probably get the program to execute arbitrary other code. This really matters if the program will ever be run by a user with 'elevated privileges'.
Incidentally, gets() is likely to be removed from the Standard C library in the next release (C1x - see n1494 from WG14). It won't vanish from actual C libraries for a long time yet (20 years?), but it should be replaced with this implementation (or something similar):
#undef NDEBUG
#include <assert.h>
char *gets(char *buffer)
{
assert("Probability of using gets() safely" == 0);
}
One other minor detail, discussed in part under the comments to the main question.
The code shown is clearly for C99; the declaration of length part way through the function is invalid in C89. Given that, it is 'OK' for the main() function not to explicitly return a value, because the C99 standard follows the lead of the C++ standard and allows you to omit the return from main() and the effect is the same as return(0); or return 0; at the end.
As such, the program in this question cannot strictly be faulted for not having a return at the end. However, I regard that as one of the more peculiar standardizing decisions, and would much prefer it if the standards had left that provision out - or done something more radical like allowing the ubiquitous but erroneous void main() observing that when control returns from that, the result is that a success status is returned to the environment. It isn't worth fighting to get that aspect of the standard changed - sadly - but as a personal style decision, I don't take advantage of the licence granted to omit the final return from main(). If the code has to work with C89 compilers, it should have the explicit return 0; at the end (but then the declaration of length has to be fixed too).
You can also use recursion to do it. I think it looks nicer then when using a loop.
Just call the method with your string, and before printing the char in the method, call the method again with the same string, minus the first char.
This will print out you string in reversed order.
First:
NEVER NEVER NEVER NEVER NEVER use gets(); it will introduce a point of failure in your code. There's no way to tell gets() how big the target buffer is, so if you pass a buffer sized to hold 10 characters and there's 100 characters in the input stream, gets() will happily store those extra 90 characters in the memory beyond the end of your buffer, potentially clobbering something important. Buffer overruns are an easy malware exploit; the Morris worm specifically exploited a gets() call in sendmail.
Use fgets() instead; it allows you to specify the maximum number of characters to read from the input stream. However, unlike gets(), fgets() will save the terminating newline character to the buffer if there's room for it, so you have to account for that:
char string[100];
char *newline;
printf("Enter a string: ");
fflush(stdout);
fgets(string, sizeof string, stdin);
newline = strchr(buffer, '\n'); // search for the newline character
if (newline) // if it's present
*newline = 0; // set it to zero
Now that's out of the way...
Your error is coming from the fact that puts() expects an argument of type char *, but you're passing an argument of type char, hence the "pointer from integer without cast" message (char is an integral type). To write a single character to stdout, use putchar() or fputc().
You should use putchar instead of puts
So this loop:
for (length = length; length>=0; length--){
puts (string[length]);
}
Will be:
for (length = length; length>=0; length--){
putchar (string[length]);
}
putchar will take a single char as a parameter and print it to stdout, which is what you want. puts, on the other hand, will print the whole string to stdout. So when you pass a single char to a function that expects a whole string (char array, NULL terminated string), compiler gets confused.
Use putc or putchar, as puts is specified to take a char* and you are feeding it a char.

Resources