Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > stream io in c

Reply
Thread Tools

stream io in c

 
 
Ron Ford
Guest
Posts: n/a
 
      07-30-2008
A question came up in a syntax which is a common C extension, and I wanted
to answer how to solve it in C, as I believe that the solution is less than
ten lines and one that I could step through with gdb, my untoward debugger.

%- Writing $00-$FF via Fortran
%-
%- I am in need for an important project to write out simple
%- unsigned-char values in the range $00 through $FF,
%- without any extraneous data being added:
%-
%- open: Open the file for "raw 8-bit binary output"
%- Sequential writes; nothing fancy.
%- write: Write out individual unsigned 8-bit values with no
%- extraneous data whatsoever being involved
%- (a single value results in a single value going to output
%- file)
%- close: Close the file with no extraneous data being appended.
%- Size: File size is only the number of actual values written!

I think the solution in c could be as easy as instantiating a loop from
zero to 255, putchar'ing in the body of the loop, then redirecting output
to a file. If the creation of the file comes from the source, I suspect it
would have to be in 'rb' mode.

But I don't know. I'm hoping to use 8-bit devices, so I better get a good
handle on it. Thanks and cheers,
--
Wealth - any income that is at least one hundred dollars more a year than
the income of one's wife's sister's husband. 6
H. L. Mencken
 
Reply With Quote
 
 
 
 
Ben Bacarisse
Guest
Posts: n/a
 
      07-30-2008
Ron Ford <> writes:

> A question came up in a syntax which is a common C extension, and I wanted
> to answer how to solve it in C, as I believe that the solution is less than
> ten lines and one that I could step through with gdb, my untoward debugger.
>
> %- Writing $00-$FF via Fortran
> %-
> %- I am in need for an important project to write out simple
> %- unsigned-char values in the range $00 through $FF,
> %- without any extraneous data being added:
> %-
> %- open: Open the file for "raw 8-bit binary output"
> %- Sequential writes; nothing fancy.
> %- write: Write out individual unsigned 8-bit values with no
> %- extraneous data whatsoever being involved
> %- (a single value results in a single value going to output
> %- file)
> %- close: Close the file with no extraneous data being appended.
> %- Size: File size is only the number of actual values written!
>
> I think the solution in c could be as easy as instantiating a loop from
> zero to 255, putchar'ing in the body of the loop, then redirecting output
> to a file.


The output stream should be binary. On a system where there is no
distinction between text and binary streams you don't really need to
bother, but I would do a:

if (freopen(NULL, stdout, "wb") != NULL) {
/* OK, of we go... */
}

to be sure. Of course, if you are writing to a device/file, just open
with mode "wb".

> If the creation of the file comes from the source, I suspect it
> would have to be in 'rb' mode.


Parse error. Can you re-phrase?

--
Ben.
 
Reply With Quote
 
 
 
 
Ron Ford
Guest
Posts: n/a
 
      07-31-2008
On Tue, 29 Jul 2008 19:49:54 -0600, Ron Ford posted:

> I think the solution in c could be as easy as instantiating a loop from
> zero to 255, putchar'ing in the body of the loop, then redirecting output
> to a file. If the creation of the file comes from the source, I suspect it
> would have to be in 'rb' mode.


I've tried some variations with this.

int i;
for (i = 0; i <= UCHAR_MAX; i++) putchar (i);

When stdout is redirected to a file, I get a file of size 257 bytes. I
wanted to see if that would also be the case if I created the file from
source, but I've got type mismatches here:

#include <stdio.h>
int main(void)
{
FILE *fp;
char name[]="text58.txt";

fp=&name;
int c;

if ((fp = fopen(fp, "rb")) == NULL)
{
printf("can't open %s\n", fp);
return 1;
}
else
{
for (c = 0; c <= 255; c ++) {
putc(c, fp);
}
fclose(fp);
}
return 0;
}
// gcc -o chars mkchars1.c

