Welcome! Log In Create A New Profile

Advanced

Writing to an array

Posted by SpaceJump 
Writing to an array
December 23, 2008 09:34PM
I have a config file "in" I read. It contains comment lines marked with #. Now I want to write the other lines into an array, but it doesn't work.

Here's what I have so far:
char *charArray[8];
	int t = 0;
	
	if ( in != NULL ) {
		char line[1024];
		while ( fgets ( line, sizeof line, in ) != NULL ) {
			size_t i = strspn ( line, " \t\n\v" );

			if ( (line == '#') || (line == ' ') ) {
			//if ( (line == '#') ) {
				continue;
			}
			//charArray[t] = line; // this doesn't seem to work
			strcpy(charArray[t], line); // this also doesn't seem to work
			t=t+1;
		}
	}

What am I doing wrong?



Edited 1 time(s). Last edit at 12/23/2008 09:35PM by SpaceJump.
Re: Writing to an array
December 23, 2008 09:39PM
Try replacing

strcpy(charArray[t], line); // this also doesn't seem to work

with

strncpy(charArray[t], line, 3);

strcpy copies to a buffer not a string I believe. Whereas strncpy copies directly to another string.
Re: Writing to an array
December 23, 2008 09:40PM
strncpy(charArray[t], line, 3);

What is the 3 for?
Re: Writing to an array
December 23, 2008 09:42PM
Redacted.



Edited 1 time(s). Last edit at 12/23/2008 09:48PM by lordzid.
Re: Writing to an array
December 23, 2008 10:17PM
Quote
SpaceJump
strncpy(charArray[t], line, 3);

What is the 3 for?
3 is the maximum amount of members to be copied. If more members are copied than the maximum amount than remaining members are simply not copied. Also remember that these are c style strings so there is an extra member in every string.

So char text [] = "#" actually has two members. # and the string terminator (looks like a 0 with a slash through it I believe)

Your second problem:

//charArray[t] = line; // this doesn't seem to work

You can't declare a member of an array to equal an array. Thats a double array and should be declared as:

char Array [t] [line];



Edited 2 time(s). Last edit at 12/23/2008 10:21PM by Arikado.
Re: Writing to an array
December 23, 2008 10:21PM
Just use this:

#include 
#include 
#include 

#define INFILE "fstab"
#define MAXLINE 1024

typedef struct _list {
        struct _list *next;
        char *data;
} list;

static list *add_line(list *l, const char *s)
{
        if(!l) {
                l = malloc(sizeof(list));
                l->data = strdup(s);
                l->next = NULL;
        } else {
                l->next = malloc(sizeof(list));
                l->data = strdup(s);
                l = l->next;
        }

        return l;
}

int main(void)
{
        FILE *f;
        list l;
        list *lp;
        char line[MAXLINE];

        f = fopen(INFILE, "r");

        lp = &l;

        while(fgets(line, MAXLINE-1, f))
        {
                line[MAXLINE-1] = '\0';
                if(line[0] == '#')
                        continue;
                lp = add_line(lp, line);
        }

        lp = &l;
        while(lp = lp->next)
                printf("%s", lp->data);
        fclose(f);
        return 0;
}

Re: Writing to an array
December 24, 2008 02:11AM
Quote
SpaceJump
What am I doing wrong?

I think your main issue is not providing any storage space for each new line you read in. It looks like you want to store each line in this array:
char *charArray[8];
The above allocates space to hold 8 pointers to a char. Your program will need to provide the memory for the data you plan to store at each of these addresses. The string functions themselves don't allocate any memory (expect for strdup). One common way to allocate strings, is to use the function strdup(). Its prototype looks like this:

char *strdup(const char *s);

And from its man page, "The strdup() function returns a pointer to a new string which is a duplicate of the string s. Memory for the new string is obtained with malloc(3), and can be freed with free(3)."

So in your code, each time you read in a new line, you would strdup() it, and assign the pointer from strdup() to an element in your charArray[].

Here's a version of your code which uses strdup (this needs more error/bounds checking):
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

char *charArray[255];   //maybe rename this lineArray, as it's an array of lines

int main(int argc, char *argv[])
{
  char line[1024];
  int current_line_num = 0;
  int i;

  FILE *fp = fopen("test.txt", "r");
  
  if (fp != NULL)
  {
    while(fgets(line, sizeof line, fp) != NULL) 
    {
      //skip lines which begin with a '#'
      if (line[0] == '#')
	continue;
      
      //make a copy of the current line using strdup (string duplicate)
      charArray[current_line_num] = strdup(line);

      current_line_num++;
    }

    //print results
    for(i = 0; i <current_line_num; i++)
      printf("%s", charArray);

    //release memory allocated by strdup's
    for(i = 0; i <current_line_num; i++)
      if (charArray != NULL)
        free(charArray);
  }
  return 0;
}
Re: Writing to an array
December 24, 2008 02:13AM
I prefer mine, naturally.
Re: Writing to an array
December 24, 2008 02:14AM
Thanks to all of you. I will try them and report back.
Re: Writing to an array
December 24, 2008 03:27AM
Good luck SpaceJump.

Quote
lordzid
I prefer mine, naturally.

So do I, but SpaceJump was asking for an explanation of why his code wasn't working, not for the best implementation, or at least that's how I took his question. Very nice implementation BTW, I like your use of linked lists here instead of arrays. I also like the way you don't try and cast every malloc() you use and I like that you use a static function. One thing missing is a way to de-allocate everything, that might be helpful to show SpaceJump and others.

Speaking of your's, would you mind explaining why you do the following in your code?
char line[MAXLINE];
...
while(fgets(line, MAXLINE-1, f))
Why do you pass in MAXLINE -1, rather than just MAXLINE? This is likely related to why you do this:
line[MAXLINE-1] = '\0';
Why do you do the above? As I understand fgets(), it will always place a '\0' at the end of the data it reads in.

Here's some info from fgets()'s man page:
Quote
man fgets
char *fgets(char *s, int size, FILE *stream);

fgets() reads in at most one less than size characters from stream and stores them into the buffer pointed to by s. Reading stops after an EOF or a newline. If a newline is read, it is stored into the buffer. A '\0' is stored after the last character in the buffer.
Re: Writing to an array
December 24, 2008 04:08PM
Thanks Michael for the explanations. I'm really used to Java that's why my approach in C is often a similar, which in this case didn't work.
Re: Writing to an array
December 24, 2008 04:18PM
Very likely because I wrote it from the top of my head into this message box :)

I was probably mashing 2 ideas into one.

I left the deallocation alone because I have no idea how he intends to use the data. I'm not even certain he really needs to store it at all given the information provided; people tend to ask why their solution doesn't work rather than stating what problem they are trying to solve.

If he's only using it once I'd never store it; else I'd use a recursive function to walk backwards up the list freeing it, similar to:
static void free_list(list *l)
{
        if(l->next)
                free_list(l->next);
        free(l->data);
        free(l);
}

Note you'd want to pass head->next rather than &head to avoid attempting to free heap data from main.

Another adaption, depending on need, would be to process it when walking down the tree, and free it as you came back up:
static void process_list(list *l)
{
        if(l->next) {
               printf("%s", l->data);
               free_list(l->next);
        }

        free(l->data);
        free(l);
}



Edited 2 time(s). Last edit at 12/24/2008 04:20PM by lordzid.
Re: Writing to an array
December 24, 2008 05:03PM
Thanks lordzid for the de-allocation code and explanation of it.
Sorry, only registered users may post in this forum.

Click here to login