string question

B

Bill Cunningham

Hello I did my homework and came to the conclusion that I thought I
would ask this question to the community. I have this function.

void chunk (char file1[],char file2[],char bytes)

Now what I want this to do is read file1[] and write to file2[] the number
of bytes in the 3rd parameter. The thing is that fopen takes a string
literal as its first parameter. I want to pass char file1[] to fopen. Is
there a conversion function somewhere that would allow me to pass to fopen
char file1[] ? I hope I am making myself clear.

Bill
 
K

Keith Thompson

Bill Cunningham said:
Hello I did my homework and came to the conclusion that I thought I
would ask this question to the community. I have this function.

void chunk (char file1[],char file2[],char bytes)

Now what I want this to do is read file1[] and write to file2[] the number
of bytes in the 3rd parameter. The thing is that fopen takes a string
literal as its first parameter. I want to pass char file1[] to fopen. Is
there a conversion function somewhere that would allow me to pass to fopen
char file1[] ? I hope I am making myself clear.

Remember that in a parameter declaration (and *only* in a parameter
declaration) ``char file1[]'' really means ``char *file1''.

A minor nit: spaces after the commas would make the declaration a bit
easier to read.

Declaring bytes as a char means that, depending on the system, the
maximum number of bytes you can specify might be only 127. I'd use
size_t rather than char. (The value of ``bytes'' should be a *count*
of bytes, not a byte.)

fopen() does not require a string literal; it requires a char*, which
should point to a string (understand the difference between a string
and a string literal). No conversion is necessary. Given your
declaration, the body of chunk() could do this:

FILE *input_file = fopen(file1, "r");
FILE *output_file = fopen(file2, "w");
/* error checking omitted for brevity */
 
B

Bill Cunningham

Keith Thompson said:
Remember that in a parameter declaration (and *only* in a parameter
declaration) ``char file1[]'' really means ``char *file1''.

A minor nit: spaces after the commas would make the declaration a bit
easier to read.

Declaring bytes as a char means that, depending on the system, the
maximum number of bytes you can specify might be only 127. I'd use
size_t rather than char. (The value of ``bytes'' should be a *count*
of bytes, not a byte.)

fopen() does not require a string literal; it requires a char*, which
should point to a string (understand the difference between a string
and a string literal). No conversion is necessary. Given your
declaration, the body of chunk() could do this:

FILE *input_file = fopen(file1, "r");
FILE *output_file = fopen(file2, "w");
/* error checking omitted for brevity */
Oh I see. So would it be better to change char file1 [] to char *file1 ?
I don't know how to declar a size_t yet or use sizeof to retrieve it in this
case.

Bill
 
M

Malcolm McLean

Bill Cunningham said:
Oh I see. So would it be better to change char file1 [] to char *file1
? I don't know how to declar a size_t yet or use sizeof to retrieve it in
this case.
Only fairly rarely do you want to hardcode a filename. An exception is for
test cases during development.

main takes a list of commandline arguments

int main(int argc, char **argv);

argv[0], by convention, is the name of the executable itself. argv[1],
argv[2], etc up to argv[argc-1] are what the user types on the command line.
Probably the most frequent thing to type is the file to operate on.

so

FILE *fp1;
FILE *fp2;

if(argc == 3)
{
fp1 = fopen(argv[1], "r")'
fp2 = fopen(argv[2], "r");
}

is the idiom. Obviously you need to check for null, which is what fopen will
return if user makes a typing mistake.

user will type

programx fred.txt joe.txt

with files "fred.txt" and "joe.txt" in his home directory.
 
K

Keith Thompson

Bill Cunningham said:
Keith Thompson said:
Remember that in a parameter declaration (and *only* in a parameter
declaration) ``char file1[]'' really means ``char *file1''.

A minor nit: spaces after the commas would make the declaration a bit
easier to read.

Declaring bytes as a char means that, depending on the system, the
maximum number of bytes you can specify might be only 127. I'd use
size_t rather than char. (The value of ``bytes'' should be a *count*
of bytes, not a byte.)

