file to array of strings(newbie question)

A

al3x4nder

Hi All,

I want read file to array of strings
and found the next soluition:

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


#define LINESIZE 1024
#define SIZE(length) (sizeof(char) * length + 1)
#define BUFFSIZE 1024



int main(int argc, char **argv){
int cnt, i;
FILE *fp;
char *p, *buff[BUFFSIZE];

if(argc < 2){
printf("Error: I need filename as argument!\n");
return 1;
}

if((fp = fopen(argv[1], "r")) == NULL){
printf("Error: %s\n", strerror(errno));
return 1;
}

/* Read file into array buff[] */
for(cnt = 0; cnt < BUFFSIZE; cnt++){
p = (char *)malloc(SIZE(LINESIZE));
if (fgets(p, LINESIZE, fp) == NULL) {
free(p);
break;
}
buff[cnt] = p;
}

/* Do something with readed data */
for(i = 0; i < cnt; i++){
printf("%s",buff);
}

return 0;
}


I`m a newbie in C, and now question:
may be exist a better way?
Thanks, and sorry for my English.
 
V

Vladimir Oka

al3x4nder said:

Before I start, a commendable example of a newbie post! Well done.
Extra marks for not using l33t anywhere else apart form the username
(with a tiny deduction for using it at all). To make sure you keep up
the high standard, do read:

http://www.clc-wiki.net/wiki/Introduction_to_comp.lang.c

and

http://cfaj.freeshell.org/google/

I you're posting from Google.
I want read file to array of strings
and found the next soluition:

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

You also needed:

#include <stdlib.h>

but you masked it by casting return value of `malloc()`. Don't do that.
#define LINESIZE 1024
#define SIZE(length) (sizeof(char) * length + 1)

I don't think you needed a macro for this. Also, `sizeof(char)` is
guaranteed to be 1, although you may want to spell it out to make
intentions clear -- a matter of style.
#define BUFFSIZE 1024

int main(int argc, char **argv){
int cnt, i;
FILE *fp;
char *p, *buff[BUFFSIZE];

I prefer one declaration per line -- a matter of style/taste.
if(argc < 2){
printf("Error: I need filename as argument!\n");
return 1;

return EXIT_FAILURE;

could have been better.
}

if((fp = fopen(argv[1], "r")) == NULL){

Again, personally, I prefer not to pack assignments into conditions.
You gain a line of screen real estate -- you lose readability and
maintainability.
printf("Error: %s\n", strerror(errno));

You should be aware that the message returned is not guaranteed to be
meaningful. Also, library functions are not guaranteed to set `errno`
to anything meaningful either (they are guaranteed not to zero it,
though, so beware).
return 1;

Again,

return EXIT_FAILURE;

could have been better.
}

/* Read file into array buff[] */
for(cnt = 0; cnt < BUFFSIZE; cnt++){
p = (char *)malloc(SIZE(LINESIZE));

Do not cast return value of `malloc()`. It's not required, and it masks
failure to include <stdlib.h>, and failure to include it tells the
compiler to assume `malloc()` (as it has no prototype in scope) returns
`int`, but you then try to use that `int` as a pointer, and BANG!,
you've invoked thja wrath of Undefined Behaviour.
if (fgets(p, LINESIZE, fp) == NULL) {
free(p);

This should have made your compiler whine about `free()` not having a
prototype in scope.
break;
}
buff[cnt] = p;
}

/* Do something with readed data */
for(i = 0; i < cnt; i++){
printf("%s",buff);


If you don't terminate the output with a '\n' (or call
`fflush(stdout)`), you're not guaranteed to see any output whatsoever.
}

return 0;

This is OK, but if you decide to use EXIT_FAILURE above, then use:

return EXIT_SUCCESS

here. EXIT_FAILURE, EXIT_SUCCESS, and 0, are the only portable return
values from `main()`.
}

I`m a newbie in C, and now question:
may be exist a better way?

Apart from what I commented on above, this looks like a decent stab at
the task you set yourself. I could imagine different ways of doing it,
but it really depends on what exactly you want to achieve.

Obvious improvement would be not to limit line and file length, but
allocate space dynamically as you go along. It would be a very good
exercise for you now, to have a think and try to achieve that. Any
problems, do come back and ask.
 
C

CBFalconer

Vladimir said:
al3x4nder wrote:

Before I start, a commendable example of a newbie post! Well done.
Extra marks for not using l33t anywhere else apart form the username
(with a tiny deduction for using it at all). To make sure you keep up
the high standard, do read:

http://www.clc-wiki.net/wiki/Introduction_to_comp.lang.c
.... snip ...

I echo the commendation part above. As far as a better mechanism,
consider downloading and reading, and possibly using:

<http://cbfalconer.home.att.net/download/ggets.zip>

Look at some of the usage examples.

--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson
More details at: <http://cfaj.freeshell.org/google/>
Also see <http://www.safalra.com/special/googlegroupsreply/>
 

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,744
Messages
2,569,483
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top