I can't seem to google this because everything turns up as C++ or C# (Side note: any easy way to search for C specific?). All I'm trying to figure out is how to accept a console string input in such a way that I know it's length so I can return it in reverse order by indexing backwards through it with a for loop. I've had a little C++ experience in the past, but never really used console IO. Any help appreciated, thanks.
-
Use the [tag:c] tag in your search to narrow down the results, e.g. search for `"[c] console input"`. – Paul R Jan 25 '16 at 22:24
-
I meant in google, but that will probably help too, thanks. – Austin Jan 25 '16 at 22:25
-
3`fgets()` followed by `strlen()` are good starts. – chux - Reinstate Monica Jan 25 '16 at 22:25
-
1The top Google hits will most likely be on StackOverflow anyway. ;-) – Paul R Jan 25 '16 at 22:25
-
1I commonly use the appendix of K&R which lists all of the standard library functions. I have also found http://www.cplusplus.com/reference/clibrary/ rather reliable. – Jon Trauntvein Jan 25 '16 at 22:56
-
1POSIX has the getline function which seems to do what you want: It automatically enlarges the buffer if it is too short for the current line. – fuz Jan 25 '16 at 23:36
5 Answers
- Read with
fgets()
. - Cope with a possible trailing
\n
. - Find length
print in reverse.
char buf[100]; if (fgets(buf, sizeof buf, stdin) == NULL) Handle_EOF(); buf[strcspn(buf, "\n")] = '\0'; // lop off potential trailing \n size_t len = strlen(buf); while (len) { putc(buf[--len], stdout); }

- 143,097
- 13
- 135
- 256
-
-
@Austin The above is just a block of code. It still needs to be coded within a function like `int main(void) {` – chux - Reinstate Monica Jan 25 '16 at 23:01
-
I just tried putting this in a main block and got a ton of warnings and a linker command failed error. Not sure if this is how it was intended to be used. – Austin Jan 25 '16 at 23:01
-
-
@Austin" ton of warnings " is vague. The `Handle_EOF();` is simply a place-holder for code that is TBD. What do you want the code to do if `stdin` is closed?. Also not posted are `#include
` and any other include files. Sounds like you are looking for a complete compilable answer. I am leaving the basic things for you to complete. – chux - Reinstate Monica Jan 25 '16 at 23:04 -
I had the include statements, but not sure if I'm understanding what you're saying about Handle_EOF. Also I don't really need any error checking or special cases, if that's what you mean by stdin being closed. Sorry if I'm misunderstanding. – Austin Jan 25 '16 at 23:07
-
Basically all I want this to be able to do is take something like 'Hello' from console and return 'olleH', just for a single short word without any special characters. I think I can just ignore Handle_EOF() for this case. – Austin Jan 25 '16 at 23:10
-
@Austin "don't really need any error checking or special cases" --> Hmmm, Do not advise this approach to coding in C. Good luck. – chux - Reinstate Monica Jan 25 '16 at 23:13
-
Well if I was actually using this code for something I would be more careful, but this is just me trying to get a small script working to see if I can get anything to return properly. Literally my first C program ever. Thanks for your help. – Austin Jan 25 '16 at 23:16
-
So I just realized this seems to use regular input rather than a terminal input argument. If I compile the code and run in in terminal by trying, "./testcode hello" nothing happens. I need to then reenter "hello" after running the program. – Austin Jan 26 '16 at 00:03
-
@Austin That makes sense as the post said "accept a console string input" and "console IO". – chux - Reinstate Monica Jan 26 '16 at 00:18
-
Hmm, what's the proper term when you mean in-line input rather than within the program? – Austin Jan 26 '16 at 00:19
-
Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/101633/discussion-between-chux-and-austin). – chux - Reinstate Monica Jan 26 '16 at 00:21
You can use the fgets
function to read from the standard input.
char buf[80];
if (fgets(buf, 80, stdin) != NULL)
/* buf now contains the first 80 chars of the input */
Note: Do NOT use gets
because it is dangerous--it can overflow the input buffer.