This compiles but gcc warns of incompatible pointer types. As of now, it
tells me it can't open. I can't find an example in K&R where they hard-code
a filename like this, so I'm a little stuck.

--
We are here and it is now. Further than that, all human knowledge is
moonshine. 3
H. L. Mencken
 
Reply With Quote
 
Ben Bacarisse
Guest
Posts: n/a
 
      07-31-2008
Ron Ford <> writes:

> On Tue, 29 Jul 2008 19:49:54 -0600, Ron Ford posted:
>
>> I think the solution in c could be as easy as instantiating a loop from
>> zero to 255, putchar'ing in the body of the loop, then redirecting output
>> to a file. If the creation of the file comes from the source, I suspect it
>> would have to be in 'rb' mode.

>
> I've tried some variations with this.
>
> int i;
> for (i = 0; i <= UCHAR_MAX; i++) putchar (i);
>
> When stdout is redirected to a file, I get a file of size 257 bytes. I
> wanted to see if that would also be the case if I created the file from
> source, but I've got type mismatches here:
>
> #include <stdio.h>
> int main(void)
> {
> FILE *fp;
> char name[]="text58.txt";
>
> fp=&name;


No need to set fp here. Just use name in the fopen call. This
assignment does no make sense anyway, since the types don't match.

> int c;
>
> if ((fp = fopen(fp, "rb")) == NULL)


Use fopen(name, "wb") here. You are opening for reading but plan to
write to this stream.

> {
> printf("can't open %s\n", fp);


printf("can't open %s\n", name);

> return 1;
> }
> else
> {
> for (c = 0; c <= 255; c ++) {
> putc(c, fp);
> }
> fclose(fp);
> }
> return 0;
> }
> // gcc -o chars mkchars1.c
>
> This compiles but gcc warns of incompatible pointer types. As of now, it
> tells me it can't open.


This is because you try to open it for reading and, presumably, the
file does not yet exist.

> I can't find an example in K&R where they hard-code
> a filename like this, so I'm a little stuck.


--
Ben.
 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      07-31-2008
Ron Ford <> writes:
> On Tue, 29 Jul 2008 19:49:54 -0600, Ron Ford posted:
>
>> I think the solution in c could be as easy as instantiating a loop from
>> zero to 255, putchar'ing in the body of the loop, then redirecting output
>> to a file. If the creation of the file comes from the source, I suspect it
>> would have to be in 'rb' mode.

>
> I've tried some variations with this.
>
> int i;
> for (i = 0; i <= UCHAR_MAX; i++) putchar (i);
>
> When stdout is redirected to a file, I get a file of size 257 bytes. I
> wanted to see if that would also be the case if I created the file from
> source, but I've got type mismatches here:


Please indent your code. Run it through "indent -kr" if necessary
(and if you have the "indent" program).

