From file to char* array

O

OziRus

Hi,

I've char* array that I defined like char *str[150]. I want to read
from a file, that contains names in each row, and assign them to my str
char * array.

m is a char array, f is a file pointer and counter is my variable that
contains number of names in my file;

When I write;

while(fgets(m,100,f)!=NULL) {
printf("%s",m)
}

code. It gets and writes all my names onto screen but;

When I recode it like;

while(fgets(m,100,f)!=NULL) {
str[counter]=m;
counter--;
}

and try print str[1] ve str[2] to screen It always print my last
elements for 2 times.

For example:

File: John, Alp, Liz, Sema

First code writes;
John, Alp, Liz, Sema

With second code and printfs:
Sema, Sema

How can I fix it? Thanks so much...
 
S

santosh

OziRus said:
Hi,

I've char* array that I defined like char *str[150]. I want to read
from a file, that contains names in each row, and assign them to my str
char * array.
<snip>

#include <stdio.h>
#include <stdlib.h>

#define MAX_NAMES 150
#define MAX_NAME_LENGTH 256

int main(int argc, char **argv) {
FILE *f;
char *names[MAX_NAMES];
int cnt;

/* open file */
if(argc < 2) {
fprintf(stderr, "No file specified.\n");
exit(EXIT_FAILURE);
}
else {
f = fopen(argv[1], "r");
if(f == NULL) {
fprintf(stderr, "Unable to open file: %s\n", argv[1]);
exit(EXIT_FAILURE);
}
}

/* allocate memory for names */
for(cnt = 0; cnt < MAX_NAMES; cnt++) {
if((names[cnt] = malloc(MAX_NAME_LENGTH * sizeof *names)) == NULL)
{
fprintf(stderr, "No memory.\n");
exit(EXIT_FAILURE);
}
}

/* read lines into memory */
for(cnt = 0; cnt < MAX_NAMES; cnt++) {
if(fgets(names[cnt], MAX_NAME_LENGTH, f) == NULL && ferror(f)) {
fprintf(stderr, "Error reading file: %s\n", argv[1]);
for(cnt = 0; cnt < MAX_NAMES; cnt++) free(names[cnt]);
exit(EXIT_FAILURE);
}
}

/* print what we've read in from file */
for(cnt = 0; cnt < MAX_NAMES; cnt++)
fprintf(stdout, "%s", names[cnt]);
fflush(stdout);

for(cnt = 0; cnt < MAX_NAMES; cnt++) free(names[cnt]);
return EXIT_SUCCESS;
}
 
O

OziRus

Thanks. But I still can't understand why

while(fgets(m,100,f)!=NULL) {
str[counter]=m;
counter--;
}

doesn't work...
 
R

Richard Heathfield

OziRus said:
Thanks. But I still can't understand why

while(fgets(m,100,f)!=NULL) {
str[counter]=m;
counter--;
}

doesn't work...

str[counter] = m; does not allocate fresh storage for a copy of your string.
It merely points str[counter] at your existing buffer. So you end up with a
whole bunch of pointers all pointing to the same place. And if you give any
one of those pointers to printf, you'll get the same data printed out.

As santosh has demonstrated, you can fix this by allocating sufficient
storage for each line of data, and by then copying your data into it.
 
L

Lew Pitcher

OziRus said:
Thanks. But I still can't understand why

while(fgets(m,100,f)!=NULL) {
str[counter]=m;
counter--;
}

doesn't work...

The line
fgets(m,100,f)
reads at most 100 bytes of data from FILE f, and places that data into
the character buffer m, overwriting anything that was previously stored
in buffer m

The line
str[counter]=m
takes the address of the first byte of the buffer m (effectively) and
stores that address in str[counter]

It /does not/ copy the contents of the buffer m into str[counter]. For
that, you would have to use something like strcpy()

Once your while loop completes, you have a number of str[] entries all
pointing to the same buffer m

When you print each str[] entry, you print the current contents of
buffer m, which contains the /last/ value retrieved by fgets()

HTH
 
O

OziRus

Thank you so much!

Richard Heathfield yazdi:
OziRus said:
Thanks. But I still can't understand why

while(fgets(m,100,f)!=NULL) {
str[counter]=m;
counter--;
}

doesn't work...

str[counter] = m; does not allocate fresh storage for a copy of your string.
It merely points str[counter] at your existing buffer. So you end up with a
whole bunch of pointers all pointing to the same place. And if you give any
one of those pointers to printf, you'll get the same data printed out.

As santosh has demonstrated, you can fix this by allocating sufficient
storage for each line of data, and by then copying your data into it.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at the above domain, - www.
 
J

jaysome

OziRus said:
Hi,

I've char* array that I defined like char *str[150]. I want to read
from a file, that contains names in each row, and assign them to my str
char * array.
<snip>

#include <stdio.h>
#include <stdlib.h>

#define MAX_NAMES 150
#define MAX_NAME_LENGTH 256

int main(int argc, char **argv) {
FILE *f;
char *names[MAX_NAMES];
int cnt;

/* open file */
if(argc < 2) {
fprintf(stderr, "No file specified.\n");
exit(EXIT_FAILURE);
}
else {
f = fopen(argv[1], "r");
if(f == NULL) {
fprintf(stderr, "Unable to open file: %s\n", argv[1]);
exit(EXIT_FAILURE);
}
}

/* allocate memory for names */
for(cnt = 0; cnt < MAX_NAMES; cnt++) {
if((names[cnt] = malloc(MAX_NAME_LENGTH * sizeof *names)) == NULL)

Why use malloc()? The size of names[cnt] is certainly not unknown or
even "dynamic". Both MAX_NAME_LENGTH and sizeof *names are
compile-time constants.

Why not just declare an appropriate array with either automatic or
static storage duration? If you did that, it:

1. Would free you from having to free().
2. Would result in a smaller memory footprint (less code).
3. Might make the difference between running or not on a non-hosted
environment. Resources can get pretty constrained on, for example,
some embedded systems. Such implementations might not even
*practically* support malloc().
4. Might unnecessarily violate coding standards (thou shall not use
dynamic memory) that are applicable to, for example, safety-critical
systems.

--
jay
{
fprintf(stderr, "No memory.\n");
exit(EXIT_FAILURE);
}
}

/* read lines into memory */
for(cnt = 0; cnt < MAX_NAMES; cnt++) {
if(fgets(names[cnt], MAX_NAME_LENGTH, f) == NULL && ferror(f)) {
fprintf(stderr, "Error reading file: %s\n", argv[1]);
for(cnt = 0; cnt < MAX_NAMES; cnt++) free(names[cnt]);
exit(EXIT_FAILURE);
}
}

/* print what we've read in from file */
for(cnt = 0; cnt < MAX_NAMES; cnt++)
fprintf(stdout, "%s", names[cnt]);
fflush(stdout);

for(cnt = 0; cnt < MAX_NAMES; cnt++) free(names[cnt]);
return EXIT_SUCCESS;
}
 
D

Dave Thompson

On 8 Dec 2006 08:46:41 -0800, "OziRus" <[email protected]>
wrote:
while(fgets(m,100,f)!=NULL) {
str[counter]=m;
counter--;
}
You almost certainly had and wanted counter++ there. Unless you knew
in advance the number of lines you will read, or at least a safe upper
bound, and from the rest of your discussion you don't.

Assuming so, the only problem you have is reusing/sharing the buffer
m, as already answered by others.

If you really have counter-- and are at any time decrementing below
zero, then that is a second problem.

- David.Thompson1 at worldnet.att.net
 

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
474,431
Messages
2,571,677
Members
48,796
Latest member
Greg L.

Latest Threads

Top