fopen() does not require a string literal; it requires a char*, which
should point to a string (understand the difference between a string
and a string literal). No conversion is necessary. Given your
declaration, the body of chunk() could do this:

FILE *input_file = fopen(file1, "r");
FILE *output_file = fopen(file2, "w");
/* error checking omitted for brevity */
Oh I see. So would it be better to change char file1 [] to char *file1 ?

It would be exactly equivalent. In my opinion it would be better to
declare "char *file1", because the parameter really is a pointer, but
the "char file[]" form does serve to document the fact that it's
intended to be a pointer to the first element of an array. It's up to
you.
I don't know how to declar a size_t yet or use sizeof to retrieve it in this
case.

size_t is just another type. It's actually an alias for one of the
predefined unsigned integer types. You can simply change "char bytes"
to "size_t bytes".

Or you could use int rather than size_t if you find that simpler.
I wouldn't do that in production code, but it's ok for a relatively
elementary exercise.
 
B

Bill Cunningham

Malcolm McLean said:
Only fairly rarely do you want to hardcode a filename. An exception is for
test cases during development.

main takes a list of commandline arguments

int main(int argc, char **argv);

argv[0], by convention, is the name of the executable itself. argv[1],
argv[2], etc up to argv[argc-1] are what the user types on the command
line. Probably the most frequent thing to type is the file to operate on.

so

FILE *fp1;
FILE *fp2;

if(argc == 3)
{
fp1 = fopen(argv[1], "r")'
fp2 = fopen(argv[2], "r");
}

is the idiom. Obviously you need to check for null, which is what fopen
will return if user makes a typing mistake.

user will type

programx fred.txt joe.txt

with files "fred.txt" and "joe.txt" in his home directory.
I see. fopen takes a pointer as its first parameter. I'm not very good
at reading default parameter types yet. That's why I need the tutorial
before the reference. I see what you're saying. I thought I would call the
function from main like such,

main(){
chunk(file,file,bytes);
return 0;}

Bill
 
B

Bill Cunningham

[snip]

size_t is just another type. It's actually an alias for one of the
predefined unsigned integer types. You can simply change "char bytes"
to "size_t bytes".

Or you could use int rather than size_t if you find that simpler.
I wouldn't do that in production code, but it's ok for a relatively
elementary exercise.
So is size_t larger than 32 bit as it is on my machine that is? I think
long(s) are also 32 bit. Would that be sizeof (number of bytes) in that
parameter? Say I wanted to copy a 4098 byte sized chunk from the beginning
of the file and copy it.

dd does all these things but I'm just trying to learn.

Bill
 
V

vippstar

[snip]

size_t is just another type. It's actually an alias for one of the> predefined unsigned integer types. You can simply change "char bytes"
to "size_t bytes".
Or you could use int rather than size_t if you find that simpler.
I wouldn't do that in production code, but it's ok for a relatively
elementary exercise.

So is size_t larger than 32 bit as it is on my machine that is? I think
long(s) are also 32 bit. Would that be sizeof (number of bytes) in that
parameter? Say I wanted to copy a 4098 byte sized chunk from the beginning
of the file and copy it.
a size_t is *guaranteed* to be able to represent correctly the value
4098 (or hold, if you prefer) while an object of type char is not
guaranteed to do that.
To copy 4098 bytes you would have a function like this:
--
int chunk(FILE * from, FILE * to, size_t n) {

int ch;
int error;

for(ch = getc(from); ch != EOF && n != 0; n--) {
if(putc(c, to) == EOF) break;
ch = getc(from);
}

error = ferror(from) || ferror(to);
if(error)
perror("ferror");

return -error; /* 0 OK, -1 ERROR */
}
 
B

Ben Bacarisse

Bill Cunningham said:
[snip]

size_t is just another type. It's actually an alias for one of the
predefined unsigned integer types. You can simply change "char bytes"
to "size_t bytes".

Or you could use int rather than size_t if you find that simpler.
I wouldn't do that in production code, but it's ok for a relatively
elementary exercise.
So is size_t larger than 32 bit as it is on my machine that is?