- 10,998
- 9
- 46
- 75
You'll need to set aside some space to store the input; since you don't know ahead of time how big the input will be, you'll have to get a little creative with the storage.
A common strategy is to use a smallish, fixed-size buffer to read from the input stream, and a dynamic, resizable buffer to store the complete string if it winds up being longer than what the fixed-size buffer can handle. This way you can read an arbitrarily long input line in discrete chunks, and then paste the chunks together, resizing the target buffer as necessary.
You'll read the fixed-size chunks from the console in a loop and store it to the dynamic buffer until you see a newline, at which point you exit the input loop. Ideally, your fixed-size buffer should be large enough to handle most reasonable cases, such that you don't need to extend the dynamic buffer.
Excessively wordy (untested!) example:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define INPUT_BUF_SIZE 21 // handle strings up to 20 characters in length
int main( void )
{
/**
* Set aside a fixed-size buffer to store input from the console. This
* buffer cannot be resized after it has been allocated.
*/
char inputBuf[INPUT_BUF_SIZE];
/**
* Dynamically allocate a buffer to store the final string;
* its initial size is the same as the fixed buffer. If necessary,
* this buffer may be extended with the realloc function. We're using
* calloc instead of malloc to make sure the initial array contents
* are set to 0.
*/
char *finalBuf = calloc( INPUT_BUF_SIZE, sizeof *finalBuf );
/**
* finalBufSize tracks the total size of the dynamic buffer; finalBufLen
* tracks the length of the string currently stored in the buffer.
* These are not the same thing.
*/
size_t finalBufSize = INPUT_BUF_SIZE;
size_t finalBufLen = 0; // initially no string stored in the buffer
/**
* Read from standard input into the fixed-size buffer; loop until
* we see EOF or there's an error on input.
*/
while ( fgets( inputBuf, sizeof inputBuf, stdin ) )
{
/**
* If there isn't enough space left in finalBuf to store
* the latest chunk, double the size of finalBuf. This strategy
* minimizes the number of times you have to call realloc (which
* can be expensive).
*/
if ( strlen( inputBuf ) + finalBufLen > finalBufSize )
{
/**
* *Always* assign the result of realloc to a temp variable; if the
* call fails it will return NULL, and if you overwrite the value
* of finalBuf with NULL, you'll lose your only reference to any
* previously allocated memory.
*/
char *tmp = realloc( finalBuf, finalBufSize * 2 );
if ( tmp )
{
finalBuf = tmp;
finalBufSize *= 2;
}
else
{
/**
* We can't extend the buffer anymore, so we'll exit the
* loop and work with what we have.
*/
fprintf( stderr, "Could not extend storage buffer, exiting input loop\n" );
break;
}
}
/**
* Append the input string to the target buffer.
*/
strcat( finalBuf, inputBuf );
finalBufLen = strlen( finalBuf );
/**
* Did we see a newline in the last input chunk? If so,
* remove that newline from the final string (unless you
* want to include that in your reversal) and exit
* the loop.
*/
char *newline = strchr( finalString, '\n' );
if ( newline )
{
*newline = 0; // overwrite the newline character with the string terminator
break;
}
}
At this point, finalBuf
contains the input from the console, and you can reverse this string for output. Once you're done with it, release the memory that's been allocated with the free
function like so:
free( finalBuf );
Ideally you'd separate all that input handling into its own function, but this is a good enough illustration for now.

- 119,563
- 19
- 122
- 198
-
_Lots_ of good ideas and deserving of +1. 2 advanced issues that I do not agree: 1) The test for `'\n'` can be fooled with a preceding embedded null character. I do not see a good way to use `fgets()` to detect that. 2) Growing the buffer with no limit allows a hacker exploit. IMO, growing the buffer dynamically is a good idea, yet some upper bound is needed to prevent exploits. – chux - Reinstate Monica Jan 26 '16 at 17:52
-
@chux: Very good points. I admit I don't do this sort of thing a lot, and don't think about those kinds of issues. – John Bode Jan 26 '16 at 18:31
I wrote this function to put input from stdin into a buffer, for a cli project in uni.
It reads stdin char by char, it has no buffer overflow.
/*max line lenght*/
#define CLI_MAX_CMD_LEN 1024
/*get_line copies characters from stdin to buffer pointed by buf, stopping when a
carriage return or newline is encountered. It returns -1 on errors, otherwise strlen count */
int get_line(char *buf) {
int i,c;
for (i=0;i<CLI_MAX_CMD_LEN;i++) {
c = getchar();
switch (c) {
/*if terminating char is found an error has occurred*/
case '\0':
printf("found '\\0' instead of '\\n'\n");
return -1;
case '\t':
/*show possible commands*/
autocomplete(buf);
break;
case EOF:
/* prints the warning to stdout */
printf("End of file reached\n");
/* continue to execute following cases code */
case '\n':
case '\r':
buf[i] = '\0';
return i;
default :
buf[i] = c;
}
}
/*if end of buffer is reached put terminating char on last element
means that an error has occurred*/
buf[CLI_MAX_CMD_LEN] = '\0';
return -1;
}

- 1
- 3
-
-
It does not look different indeed. It is just meant to show how to get input char by char, which basically is what fgets does. You could also add a case for a special meaning char.. – StriDer99 Jan 25 '16 at 23:02
-
Using `int ch` rather than `char c` is better. `getchar()` typically returns 257 different values: 0-255 and `EOF`. Saving that result in a `char` loses the ability to distinguish `EOF` from a valid character input. – chux - Reinstate Monica Jan 25 '16 at 23:18
-
1) Rather than ` case -1:`, code should use ` case EOF:`. `EOF` is some negative value, potential it is not `-1`. 2) The fall through from `case -1` to `case '\n'` appears intentional. A comment here would remove doubt. – chux - Reinstate Monica Jan 26 '16 at 17:57
This is my solution but with recursion:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 20
void reverseW(char *, int);
int main()
{
char tmp[N], *string;
printf("Type a String:\n");
scanf("%s", tmp);
string=(char*)malloc((strlen(tmp)+1)*sizeof(char));
if (string==NULL)
{
printf("Error !\n");
exit(0);
}
strcpy(string, tmp);
reverseW(string, strlen(string));
printf("\nThe reverse of %s is %s !\n", tmp, string);
free(string);
return 0;
}
void reverseW(char *word, int size)
{
char tmp;
if (size>1)
{
tmp=word[0];
word[0]=word[size-1];
word[size-1]=tmp;
reverseW(word+1, size-2);
}
return;
}

- 936
- 2
- 18
- 30
-
`scanf("%s", tmp);` is like `gets(tmp)`. Both cause undefined behavior with too long an input and both should be avoided. – chux - Reinstate Monica Jan 25 '16 at 22:50
-
-
Recursion can be used, but this offers little advantage and uses a limiting `signed` size of type `int` rather than `size_t` which is best for arrays. See [ref](http://stackoverflow.com/a/198275/2410359) for a good approach. – chux - Reinstate Monica Jan 25 '16 at 23:00