> #include <stdio.h>
> int main(void)
> {
> FILE *fp;
> char name[]="text58.txt";


Ok, so far, so good.

> fp=&name;


What?

fp is a FILE*, something you use for things like fopen. You're
assigning the address of a character array to it. What exactly is
"fp=&name;" intended to accomplish?

Just delete that line.

> int c;
>
> if ((fp = fopen(fp, "rb")) == NULL)


And here you're trying to use fp both to hold the result of fopen and
to hold the name of the file.

A FILE* and the name of a file are two entirely different things. You
pass the name of a file to fopen, and it gives you a FILE*. (A FILE*
is a pointer to some blob of information; you don't need to know the
details, which will vary from system to system.)

You already have a variable that holds the name of the file. Use it.

... fp = fopen(name, "rb") ...

> {
> printf("can't open %s\n", fp);


Mis-using fp again. You want name. And consider printing the error
message to stderr rather than stdout (that's not a high priority).

> return 1;


Add "#include <stdlib.h> and change this to "return EXIT_FAILURE;".
The value 1 isn't necessarily meaningful.

> }
> else
> {
> for (c = 0; c <= 255; c ++) {
> putc(c, fp);


You opened fp as an input file. Now you're trying to write to it.

If you wanted to write to the file, you should have used mode "wb"
rather than "rb".

> }
> fclose(fp);
> }
> return 0;
> }
> // gcc -o chars mkchars1.c
>
> This compiles but gcc warns of incompatible pointer types. As of now, it
> tells me it can't open. I can't find an example in K&R where they hard-code
> a filename like this, so I'm a little stuck.


--
Keith Thompson (The_Other_Keith) kst- <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
 
Reply With Quote
 
CBFalconer
Guest
Posts: n/a
 
      07-31-2008
Ron Ford wrote:
>

.... snip ...
>
> I've tried some variations with this.
>
> int i;
> for (i = 0; i <= UCHAR_MAX; i++) putchar (i);
>
> When stdout is redirected to a file, I get a file of size 257
> bytes. I wanted to see if that would also be the case if I
> created the file from source, but I've got type mismatches here:


The system you are using affects this. Some will expand '\n' to cr
and lf, others just to lf, others to just cr, or even a line with a
length flag. Some will insist on adding an EOF marker, some wont.
If your system is ASCII you wrote a '\n' with the 11th character.
You wrote a '\0' with the first.

What you ARE guaranteed is that you get back what you wrote
(assuming proper file modes in the open argument).

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


 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      07-31-2008
CBFalconer <> writes:
> Ron Ford wrote:
>>

> ... snip ...
>>
>> I've tried some variations with this.
>>
>> int i;
>> for (i = 0; i <= UCHAR_MAX; i++) putchar (i);
>>
>> When stdout is redirected to a file, I get a file of size 257
>> bytes. I wanted to see if that would also be the case if I
>> created the file from source, but I've got type mismatches here:

>
> The system you are using affects this. Some will expand '\n' to cr
> and lf, others just to lf, others to just cr, or even a line with a
> length flag. Some will insist on adding an EOF marker, some wont.
> If your system is ASCII you wrote a '\n' with the 11th character.
> You wrote a '\0' with the first.
>
> What you ARE guaranteed is that you get back what you wrote
> (assuming proper file modes in the open argument).


I believe that's guaranteed only for binary file (except that they may
be padded at the end with an arbitrary number of zero bytes). There's
no such guarantee for text files.

For example, on a system that uses character 26 as an end-of-file
marker for text files, if you write character 26 in the middle of an
output file, you'll only see half the file when you try to read it.

--
Keith Thompson (The_Other_Keith) kst- <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
 
Reply With Quote
 
Ron Ford
Guest
Posts: n/a
 
      07-31-2008
On Thu, 31 Jul 2008 01:26:25 +0000, Richard Heathfield posted:

> Ron Ford said:
>
>> On Tue, 29 Jul 2008 19:49:54 -0600, Ron Ford posted:
>>
>>> I think the solution in c could be as easy as instantiating a loop from
>>> zero to 255, putchar'ing in the body of the loop, then redirecting
>>> output
>>> to a file. If the creation of the file comes from the source, I suspect
>>> it would have to be in 'rb' mode.