The advantage of using size_t is precisely that you don't need to know
(or care)! It is large enough (i.e. has enough bits) to store the
size of any object in memory. No one here can tell how many bits it
uses on your machine, but if you tun this:

#include <limits.h>
#include <stdio.h>
#include <stddef.h>

int main(void)
{
printf("size_t uses %d bits.\n", sizeof(size_t) * CHAR_BIT);
return 0;
}

it will tell you.

Of course, in your program, the third parameter is not being used for
that purpose. It denotes a number of bytes to copy from one file to
another, and size_t may not be big enough for that in the most general
case.
I think
long(s) are also 32 bit. Would that be sizeof (number of bytes) in that
parameter?

The sizeof operator always returns a value of type size_t, but that
does not mean you can only use 'sizeof(something)' for such a
parameter. If you had:

void chunk(char file1[], char file2[], size_t bytes)

you can just write:

chunk("input", "output", 42);

of you want to cop[y 42 bytes.
Say I wanted to copy a 4098 byte sized chunk from the beginning
of the file and copy it.

If you know that an int is big enough (it is for 4098) then using an
int is fine.
 
K

Keith Thompson

Ben Bacarisse said:
#include <limits.h>
#include <stdio.h>
#include <stddef.h>

int main(void)
{
printf("size_t uses %d bits.\n", sizeof(size_t) * CHAR_BIT);
return 0;
}
[...]

You forgot to cast the value to int. You're trying to print a size_t
value with a "%d" format. It might happen to work, or it might not.

#include <limits.h>
#include <stdio.h>
#include <stddef.h>

int main(void)
{
printf("size_t uses %d bits.\n", (int)(sizeof(size_t) * CHAR_BIT));
return 0;
}
 
B

Ben Bacarisse

Keith Thompson said:
Ben Bacarisse said:
printf("size_t uses %d bits.\n", sizeof(size_t) * CHAR_BIT);
[...]

You forgot to cast the value to int. You're trying to print a size_t
value with a "%d" format. It might happen to work, or it might not.

Ah! Thanks. I did not want to use %zu, but then forgot the cast.
[Note to self: post no code after 1am.]
 
M

Malcolm McLean

Ben Bacarisse said:
Keith Thompson said:
You forgot to cast the value to int. You're trying to print a size_t
value with a "%d" format. It might happen to work, or it might not.

Ah! Thanks. I did not want to use %zu, but then forgot the cast.
[Note to self: post no code after 1am.]
I'll offer you another chance to order a "give me 64" T-shirt.
 
B

Ben Bacarisse

Malcolm McLean said:
Ben Bacarisse said:
Keith Thompson said:
You forgot to cast the value to int. You're trying to print a size_t
value with a "%d" format. It might happen to work, or it might not.

Ah! Thanks. I did not want to use %zu, but then forgot the cast.
[Note to self: post no code after 1am.]
I'll offer you another chance to order a "give me 64" T-shirt.

Not all gone yet?

Do you have one that says:

The only place you really need a cast in C is
printing size_t in C90... and passing a char **
as a const char *const *. No, the *two* places
you need a cast are: printing size_t in C90,
passing a char ** as a const char *const * and
when calling ctype.h functions.
No, the *three* places... *Amongst* the places you
need a cast are printing size_t in C90...
 
B

Bill Cunningham

void chunk(char *f1, char *f2, size_t bytes)
{FILE *of *if;
if=fopen(f1,"r");
fread( f1,sizeof(

Now at sizeof() I don't know what to put there. Should it be size_t ? And
the next parameter is usually the number of bytes. What should I put there?

Basically how should I write out fread in this example?

Bill
 
M

Malcolm McLean

Ben Bacarisse said:
Malcolm McLean said:
Ben Bacarisse said:
You forgot to cast the value to int. You're trying to print a size_t
value with a "%d" format. It might happen to work, or it might not.

Ah! Thanks. I did not want to use %zu, but then forgot the cast.
[Note to self: post no code after 1am.]
I'll offer you another chance to order a "give me 64" T-shirt.

Not all gone yet?

Do you have one that says:

The only place you really need a cast in C is
printing size_t in C90... and passing a char **
as a const char *const *. No, the *two* places
you need a cast are: printing size_t in C90,
passing a char ** as a const char *const * and
when calling ctype.h functions.
No, the *three* places... *Amongst* the places you
need a cast are printing size_t in C90...

Too busy.

Try
Let him who has 64 bits cast the first size_t.

You can get T-shirt designs done remarkably cheaply these days, you know.
 
K

Keith Thompson

Bill Cunningham said:
void chunk(char *f1, char *f2, size_t bytes)
{FILE *of *if;
if=fopen(f1,"r");
fread( f1,sizeof(

Now at sizeof() I don't know what to put there. Should it be size_t ? And
the next parameter is usually the number of bytes. What should I put there?

Basically how should I write out fread in this example?

You're assuming that you need to use sizeof. You really don't.

The sizeof operator gives you the size in bytes of a type or of an
expression. For your call to fread, you already know how many bytes
you want to read (or rather attempt to read); it's the "bytes"
parameter to your function. Just use that.

Re-read the documentation for fread() to make sure you get the
arguments right, and don't forget to check for errors.

And *please* use a layout that makes your code easier to read. You
tend to put your '{' and '} delimiters right next to other tokens, so
they're difficult to see. An opening brace should be either at the
end of a line (preceded by a blank) or on a line by itself. A closing
brace should be on a line by itself. There are a number of different
styles. Look at some existing code, find a style you like, and use
it.
 
D

Default User

Bill said:
void chunk(char *f1, char *f2, size_t bytes)
{FILE *of *if;
if=fopen(f1,"r");

How do know the fopen() call succeeded? Check it! Also, "if" is a
keyword. Don't try to use that for a variable name.
fread( f1,sizeof(

f1 is the string you passed to fopen(). Why would it appear in your
fread call? You meant f2. You should get in the habit of using more
descriptive parameter and variable names.
Now at sizeof() I don't know what to put there. Should it be size_t
? And the next parameter is usually the number of bytes. What should
I put there?

Basically how should I write out fread in this example?

As Keith mentioned, in this case you have a byte count. In general, as
the web site I gave you shows:

int fread( void *buffer, size_t size, size_t num, FILE *stream );

"size" is the size of an individual element to be retrieved from the
file. "num" is the number of those. In your particular case, you are
reading characters, which always have a size of 1.

void chunk(char *filename, char *buffer, size_t bytes)
{
FILE *file_p;
int num_read;

file_p = fopen(filename, "r");

if (file_p == 0)
{
/* error handler */
}
else
{
num_read = fread(buffer, 1, bytes, file_p);
/* check and see how many you actually read */
/* now what to do with the file pointer? */
}
}




Brian
 
D

Default User

Bill said:
file_p==NULL or file_p=='\0';

You snipped too much, but the answer is no to both of those. There's no
need to set file_p to NULL at this point. The point is, that file is
still open and you're about to leave the function that opened it. You
need to do something about that.

Also, '\0' is a character constant of value 0. While it would be
converted to a null-pointer value, as would plain 0, it's not the
clearest expression of the idea.




Brian
 
B

Bill Cunningham

Default User said:
You snipped too much, but the answer is no to both of those. There's no
need to set file_p to NULL at this point. The point is, that file is
still open and you're about to leave the function that opened it. You
need to do something about that.

Also, '\0' is a character constant of value 0. While it would be
converted to a null-pointer value, as would plain 0, it's not the
clearest expression of the idea.

I'm still not clear of fread. I've always used it like this in the past
fread (buf name,sizeof(char),512,fp); But how to pass parameters from a
function fread is used in confuses me. If size_t is there I might as well
use it.

void chunk(char *file1, char *file2, size_t bytes)

Do I need to add another parameter to this to use as a buffer?

Bill
 

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

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,133
Latest member
MDACVReview
Top