0

I am currently studying input and output in C and I have found out that there are about a billion different ways to get input, such as, getch, getchar, gets and fgets, and the same with output (putchar, puts, fputs, etc.).

All these different methods of I/O are confusing me quite a bit, so I came on here to ask what the basic differences between the aforementioned functions are.

I also wrote a bit of code using these different functions and I commented in how I think they work, based on what I've learnt, but I'm not sure if my understanding is correct. I've read up on them in other places as well, but the explanations are very complicated and don't seem coherent.

So could anyone please tell me if I am using them correctly and if not, how I should use them and what are the main differences between them?

Here is my code:

#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <ctype.h>

void individualCharacters()
{
    char theChar;

    while ((theChar = getchar()) != '~') {  //    getchar() stores all characters in a line buffer as it is entered until newline is entered
        putchar(theChar);    // putchar() prints the characters in the line buffer and does not print a newline, line buffering depends on compiler
    }
}

void withoutF()
{
    char name[50];

    printf("What is your name? ");

    gets(name);    // receives a string until newline is entered, newline is then replaced with string terminator, array limit should not be passed

    puts("Hi");    // only prints one string at a time and adds the newline because gets() previously replaces the newline
    puts(name);
}

void withF()
{
    char name[50];

    printf("What is your name? ");

    fgets(name, 50, stdin);    // does add a newline so the newline takes up one space in the array, it stores input until either newline is entered or array limit is reached

    fputs("Hi ", stdout);    // does not print a newline but prints the string input up to the array limit
    fputs(name, stdout);
}

void main()
{
    //sum();

    //individualCharacters();

    //withoutF();

    //withF();

    //printRandomString();
}

These are just some functions I wrote that get input and display output in different ways, but I'm having trouble understanding why there are so many different ways of doing so.

If I have made any mistakes using the I/O functions, feel free to tell me so I can make amendments.

Thank you

AkThao
  • 582
  • 4
  • 7
  • 23
  • Some interesting read: http://stackoverflow.com/questions/1694036/why-is-the-gets-function-so-dangerous-that-it-should-not-be-used – Garf365 Aug 30 '16 at 10:10
  • Now I understand why `gets` is so dangerous. So if it is not used properly and you don't allow it enough memory, it will overflow without knowing it and that could potentially overwrite other important memory? – AkThao Aug 30 '16 at 10:20
  • Whereas, `fgets` just avoids that issue by ignoring any characters past the array limit. – AkThao Aug 30 '16 at 10:21

3 Answers3

2

getch() is a function that prompts to press a key,in which the character is not echoed back.

In contrast getche() will echo the character back.

gets() will read characters from stdin but is unsafe(use fgets() instead).

getchar() will return the next character it reads from stdin, it's same as calling getc() with stdin as an argument.

fgets() reads characters from a stream (like a file or stdin), and stores them as a C string into str until (num-1) characters have been read or newline or EOF is reached.

putch() writes a character to stdout. It's same as calling putc() with stdout as an argument.

puts() writes a C string pointed by str to stdout and appends a newline character. It starts copying till it reached the null-terminator(\0). Null-terminator is not printed.

fputs() writes a C string pointed by str to the stream, and is essentially like puts()

As for your code,try to avoid using gets(), as it is unsafe and use scanf(), same goes for puts(). Use printf() instead.

Here,give this a read: http://www.cplusplus.com/reference/cstdio/

I know it's C++ reference but the library functions are the same

Garf365
  • 3,619
  • 5
  • 29
  • 41
Zvonimir Rudinski
  • 435
  • 1
  • 5
  • 15
  • Thank you very much, that's cleared up some confusion in terms of what the functions all do. When you said 'getchar() will return the next character it reads from stdin', what exactly does that mean? – AkThao Aug 30 '16 at 10:26
  • It means you use getchar() in a loop.Like this: `#include int main() { int nc = 0; for(;;) { do ++nc; while (getchar() != '\n'); printf("Character count is:%d\n%d\n", nc - 1); nc = 0; } }` – Zvonimir Rudinski Aug 30 '16 at 10:28
2

fgets - reads up to SIZE-1 characters from a specified stream into a buffer, including the trailing newline if there's room. Adds a 0 terminator to the end of the buffer, making it a valid C string:

char buffer[SIZE];

if ( fgets( buffer, sizeof buffer, stdin ) ) // read from standard input
  do_something_with( buffer );
else
  error();

On success, fgets returns the address of the input buffer. On failure or end-of-file, it returns NULL.

fgetc - reads a single character from the specified input stream and returns it:

FILE *input_stream = fopen( "some_file", "r" );
int c;
while ( (c = fgetc( input_stream )) != EOF )
  do_something_with( c );

