stdin (keyboard) to file

Discussion in 'C Programming' started by Peter Blues, Feb 6, 2008.

  1. Peter Blues

    Peter Blues Guest

    I'm trying to write from keyboard input to a txt file. I don't understand
    why the while loop below doesn't achieve this.
    I..
    1: open the file for writing through FILE pointer outstream
    2: I get chars one at a time as ints(ascii) through fd using getchar()
    3: Copy from fd to FILE *outstream using fputc()
    4: Finally close outstream.

    I feel the problem lies in step 2 and 3. Can someone please explain
    where the following code is wrong.

    #include <stdio.h>

    int main(void) {

    int fd;
    char file_name[80];
    FILE *outstream;

    printf("File Name: \n");
    scanf("%79s", file_name);

    if((outstream = fopen(file_name, "w")) == NULL) {
    fprintf(stderr, "open %s for writing failed ", file_name);
    perror("because");
    return 1;
    }

    while((fd = getchar()) != EOF)
    fputc(fd, outstream);

    fclose(outstream);

    return 0;
    }
     
    Peter Blues, Feb 6, 2008
    #1
    1. Advertising

  2. Peter Blues

    Guest

    On Feb 6, 3:14 am, Peter Blues <> wrote:
    > I'm trying to write from keyboard input to a txt file. I don't understand
    > why the while loop below doesn't achieve this.
    > I..
    > 1: open the file for writing through FILE pointer outstream
    > 2: I get chars one at a time as ints(ascii) through fd using getchar()
    > 3: Copy from fd to FILE *outstream using fputc()
    > 4: Finally close outstream.

    You are a bit confused about what int and ascii is.
    > I feel the problem lies in step 2 and 3. Can someone please explain
    > where the following code is wrong.
    >
    > #include <stdio.h>
    >
    > int main(void) {
    >
    > int fd;

    'fd' as a name for an int object is a bad name, because 'int fd;' is
    commonly used in UNIX programming where fd stands for file descriptor.
    > char file_name[80];

    You could change that to FILENAME_MAX
    > FILE *outstream;
    >
    > printf("File Name: \n");
    > scanf("%79s", file_name);

    You read at most 79 characters but the last character of file_name is
    not initialized.
    Either do file_name[79] = 0; or define file_name as char file_name[80]
    = {0};
    You also don't check the return value of scanf but I don't think that
    is importand for such small code.
    (althought if this code is part of a bigger project, I suggest you do
    check the return value)
    >
    > if((outstream = fopen(file_name, "w")) == NULL) {
    > fprintf(stderr, "open %s for writing failed ", file_name);
    > perror("because");

    How about this
    fprintf(stderr, "open %s for writing failed because %s\n", file_name,
    strerror(errno));
    You need to include <string.h> for strerror().
    > return 1;

    It is not portable to return 1 from main.
    The portable values are 0, EXIT_SUCCESS and EXIT_FAILURE, again, for a
    small snippet it does not matter much.
    If it's a bigger project change it.
    > }
    >
    > while((fd = getchar()) != EOF)
    > fputc(fd, outstream);

    This seems alright to me.
    >
    > fclose(outstream);
    > return 0;
    >
    > }


    I believe your problem lies in your confusion about keyboard being
    stdin.
    stdin is just an input file stream.
    C does not define a 'keyboard'. If you expect the above snippet to
    capture keystrokes.. then you are out of luck as far as ISO C is
    concerned.
    You can, however use a system specific function to capture them, which
    is off-topic for this newsgroup.
    try a newsgroup whose subject is relevant to your system.
     
    , Feb 6, 2008
    #2
    1. Advertising

  3. Peter Blues <> writes:

    > I'm trying to write from keyboard input to a txt file. I don't understand
    > why the while loop below doesn't achieve this.


    It does. You need to say what you think is wrong. It is likely to do
    with getting both the file name and the data from the same place
    (stdin) but I won't say more until you say what you think is wrong!

    > I..
    > 1: open the file for writing through FILE pointer outstream
    > 2: I get chars one at a time as ints(ascii) through fd using getchar()
    > 3: Copy from fd to FILE *outstream using fputc()
    > 4: Finally close outstream.


    All good.

    > #include <stdio.h>
    >
    > int main(void) {


    Note that you have avoided lots of the beginner errors that are so
    common so it seems almost churlish to comment, but...

    > int main(void) {
    >
    > int fd;


    Not an obvious name for an input character!

    > char file_name[80];
    > FILE *outstream;
    >
    > printf("File Name: \n");
    > scanf("%79s", file_name);


    You should check the return from scanf. You can't (safely) use the
    file name if the input operation failed.

    >
    > if((outstream = fopen(file_name, "w")) == NULL) {
    > fprintf(stderr, "open %s for writing failed ", file_name);
    > perror("because");
    > return 1;


    Better is 'return EXIT_FAILURE;' (you need to #include <stdlib.h>).

    > }
    >
    > while((fd = getchar()) != EOF)
    > fputc(fd, outstream);
    >
    > fclose(outstream);
    >
    > return 0;
    > }


    --
    Ben.
     
    Ben Bacarisse, Feb 6, 2008
    #3
  4. Peter Blues

    santosh Guest

    Peter Blues wrote:

    > I'm trying to write from keyboard input to a txt file. I don't
    > understand why the while loop below doesn't achieve this.
    > I..
    > 1: open the file for writing through FILE pointer outstream
    > 2: I get chars one at a time as ints(ascii) through fd using getchar()
    > 3: Copy from fd to FILE *outstream using fputc()
    > 4: Finally close outstream.
    >
    > I feel the problem lies in step 2 and 3. Can someone please explain
    > where the following code is wrong.
    >
    > #include <stdio.h>
    >
    > int main(void) {
    >
    > int fd;


    This is a confusing name for a variable that is supposed to store a
    character value or EOF.

    > char file_name[80];
    > FILE *outstream;
    >
    > printf("File Name: \n");
    > scanf("%79s", file_name);


    scanf is a tricky function to use safely. I suggest using fgets() to
    capture lines (or partial lines) and then processing as necessary.

    if (fgets(file_name, FILENAME_MAX, stdin) == NULL) printf("Error.\n");
    else if (strchr(file_name, '\n') == NULL) {
    /* fgets() has got only a partial line. You might want to retrieve
    the rest of the line, but one thing at a time.
    */
    }

    > if((outstream = fopen(file_name, "w")) == NULL) {
    > fprintf(stderr, "open %s for writing failed ", file_name);
    > perror("because");
    > return 1;


    One is not a strictly portable return status. Use 0 or EXIT_SUCCESS or
    EXIT_FAILURE. Both the symbolic constants are in stdlib.h.

    > }
    >
    > while((fd = getchar()) != EOF)
    > fputc(fd, outstream);


    fputc() can fail too, returning EOF if so.

    > fclose(outstream);
    >
    > return 0;
    > }


    It's not immediately obvious what your problem is. In what way does your
    program fail?
     
    santosh, Feb 6, 2008
    #4
  5. wrote:
    > Peter Blues <> wrote:>
    > > I'm trying to write from keyboard input to a txt file.
    > > I don't understand why the while loop below doesn't
    > > achieve this.
    > > I..
    > > 1: open the file for writing through FILE pointer outstream
    > > 2: I get chars one at a time as ints(ascii) through fd
    > > using getchar()
    > > 3: Copy from fd to FILE *outstream using fputc()
    > > 4: Finally close outstream.

    >
    > You are a bit confused about what int and ascii is.
    >
    > > I feel the problem lies in step 2 and 3. Can someone
    > > please explain where the following code is wrong.
    > >
    > > #include <stdio.h>
    > >
    > > int main(void) {
    > >
    > >         int fd;

    >
    > 'fd' as a name for an int object is a bad name,
    > because 'int fd;' is commonly used in UNIX programming
    > where fd stands for file descriptor.
    >
    > >         char file_name[80];

    >
    > You could change that to FILENAME_MAX


    You mean change the magic constant 80. Also, switch to
    fgets over scanf.

    > >         FILE *outstream;

    >
    > >         printf("File Name: \n");
    > >         scanf("%79s", file_name);

    >
    > You read at most 79 characters but the last character of
    > file_name is not initialized.


    %s will null terminate the string. The problem may be that
    %s will stop reading after the first whitespace character.

    > Either do file_name[79] = 0; or define file_name as char
    > file_name[80] = {0};


    Neither is necessary.

    > You also don't check the return value of scanf but I
    > don't think that is importand for such small code.


    I do.

    > (althought if this code is part of a bigger project,
    > I suggest you do check the return value)


    Given that it's not clear what the error actually is,
    checking the return value will rule out certain
    candidates.

    > >  if((outstream = fopen(file_name, "w")) == NULL) {
    > >   fprintf(stderr, "open %s for writing failed ", file_name);
    > >   perror("because");

    >
    > How about this
    > fprintf(stderr, "open %s for writing failed because %s\n", file_name,
    > strerror(errno));
    > You need to include <string.h> for strerror().>                 return 1;
    >
    > It is not portable to return 1 from main.
    > The portable values are 0, EXIT_SUCCESS and EXIT_FAILURE,
    > again, for a small snippet it does not matter much.


    Either it matters or it doesn't. False lazyness is preventable
    and it starts with the small.

    > If it's a bigger project change it.
    >         }
    >
    > >         while((fd = getchar()) != EOF)
    > >                 fputc(fd, outstream);

    >
    > This seems alright to me.


    Check the return value from fputc. Apart from that, it
    looks ok.

    > >         fclose(outstream);


    Checking the result here is waranted too.

    > >         return 0;

    >
    > > }


    --
    Peter
     
    Peter Nilsson, Feb 6, 2008
    #5
  6. Peter Blues

    Peter Blues Guest

    On Wed, 06 Feb 2008 07:13:43 +0530, santosh wrote:

    >> while((fd = getchar()) != EOF)
    >> fputc(fd, outstream);

    >
    > fputc() can fail too, returning EOF if so.
    >
    >> fclose(outstream);
    >>
    >> return 0;
    >> }

    >
    > It's not immediately obvious what your problem is. In what way does your
    > program fail?


    An example: I open an empty filename.txt, when code is run I
    enter filename.txt file. I then enter arbitrary characters from the
    keyboard then exit with control c. I then return to the gedit which gives
    the message filename.txt has changed do you want to reload which I do but
    no characters appear in the file.
     
    Peter Blues, Feb 6, 2008
    #6
  7. In article <47a922aa$0$13262$>,
    Peter Blues <> wrote:

    >An example: I open an empty filename.txt, when code is run I
    >enter filename.txt file. I then enter arbitrary characters from the
    >keyboard then exit with control c. I then return to the gedit which gives
    >the message filename.txt has changed do you want to reload which I do but
    >no characters appear in the file.


    Control-C seldom signals end-of-file. Usually control-C signals
    interruption. When you interrupt the program, by default you
    would be requesting to abort the program -- in which case flushing
    of the output buffers is not certain to happen. Indeed, if you
    interrupt the program, transfering the entered data from the
    operating system to the program is not certain to happen.

    --
    "All is vanity." -- Ecclesiastes
     
    Walter Roberson, Feb 6, 2008
    #7
  8. Peter Blues

    Jack Klein Guest

    On Tue, 5 Feb 2008 17:28:46 -0800 (PST), wrote in
    comp.lang.c:

    > On Feb 6, 3:14 am, Peter Blues <> wrote:
    > > I'm trying to write from keyboard input to a txt file. I don't understand
    > > why the while loop below doesn't achieve this.
    > > I..
    > > 1: open the file for writing through FILE pointer outstream
    > > 2: I get chars one at a time as ints(ascii) through fd using getchar()
    > > 3: Copy from fd to FILE *outstream using fputc()
    > > 4: Finally close outstream.

    > You are a bit confused about what int and ascii is.
    > > I feel the problem lies in step 2 and 3. Can someone please explain
    > > where the following code is wrong.
    > >
    > > #include <stdio.h>
    > >
    > > int main(void) {
    > >
    > > int fd;

    > 'fd' as a name for an int object is a bad name, because 'int fd;' is
    > commonly used in UNIX programming where fd stands for file descriptor.
    > > char file_name[80];

    > You could change that to FILENAME_MAX
    > > FILE *outstream;
    > >
    > > printf("File Name: \n");
    > > scanf("%79s", file_name);

    > You read at most 79 characters but the last character of file_name is
    > not initialized.


    What is the source of the incorrect information you have been coming
    up with lately? Where did you get the idea that scanf() will not
    terminate any successful input with '\0'?

    However many characters scanf() reads from the standard input stream,
    up to and including 79, it will place a '0' terminator at the end.

    > Either do file_name[79] = 0; or define file_name as char file_name[80]
    > = {0};


    Your second suggestion is good advice, not because it is needed if the
    scanf() succeeds, because however many characters it retrieves will
    have a '0' terminator added at the end. It is a good idea in case
    scanf() fails to read any characters at all, due encountering an
    end-of-file condition, if will call fopen() with "", instead of an
    uninitialized array of characters.

    Your first suggestion, file_name[79] = 0; (prefer '\0' myself), does
    not protect against this problem.

    --
    Jack Klein
    Home: http://JK-Technology.Com
    FAQs for
    comp.lang.c http://c-faq.com/
    comp.lang.c++ http://www.parashift.com/c -faq-lite/
    alt.comp.lang.learn.c-c++
    http://www.club.cc.cmu.edu/~ajo/docs/FAQ-acllc.html
     
    Jack Klein, Feb 6, 2008
    #8
  9. Peter Blues

    santosh Guest

    Peter Blues wrote:

    > On Wed, 06 Feb 2008 07:13:43 +0530, santosh wrote:
    >
    >>> while((fd = getchar()) != EOF)
    >>> fputc(fd, outstream);

    >>
    >> fputc() can fail too, returning EOF if so.
    >>
    >>> fclose(outstream);
    >>>
    >>> return 0;
    >>> }

    >>
    >> It's not immediately obvious what your problem is. In what way does
    >> your program fail?

    >
    > An example: I open an empty filename.txt, when code is run I
    > enter filename.txt file. I then enter arbitrary characters from the
    > keyboard then exit with control c.


    In most systems CONTROL-C usually leads to the OS terminating the
    program, which might result in the file not being properly written. Use
    CONTROL-D under UNIX or CONTROL-Z under DOS to signal end-of-file which
    is what you want to exit the read loop.

    > I then return to the gedit which
    > gives the message filename.txt has changed do you want to reload which
    > I do but no characters appear in the file.
     
    santosh, Feb 6, 2008
    #9
  10. Peter Blues

    CBFalconer Guest

    Peter Blues wrote:
    >
    > I'm trying to write from keyboard input to a txt file. I don't
    > understand why the while loop below doesn't achieve this.
    > I..
    > 1: open the file for writing through FILE pointer outstream
    > 2: I get chars one at a time as ints(ascii) through fd using
    > getchar()
    > 3: Copy from fd to FILE *outstream using fputc()
    > 4: Finally close outstream.


    On most systems you can simply use the redirection of stdin and
    stdout, as follows:

    #include <stdio.h>

    int main(void) {

    int ch; /* note int, not char */

    while (EOF != (ch = getc(stdin))} putc(ch);
    return 0;
    }

    and you run it with:

    progname > outfile

    followed by typing the required data. End with a ctrl-Z (for
    windoze) or ctrl-D (for linux) to signal end-of-file.

    Later, if you wish, you can investigate using the file open/close
    statements, and get the necessary information from the command
    line. Then the main parameters will no longer be void.

    --
    [mail]: Chuck F (cbfalconer at maineline dot net)
    [page]: <http://cbfalconer.home.att.net>
    Try the download section.



    --
    Posted via a free Usenet account from http://www.teranews.com
     
    CBFalconer, Feb 6, 2008
    #10
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Wodny

    Return stdin to keyboard

    Wodny, May 12, 2005, in forum: C++
    Replies:
    2
    Views:
    427
    Wodny
    May 12, 2005
  2. herrcho
    Replies:
    23
    Views:
    1,318
  3. Johnathan Doe

    peek at stdin, flush stdin

    Johnathan Doe, May 15, 2004, in forum: C Programming
    Replies:
    5
    Views:
    25,042
    Chatoyer
    May 17, 2013
  4. Replies:
    3
    Views:
    764
    Chris Dollin
    Aug 31, 2005
  5. Mad Scientist Jr
    Replies:
    5
    Views:
    401
    Mad Scientist Jr
    Apr 17, 2006
Loading...

Share This Page