>>
>> I've tried some variations with this.
>>
>> int i;
>> for (i = 0; i <= UCHAR_MAX; i++) putchar (i);
>>
>> When stdout is redirected to a file, I get a file of size 257 bytes. I
>> wanted to see if that would also be the case if I created the file from
>> source, but I've got type mismatches here:
>>
>> #include <stdio.h>
>> int main(void)
>> {
>> FILE *fp;
>> char name[]="text58.txt";
>>
>> fp=&name;

>
> Huh? fp has type FILE *, but &name has type char (*)[11]. How can it
> possibly make sense to you to assign the one to the other?


It would seem that I was trying to shoe-horn a char* into a file*. I
believed that the & operator hands the LHS the address of the object, in
this case, the name of a file.


> Serious
> question. What on earth do you think this assignment means? Why did you
> type it? (Answering that question might be the most important way you can
> learn from this thread.)


LHS is a pointer. Since I could not create a sensical thingamajig of type
FILE--everything I tried was a syntax error--I tried chars. There's no
guarantees on pointers like this; why would there be a prohibition?


>
>> int c;
>>
>> if ((fp = fopen(fp, "rb")) == NULL)

>
> fopen's first parameter is declared as being const char *, so why are you
> passing it a FILE *?
>
> Fixing that, we get:
>
> if((fp = fopen(name, "rb")) != NULL) /* but see below */
>
>> {
>> printf("can't open %s\n", fp);
>> return 1;

>
> Better: return EXIT_FAILURE; but you'll need <stdlib.h> for that.
>
>> }
>> else
>> {
>> for (c = 0; c <= 255; c ++) {
>> putc(c, fp);

>
> Wait a minute. Didn't you just try to open that file for reading? So why
> are you trying to write to it?
>
>> This compiles

>
> <cough> Yes, I know. But compilation does not indicate correctness. It
> merely indicates that the compiler has managed, sometimes against heavy
> odds, to produce an executable program. Unless the program is correct,
> however, the program won't make a lot of sense.



--
We are here and it is now. Further than that, all human knowledge is
moonshine. 3
H. L. Mencken
 
Reply With Quote
 
santosh
Guest
Posts: n/a
 
      07-31-2008
Ron Ford wrote:
> On Thu, 31 Jul 2008 01:26:25 +0000, Richard Heathfield posted:
>> Ron Ford said:


[ ... ]

>>> #include <stdio.h>
>>> int main(void)
>>> {
>>> FILE *fp;
>>> char name[]="text58.txt";
>>>
>>> fp=&name;

>>
>> Huh? fp has type FILE *, but &name has type char (*)[11]. How can it
>> possibly make sense to you to assign the one to the other?

>
> It would seem that I was trying to shoe-horn a char* into a file*.


You mean a FILE*?

In any case the FILE type holds critical data that is needed to operate
on the associated stream, like address of buffers, status flags etc.
You simply cannot stuff a FILE* object with the address of any object
other than a FILE, and hope get anything right. This is in fact an
illustration of a general rule in C, viz., object pointers of type T*
can only hold NULL or addresses of objects of type T. An exception is
the void* which can hold NULL or values of any object pointer type.

> I believed that the & operator hands the LHS the address of the
> object, in this case, the name of a file.


The & operator indeed computes the address of it's operand, but in your
case the address generated is the address of the array name, not the
address of it's first element. The values would be identical, but the
type differs.

>> Serious
>> question. What on earth do you think this assignment means? Why did
>> you type it? (Answering that question might be the most important way
>> you can learn from this thread.)

>
> LHS is a pointer. Since I could not create a sensical thingamajig of
> type FILE


That's what the fopen function is for.

> --everything I tried was a syntax error--I tried chars. There's
> no guarantees on pointers like this; why would there be a prohibition?


Because there are implementations were the sizes and representations of
various pointer types are different and a value of type A* need not
make any sense when interpreted as a value of type B*.

<snip>

 
Reply With Quote
 
Ron Ford
Guest
Posts: n/a
 
      07-31-2008
On Wed, 30 Jul 2008 18:35:48 -0700, Keith Thompson posted:

> Ron Ford <> writes:
>> On Tue, 29 Jul 2008 19:49:54 -0600, Ron Ford posted:
>>
>>> I think the solution in c could be as easy as instantiating a loop from
>>> zero to 255, putchar'ing in the body of the loop, then redirecting output
>>> to a file. If the creation of the file comes from the source, I suspect it
>>> would have to be in 'rb' mode.

>>
>> I've tried some variations with this.
>>
>> int i;
>> for (i = 0; i <= UCHAR_MAX; i++) putchar (i);
>>
>> When stdout is redirected to a file, I get a file of size 257 bytes. I
>> wanted to see if that would also be the case if I created the file from
>> source, but I've got type mismatches here:

>
> Please indent your code. Run it through "indent -kr" if necessary
> (and if you have the "indent" program).
>
>> #include <stdio.h>
>> int main(void)
>> {
>> FILE *fp;
>> char name[]="text58.txt";

>
> Ok, so far, so good.
>
>> fp=&name;

>
> What?
>
> fp is a FILE*, something you use for things like fopen. You're
> assigning the address of a character array to it. What exactly is
> "fp=&name;" intended to accomplish?
>
> Just delete that line.
>
>> int c;
>>
>> if ((fp = fopen(fp, "rb")) == NULL)

>
> And here you're trying to use fp both to hold the result of fopen and
> to hold the name of the file.
>
> A FILE* and the name of a file are two entirely different things. You
> pass the name of a file to fopen, and it gives you a FILE*. (A FILE*
> is a pointer to some blob of information; you don't need to know the
> details, which will vary from system to system.)
>
> You already have a variable that holds the name of the file. Use it.
>
> ... fp = fopen(name, "rb") ...
>
>> {
>> printf("can't open %s\n", fp);

>
> Mis-using fp again. You want name. And consider printing the error
> message to stderr rather than stdout (that's not a high priority).
>
>> return 1;

>
> Add "#include <stdlib.h> and change this to "return EXIT_FAILURE;".
> The value 1 isn't necessarily meaningful.
>
>> }
>> else
>> {
>> for (c = 0; c <= 255; c ++) {
>> putc(c, fp);

>
> You opened fp as an input file. Now you're trying to write to it.
>
> If you wanted to write to the file, you should have used mode "wb"
> rather than "rb".
>
>> }
>> fclose(fp);
>> }
>> return 0;
>> }
>> // gcc -o chars mkchars1.c
>>
>> This compiles but gcc warns of incompatible pointer types. As of now, it
>> tells me it can't open. I can't find an example in K&R where they hard-code
>> a filename like this, so I'm a little stuck.


Thanks, Keith, I seem to be doing much better:


#include <stdio.h>
int main(void)
{
FILE *fp;
char name[]="text58.txt";


int c;

if ((fp = fopen(name, "wb")) == NULL)
{
printf("can't open %s\n", fp);
return 1;
}
else
{
for (c = 0; c <= 255; c ++) {
putc(c, fp);
}
fclose(fp);
}
return 0;
}
// gcc -o chars mkchars2.c

It seems to compile and behave:

C:\MinGW\source> gcc -o chars mkchars2.c

C:\MinGW\source>chars

C:\MinGW\source>dir
Volume in drive C has no label.
Volume Serial Number is 486B-CFF3

Directory of C:\MinGW\source

[...]
07/31/2008 02:58 AM 309 mkchars1.c
07/30/2008 06:31 PM 257 text55.txt
07/30/2008 06:56 PM 2,592 mkchars1.o
07/30/2008 06:56 PM 19,581 new.exe
07/31/2008 03:06 AM 312 mkchars2.c
07/31/2008 03:06 AM 256 text58.txt
07/31/2008 03:06 AM 17,203 chars.exe
27 File(s) 108,824 bytes
3 Dir(s) 492,433,408 bytes free

I think this shows a difference between a way to get a file with 257 bytes
(> .txt) and one without an ultimate -1.

I'll tune up the minor points when I can follow through. Best regards,

--
We are here and it is now. Further than that, all human knowledge is
moonshine. 3
H. L. Mencken
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Convert DVD with subtitle stream to DivX with same subtitle stream(selectable) malise Software 2 04-17-2007 09:15 AM
what is the different between byte stream and character stream? dolphin Java 6 03-18-2007 01:58 PM
get stream mode flags from an opened stream Alexander Korsunsky C++ 1 02-17-2007 10:38 AM
How to GET multi-word input from a *file* stream as opposed to a *console* stream? sherifffruitfly@gmail.com C++ 9 04-27-2006 04:14 PM
Doing readline in a thread from a popen4('rsync ...') stream blocks when the stream ends. Rasmusson, Lars Python 1 04-30-2004 08:10 AM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57