-3

This is the c code that I wrote to write something to a file. But when I compile it, the process terminates without getting input for the contents. What is the error?

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

void main()
{
    FILE *fp;
    char name[20];
    char content[100];

    printf("Enter file name:\n");
    scanf("%s", name);

    printf("Enter the content:\n");
    gets(content);

    fp = fopen(name, "w");

    fprintf(fp, "%s", content);
    fclose(fp);
}
  • Is the input you enter for the file-name no more than 19 characters? – Some programmer dude Sep 23 '18 at 17:37
  • 2
    Also, don't use `gets`! [It's a dangerous function](https://stackoverflow.com/questions/1694036/why-is-the-gets-function-so-dangerous-that-it-should-not-be-used), and has therefore been removed entirely from the C specification. For a portable alternative use [`fgets`](https://en.cppreference.com/w/c/io/fgets) instead. – Some programmer dude Sep 23 '18 at 17:38
  • @Someprogrammerdude no, just demo.txt – Basanta Goswami Sep 23 '18 at 17:38
  • 1
    Why use scanf() for the first string, and gets() for the second? You must check the result returned from system calls like fopen() for errors before attempting further operations. Also, don't use gets() anyway - it's unsecure and deprecated. – Martin James Sep 23 '18 at 17:38
  • I would still recommend you to use `scanf("%19s", name);` just in case (remember that the string terminator needs one character). And check what `scanf` *returns* :) – Some programmer dude Sep 23 '18 at 17:39
  • 1
    The `scanf` call is leaving the trailing newline from console input in your input stream, which is then consumed by the `gets` call (and amounting to nothing in `content` worth keeping). In short, your `content` never reads your content; it stop after the preceding newline. You need to consume that newline before reading the next line (preferably with something *other* than `gets`). – WhozCraig Sep 23 '18 at 17:43
  • Also, you should note that there are a LOT of SO questions about scanf() leaving a newline char in the input buffer. That would cause the gets() to return nothing, (or a segfault, or some other horribru UB when it overflows the buffer). – Martin James Sep 23 '18 at 17:44

1 Answers1

0

It blew right past the gets line. Why? Because the scanf family has lots and lots of problems. Avoid them.

Specifically it tends to leave input on the buffer. In this case scanf("%s", name); read in all the text and left a newline on stdin. Then gets dutifully read that newline... and throws it out because that's how gets behaves. We can see this if we print name and content just before gets.

printf("name: '%s'\n", name);
printf("content: '%s'\n", content);

name: 'foo'
content: ''

Then your program dutifully writes nothing to the file.

Instead, use fgets to read entire lines, and sscanf to parse them. This avoids the danger of leaving input on the buffer.

printf("Enter file name:\n");
fgets(name, sizeof(name), stdin);

printf("Enter the content:\n");
fgets(content, sizeof(content), stdin);

fgets does not strip newlines, so you'll have to do that yourself. There's a variety of ways to do it.

void trim( char *string, char to_trim ) {
    size_t len = strlen(string);
    if( len == 0 ) {
        return;
    }
    size_t last_idx = len -1;
    if( string[last_idx] == to_trim ) {
        string[last_idx] = '\0';
    }
}

I prefer this approach because it only removes the newline if it's the final character.

Finally, always check your file operations. You're not checking if the fopen succeeded. If it fails for whatever reason you'll get another mysterious error. In my case the name I was using for testing already existed as a directory.

#include <string.h>  // for strerror
#include <errno.h>   // for errno

fp = fopen(name, "w");
if( fp == NULL ) {
    fprintf(stderr, "Could not open '%s' for writing: %s.\n", name, strerror(errno));
    return 1;
}
Schwern
  • 153,029
  • 25
  • 195
  • 336