stdin (keyboard) to file

P

Peter Blues

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;
}
 
V

vippstar

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 said:
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.
 
B

Ben Bacarisse

Peter Blues said:
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.
 
S

santosh

Peter said:
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?
 
P

Peter Nilsson

Peter Blues said:
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.
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.
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.
        }


This seems alright to me.

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

Checking the result here is waranted too.
 
P

Peter Blues

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


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.
 
W

Walter Roberson

Peter Blues said:
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.
 
J

Jack Klein

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
 
S

santosh

Peter said:
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.
 
C

CBFalconer

Peter said:
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.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,756
Messages
2,569,533
Members
45,007
Latest member
OrderFitnessKetoCapsules

Latest Threads

Top