read multiple lines of a file

C

Clunixchit

How can i read lines of a file and place each line read in an array?
for exemple;
array[0]=line1
array[1]=line2
...
 
B

Barry Schwarz

On Mon, 30 May 2005 16:50:49 +0000 (UTC),
How can i read lines of a file and place each line read in an array?
for exemple;
array[0]=line1
array[1]=line2

Your use of the word line implies a text file. fgets() is frequently
the tool of choice.

If the file is not a text file, then fread() would probably be better.



<<Remove the del for email>>
 
C

Clunixchit

im having a *** glibc detected *** corrupted double-linked list:
0x0804b error.
here is my code :

typedef struct new_phrase {
int N; // number of words
char **T; // words stored in an array
} new_phrase;

new_phrase file_array (new_phrase phrase) {
phrase.N=0;
FILE *stream;
char tmp[LINE_LENGTH];

/* Open the file. If NULL is returned there was an error */
if ( !(stream = fopen( MYAIRC , "r"
))) {
perror("fopen");
_exit(EXIT_FAILURE);
}
(void) fseek(stream,0,SEEK_SET);

if ( !(phrase.T = malloc ( sizeof (phrase.T)
))) {
perror("malloc");
_exit(EXIT_FAILURE);
}

// creating array > phrase.T
while ( fgets ( tmp , LINE_LENGTH-1 , stream ) != NULL
) {
size_t l = strlen(tmp);
if (l > 0 && tmp[l-1] == '\n')
tmp[l-1] = '\0';
if ( !(phrase.T[phrase.N] = malloc ( sizeof
(phrase.T[phrase.N]) ))) {
perror("malloc");
_exit(EXIT_FAILURE);
}
phrase.T[phrase.N]=tmp;
printf("phrase.T %s
%d\n",phrase.T[phrase.N],phrase.N);
phrase.N++;
}

fclose (stream);

if ( phrase.N == 0 ) {
printf("%s is empty\n",MYAIRC);
_exit(EXIT_FAILURE);
}
return phrase;
}

ive used the fgets mentioned above.
this code allows to fill the array but return the error
*** glibc detected *** corrupted double-linked list: 0x0804b168 ***

any suggestions? or improvements?
 
C

Chris Torek

here is my code :

[snippage - some slight editing for space]
if ( !(phrase.T[phrase.N] = malloc(sizeof (phrase.T[phrase.N]) ))) {

This line is obviously wrong.

A call to malloc() should always have the general form:

p = malloc(N * sizeof *p)

or:

p = malloc(sizeof *p) /* i.e., N == 1 */

or, similarly:

*pp = malloc(N * sizeof **pp)

but this one has the form:

p = malloc(sizeof p)

The unary "*" operator is missing: there should be one more "*" on
the right side of the "=" sign than there is on the left.

The line above should read more like:

if ((phrase.T[phrase.N] = malloc(sizeof *phrase.T[phrase.N])) == NULL) {

for instance.
 
C

Clunixchit

*** glibc detected *** corrupted double-linked list: 0x0804b168 ***

nope it didnt solve the problem.
The Anjuta program giving me:
Program has been terminated receiving signal 6 (Aborted)
in the end
 
B

Barry Schwarz

On Sat, 18 Jun 2005 12:58:09 +0000 (UTC),
im having a *** glibc detected *** corrupted double-linked list:
0x0804b error.
here is my code :

typedef struct new_phrase {
int N; // number of words
char **T; // words stored in an array
} new_phrase;

new_phrase file_array (new_phrase phrase) {
phrase.N=0;
FILE *stream;
char tmp[LINE_LENGTH];

/* Open the file. If NULL is returned there was an error */
if ( !(stream = fopen( MYAIRC , "r"))) {
perror("fopen");
_exit(EXIT_FAILURE);

What is _exit? Is there some reason the standard function won't work
for you so others could test your code?
}
(void) fseek(stream,0,SEEK_SET);

The cast does nothing but clutter up your code.
if ( !(phrase.T = malloc ( sizeof (phrase.T)))) {

You have attempted to allocate enough space for a char**. However,
phrase.T must point to an area with enough space for a char*. It is
entirely possible for the latter to be larger than the former. You
probably want malloc(sizeof *phrase.T).
perror("malloc");
_exit(EXIT_FAILURE);
}

// creating array > phrase.T
while ( fgets ( tmp , LINE_LENGTH-1 , stream ) != NULL

fgets() already subtracts one for you so there is no need for you to
subtract another one.
) {
size_t l = strlen(tmp);
if (l > 0 && tmp[l-1] == '\n')
tmp[l-1] = '\0';
if ( !(phrase.T[phrase.N] = malloc ( sizeof
(phrase.T[phrase.N]) ))) {

This is wrong for a more complex reason. You really don't care about
the size of phrase.T[phrase.N]. That is simply a char* whose size
never changes. You want to allocate enough space to hold the string.
l+1 will always be sufficient though if there was a \n in the string
you removed it and l would be sufficient. Your code could read
malloc(l+1).

If sizeof(char*) > sizeof(char**), then this invokes undefined
behavior by attempting to stuff a wider value into a narrower
allocation.
perror("malloc");
_exit(EXIT_FAILURE);
}
phrase.T[phrase.N]=tmp;

This throws away the address of the area you just allocated, creating
a memory leak. I think you intended to copy the string in tmp to the
newly allocated area. For that you need something akin to strcpy().
printf("phrase.T %s
%d\n",phrase.T[phrase.N],phrase.N);
phrase.N++;
}

fclose (stream);

if ( phrase.N == 0 ) {
printf("%s is empty\n",MYAIRC);
_exit(EXIT_FAILURE);
}
return phrase;

Your structure is very small (two simple items) so this is not a big
deal. But most C code would use a pointer to struct to avoid the
overhead of passing a large struct back and forth.
}

ive used the fgets mentioned above.
this code allows to fill the array but return the error

What array? The only array in your code is tmp. And it ceases to
exist as soon as you exit the function.

Furthermore, this function will only allocate one value in the area
pointed to by phrase.T. You set phrase.N to 0 on entry. No matter
what the struct contains from the caller, you force it to be "empty".
*** glibc detected *** corrupted double-linked list: 0x0804b168 ***

Have you run it through a debugger? On which statement does this
error occur? Since you have no linked list in your code, this must
have something to do with the run time library, most likely memory
allocation. Fix the obvious problems and try again.
any suggestions? or improvements?

It would have helped if you had shown us how you call the function.



<<Remove the del for email>>
 
C

Clunixchit

It would have helped if you had shown us how you call the function.

here it is:

new_phrase phrase;

//initialise the array in new_phrase
phrase = file_array(phrase);

i will correct with respect to your suggestion and will post
accordingingly
 
C

Clunixchit

i can't find whats going wrong with it
here is the full source code:

#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>

#define LINE_LENGTH 20
#define MYAIRC "myAIc"

typedef struct new_phrase { // if new_phrase is not written here,
it will be an anonymous structure
int N; // number of words
char **T; // words stored in an array
} new_phrase;

/* initialise my structure by first loading MYAIRC into a
bidimensional array*/
new_phrase * file_array (new_phrase *phrase) {
(*phrase).N=0;
char tmp[LINE_LENGTH];

FILE *stream = fopen( MYAIRC , "r" );
if ( !stream ) {
perror("fopen");
_exit(EXIT_FAILURE);
}
fseek(stream,0,SEEK_SET);

if ( !((*phrase).T = malloc ( sizeof
*((*phrase).T) ))) {
perror("malloc");
_exit(EXIT_FAILURE);
}
while ( fgets( tmp , LINE_LENGTH , stream ) != NULL )
{
size_t l = strlen(tmp);
if (l > 0 && tmp[l-1] == '\n')
tmp[l-1] = '\0';
if ( !((*phrase).T[(*phrase).N] =
malloc ( strlen(tmp) ))) {
perror("malloc");
_exit(EXIT_FAILURE);
}

strcpy((*phrase).T[(*phrase).N],tmp);
printf("phrase.T %s
%d\n",(*phrase).T[(*phrase).N],(*phrase).N);

(*phrase).N++;
}
fclose (stream);

if ( (*phrase).N == 0 ) {
printf("%s is empty\n",MYAIRC);
_exit(EXIT_FAILURE);
}
return phrase;
}
int main ( void ) {
new_phrase *phrase = malloc ( sizeof(*phrase));

//initialise the structure
new_phrase *phrase1 = file_array(phrase);
return 0;
}
 
M

Martin Ambuhl

Clunixchit said:
i can't find whats going wrong with it
here is the full source code:

Just in case anyone cares to bother, here is a legal standard C version
of your code. This code compiles and with a copy of itself named
"myAIc" runs without error.

#if 0
/* mha: non-standard headers placed in this commented-out section */
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#endif
/* mha: Further general notes -- (1) The C++-style comments have been
converted. Your example code, with comments broken across lines, is
exactly why C++-style comments should not be used in usenet
postings. (2) The non-standard _exit() calls have been replaced
with exit(). Any time you need to #include <unistd.h>, you know
your code is not standard C. (3) The broken printf() specifier
string has been spliced together. */

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

#define LINE_LENGTH 20
#define MYAIRC "myAIc"

typedef struct new_phrase
{ /* if new_phrase is not written here,
it will be an anonymous structure */
int N; /* number of words */
char **T; /* words stored in an array */
} new_phrase;

/* initialise my structure by first loading MYAIRC into a
bidimensional array*/
new_phrase *file_array(new_phrase * phrase)
{
(*phrase).N = 0;
char tmp[LINE_LENGTH];

FILE *stream = fopen(MYAIRC, "r");
if (!stream) {
perror("fopen");
exit(EXIT_FAILURE);
}
fseek(stream, 0, SEEK_SET);

if (!((*phrase).T = malloc(sizeof *((*phrase).T)))) {
perror("malloc");
exit(EXIT_FAILURE);
}
while (fgets(tmp, LINE_LENGTH, stream) != NULL) {
size_t l = strlen(tmp);
if (l > 0 && tmp[l - 1] == '\n')
tmp[l - 1] = '\0';
if (!((*phrase).T[(*phrase).N] = malloc(strlen(tmp)))) {
perror("malloc");
exit(EXIT_FAILURE);
}

strcpy((*phrase).T[(*phrase).N], tmp);
printf("phrase.T %s %d\n", (*phrase).T[(*phrase).N],
(*phrase).N);

(*phrase).N++;
}
fclose(stream);

if ((*phrase).N == 0) {
printf("%s is empty\n", MYAIRC);
exit(EXIT_FAILURE);
}
return phrase;
}
int main(void)
{
new_phrase *phrase = malloc(sizeof(*phrase));

/* initialise the structure */
new_phrase *phrase1 = file_array(phrase);
return 0;
}
 
C

Clunixchit

Martin Ambuhlwrote:
Clunixchit said:
i can't find whats going wrong with it
here is the full source code:
Just in case anyone cares to bother, here is a legal standard C
version
of your code. This code compiles and with a copy of itself named
"myAIc" runs without error.

#if 0
/* mha: non-standard headers placed in this commented-out section
*/
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#endif
/* mha: Further general notes -- (1) The C++-style comments have
been
converted. Your example code, with comments broken across lines,
is
exactly why C++-style comments should not be used in usenet
postings. (2) The non-standard _exit() calls have been replaced
with exit(). Any time you need to #include <unistd.h>, you
know
your code is not standard C. (3) The broken printf() specifier
string has been spliced together. */

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

#define LINE_LENGTH 20
#define MYAIRC "myAIc"

typedef struct new_phrase
{ /* if new_phrase is not written here,
it will be an anonymous structure
*/
int N; /* number of words */
char **T; /* words stored in an array */
} new_phrase;

/* initialise my structure by first loading MYAIRC into a
bidimensional array*/
new_phrase *file_array(new_phrase * phrase)
{
(*phrase).N = 0;


.........................................
return 0;
}[/quote:78b2fb99c6]

have you tested the code at your place? coz im still have the same
glib error
 
M

Martin Ambuhl

Clunixchit said:
Martin Ambuhlwrote:
[...]
This code compiles and with a copy of itself named
"myAIc" runs without error.
have you tested the code at your place? coz im still have the same
glib error

Can you read? How the hell would I know that it 'compiles and with a
copy of itself named "myAIc" runs without error' if I hadn't tested it?
 
M

Martin Ambuhl

Eric said:
Martin said:
[...]
if (!((*phrase).T[(*phrase).N] = malloc(strlen(tmp)))) {
[...]
strcpy((*phrase).T[(*phrase).N], tmp);


Off-by-one error.

Well spotted. In case (e-mail address removed)-spam.invalid
(Clunixchit), who is responsible for the logic (I claimed only to make a
legal compilable version available to anyone who cared), doesn't
understand the rather terse comment by Eric:
to copy the string tmp, the target must have a size of strlen(tmp)+1
or greater. The terminating '\0' which is necessary is not counted in
the value returned by strlen().
 
C

Clunixchit

I got my code working only if i create another "while".
As u can see i have made modifications with respect to your
suggestions. Ill be happy to receive more :)
concerning the non-standard libraries, this is because im using fork
and the exec family.

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

#define FILLED 1
#define EMPTY 0
#define LINE_LENGTH 20
#define MYAIRC "myAIrc"

typedef struct new_phrase {
int N;
char **T;
} new_phrase;

/* initialise my structure by first loading MYAIRC into a
bidimensional array*/
new_phrase * file_array () {
int i=0 , j=0;
char tmp[LINE_LENGTH][LINE_LENGTH];
new_phrase *phrase = malloc (sizeof *phrase);//8
(*phrase).N = EMPTY;

FILE *stream = fopen( MYAIRC , "r" );
if ( !stream ) {
perror("fopen");
exit(EXIT_FAILURE);
}
fseek(stream,0,SEEK_SET);

(*phrase).T = malloc ( sizeof
(*(*phrase).T) );

while ( fgets ( tmp , LINE_LENGTH , stream )
) {
(*phrase).N=FILLED;
size_t l = strlen(tmp);
if (l > 0 && tmp[l-1] ==
'\n')
tmp[l-1] = '\0';
i++;
}
fclose (stream);

while ( j < i ) {
(*phrase).T[j] = malloc (
strlen(tmp[j]));
strcpy((*phrase).T[j],tmp[j]);
printf("phrase.T %s
%d\n",(*phrase).T[j],j);
j++;
}
return phrase;
}
int main ( ) {

new_phrase *phrase = malloc(sizeof(*phrase));

phrase = file_array();
return 0;
}
 
D

David Resnick

Barry said:
On Sat, 18 Jun 2005 12:58:09 +0000 (UTC),
im having a *** glibc detected *** corrupted double-linked list:
0x0804b error.
here is my code :

typedef struct new_phrase {
int N; // number of words
char **T; // words stored in an array
} new_phrase;

new_phrase file_array (new_phrase phrase) {
phrase.N=0;
FILE *stream;
char tmp[LINE_LENGTH];

/* Open the file. If NULL is returned there was an error */
if ( !(stream = fopen( MYAIRC , "r"))) {
perror("fopen");
_exit(EXIT_FAILURE);

What is _exit? Is there some reason the standard function won't work
for you so others could test your code?

I had always thought _exit was C. Having looked, I can see that _Exit
is
C99, and means about the same thing as the pretty widely available (but
OT here) Posix/BSD/etc _exit. Means quit the program, do not pass go,
do not invoke atexit registered functions, don't invoke signal
handlers, maybe skip some other cleanup. Not clear why the OP is using
it, seems to be designed
for more dire situations than failing to open a file (not sure what,
when might you need to call this, some sort of error or signal
handling?)

-David
 
M

Mark McIntyre

On Mon, 20 Jun 2005 12:00:05 +0000 (UTC), in comp.lang.c ,
new_phrase *phrase = malloc (sizeof *phrase);//8
(*phrase).N = EMPTY;

This is an obscure way to say
phrase->N = EMPTY;

I'd suggest you use the latter, since its the normal means of doing it
in C.
(*phrase).T = malloc ( sizeof (*(*phrase).T) );

and this is a very odd way of saying

phrase->T = malloc( sizeof (*(phrase->T)));
 
L

Lawrence Kirby

I got my code working only if i create another "while".
As u can see i have made modifications with respect to your
suggestions. Ill be happy to receive more :)
concerning the non-standard libraries, this is because im using fork
and the exec family.

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

#define FILLED 1
#define EMPTY 0
#define LINE_LENGTH 20
#define MYAIRC "myAIrc"

typedef struct new_phrase {
int N;
char **T;
} new_phrase;

/* initialise my structure by first loading MYAIRC into a
bidimensional array*/
new_phrase * file_array () {
int i=0 , j=0;
char tmp[LINE_LENGTH][LINE_LENGTH];

LINE_LENGTH seems an odd value to use for the first dimension.
new_phrase *phrase = malloc (sizeof *phrase);//8

Bad comment. It doesn't add any useful information and is wrong in
general. You should test the return value of malloc() for failure.
(*phrase).N = EMPTY;

A slighty obfiscated way of writing

phrase->N = EMPTY;
FILE *stream = fopen( MYAIRC , "r" );
if ( !stream ) {
perror("fopen");
exit(EXIT_FAILURE);
}
fseek(stream,0,SEEK_SET);

A file opened in non-append more will initially be positioned at the
start of the file so this seek has no effect.
(*phrase).T = malloc ( sizeof
(*(*phrase).T) );

You might find this easier to read as

phrase->T = malloc(sizeof *phrase->T);

Again you should test the return value. Note that you are allocating
space for a single pointer to char.
while ( fgets ( tmp , LINE_LENGTH , stream )
) {
(*phrase).N=FILLED;
size_t l = strlen(tmp);
if (l > 0 && tmp[l-1] ==
'\n')
tmp[l-1] = '\0';
i++;
}
fclose (stream);

while ( j < i ) {
(*phrase).T[j] = malloc (
strlen(tmp[j]));


Since you allocated only a single pointer to char this will produce
undefined behaviour when j != 0.
strcpy((*phrase).T[j],tmp[j]);

This will additionally produce undefined behaviour because you didn't allocate
space for the terminating null character of the string.
printf("phrase.T %s
%d\n",(*phrase).T[j],j);
j++;
}
return phrase;
}
int main ( ) {

new_phrase *phrase = malloc(sizeof(*phrase));

phrase = file_array();

You have a memory leak here. You allocate an object and make phrase a
pointer to it. Then you overwrite phrase and you no longer have a way
to access the object you allocated.
return 0;
}

Lawrence
 

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

Forum statistics

Threads
474,166
Messages
2,570,902
Members
47,442
Latest member
KevinLocki

Latest Threads

Top