Connecting Tech Pros Worldwide Forums | Help | Site Map

From file to char* array

OziRus
Guest
 
Posts: n/a
#1: Dec 8 '06
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...


santosh
Guest
 
Posts: n/a
#2: Dec 8 '06

re: From file to char* array


OziRus wrote:
Quote:
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;
}

OziRus
Guest
 
Posts: n/a
#3: Dec 8 '06

re: From file to char* array


Thanks. But I still can't understand why

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

doesn't work...

Richard Heathfield
Guest
 
Posts: n/a
#4: Dec 8 '06

re: From file to char* array


OziRus said:
Quote:
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.
Lew Pitcher
Guest
 
Posts: n/a
#5: Dec 8 '06

re: From file to char* array



OziRus wrote:
Quote:
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
--
Lew

OziRus
Guest
 
Posts: n/a
#6: Dec 8 '06

re: From file to char* array


Thank you so much!

Richard Heathfield yazdi:
Quote:
OziRus said:
>
Quote:
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.
Default User
Guest
 
Posts: n/a
#7: Dec 8 '06

re: From file to char* array


OziRus wrote:
Quote:
Thank you so much!
Please don't top-post. Your replies belong following or interspersed
with properly trimmed quotes. See the majority of other posts in the
newsgroup, or:
<http://www.caliburn.nl/topposting.html>
jaysome
Guest
 
Posts: n/a
#8: Dec 9 '06

re: From file to char* array


On 8 Dec 2006 09:24:34 -0800, "santosh" <santosh.k83@gmail.comwrote:
Quote:
>OziRus wrote:
Quote:
>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
Quote:
>{
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;
>}
Dave Thompson
Guest
 
Posts: n/a
#9: Dec 26 '06

re: From file to char* array


On 8 Dec 2006 08:46:41 -0800, "OziRus" <caliskanfurkan@gmail.com>
wrote:
<snip>
Quote:
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
Closed Thread