gets - was deprecated after C99, removed completely from C2011. Like fgets, it would read a sequence of characters from standard input into a buffer and add a 0 terminator, but unlike fgets it did not provide a mechanism to limit input, making it a popular malware exploit. Also, it would not store a trailing newline to the buffer. Using it was guaranteed to introduce a point of failure in your code. Pretend you've never heard of it.

getc - identical to fgetc, except that it may be implemented as a macro.

getchar - reads a single character from standard input:

int c;
...
while( (c = getchar()) != EOF )
  do_something_with( c );

fputs - writes a string to the specified output stream:

char str[SIZE];
...
fputs( str, output_stream ); 

fputc - writes a single character to the specified output stream:

while ( i < strsize )
  fputc( str[i], output_stream );

putc - identical to fputc, except that it may be implemented as a macro

putchar - writes a single character to standard output.

John Bode
  • 119,563
  • 19
  • 122
  • 198
  • Thank you for your answer, it all makes a lot more sense to me now. I still have a couple of questions. If `fgetc` and `getchar` both read a single character from input, how are they different (apart from syntax) and when should each of them be used (same question with `fputc` and `putchar`)? Also, is there a difference between 'standard output' and 'output stream', because I've looked them up but I've seen them being used interchangeably? – AkThao Aug 31 '16 at 09:54
  • `getchar` only reads from the standard input stream (`stdin`). `fgetc` reads from any stream you specify. `stdin`, `stdout`, and `stderr` are predefined input and output streams that usually refer to your console in an interactive session. – John Bode Aug 31 '16 at 12:04
  • Oh ok, so `fgets/fgetc` and `fputs/fputc` are best for all-purpose general standard I/O? – AkThao Aug 31 '16 at 19:07
  • @kashveyron: It really depends on what you want to do. If you want to read/write *formatted* text, or deal with non-character types (integers, floats, etc.), you'd use `fscanf/fprintf` or `scanf/printf` (same deal; the first pair read or write the stream you specify, the second work with standard input and output). If you want to read or write *binary* data, you'd use `fread/fwrite`. There's no one-size-fits-all solution; it depends on the problem you're trying to solve. That's why there are so many different I/O routines in the first place. – John Bode Aug 31 '16 at 19:19
  • That makes better sense to me now, it looks like I've just got to learn all these different methods over time, as it's difficult to understand it all in one go :) So thank you for your help. – AkThao Sep 01 '16 at 09:14
1
fgets
char * fgets ( char * str, int num, FILE * stream );
Get string from stream

Reads characters from stream and stores them as a C string into str until (num-1) characters have been read or either a newline or a the End-of-File is reached, whichever comes first. A newline character makes fgets stop reading, but it is considered a valid character and therefore it is included in the string copied to str. A null character is automatically appended in str after the characters read to signal the end of the C string.

fputs

int fputs ( const char * str, FILE * stream );
Write string to stream

Writes the string pointed by str to the stream. The function begins copying from the address specified (str) until it reaches the terminating null character ('\0'). This final null-character is not copied to the stream.

getchar

function
<cstdio>
int getchar ( void );

Get character from stdin. Returns the next character from the standard input (stdin). It is equivalent to getc with stdin as its argument.

putchar


function
<cstdio>
int putchar ( int character );

Write character to stdout Writes character to the current position in the standard output (stdout) and advances the internal file position indicator to the next position. It is equivalent to putc(character,stdout).

gets: from standard input to memory

puts: from memory to standard input

Example : 

#include<stdio.h> 
void main( ) 
{ 
char name[10]; 
printf("What is your first and last name?"); 
gets(name); 
puts(name); 
}
khakishoiab
  • 9,673
  • 2
  • 16
  • 22
  • Oh, so that's why with `fgets`, if I specify an array of 50 elements and in my program, I input 50 characters, it only prints 49 characters? Because the newline is the last character? – AkThao Aug 30 '16 at 10:35
  • In my code, when I use `name` as a variable and I pass it as an argument to `fgets`, `str` is actually a pointer to `name`? – AkThao Aug 30 '16 at 10:37
  • fgets is supposed to be able to read from any file on disk, not just from the user's keyboard (or other "standard input" device). whenever we call fgets, we'll just pass in a variable called stdin, defined in stdio.h, which refers to "standard input". This effectively tells the program to read from the keyboard. fgets will read input until it either has no more room to store the data or until the user hits enter. – khakishoiab Aug 30 '16 at 11:29
  • Oh ok, now I get it, so standard input is just any kind of common input. Thank you. – AkThao Aug 30 '16 at 12:39