Thread: .dat to a 2D array

  1. #1
    Registered User
    Join Date
    Nov 2009
    Posts
    59

    .dat to a 2D array

    Hi

    I am writing a program and unfortunately have already come across the first problem. Generally I am trying to write a 2 column, 10000 row .dat file to a 2D array. I do not want to declare an array of fixed length so I am trying to count the columns and entries (and that means entry/column=rows)

    So starting out I wrote this;

    Code:
    int main(int argc, char* argv[])
    {
    	FILE*		input;
    	const char	input_fn[]="proj3input.dat";
    	char 		linebuf[1025];
    	char 		*tokptr, *strptr = linebuf;
    	int			col;
    	
    	
    	input=fopen("proj3input.dat","r");
    	
    	
    	
    	
    	col=0;
    	fgets(linebuf, 1024, input);
        while((tokptr=(char*)strtok(strptr, " \t\n\r\b,")) != NULL);
        {
            strptr = NULL;
            col++;
        }
    	printf("Number of columns is %d \n",col);
    	return(0);
    }
    Running it gives me a new line in UNIX and then it just hangs there. I have a feeling it is something to do with the NULL?

    Any ideas? Thanks

  2. #2
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    Code:
    	col=0;
    	fgets(linebuf, 1024, input);
        while((tokptr=(char*)strtok(strptr, " \t\n\r\b,")) != NULL);
        {
            strptr = NULL;
            col++;
        }
    	printf("Number of columns is %d \n",col);
    	return(0);
    }
    Oh my!


    All you need is
    Code:
    int line_num = 0;
    
    while((fgets(linebuf, 1024, input) != NULL)
      line_num++;
    This is true regardless of the number of columns in the row, (up to a total of 1024 char's).

    Remember that fgets stops when it reaches the newline, regardless of the number of char's.

  3. #3
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Throw a printf("%s\n%s\n\n",tokptr,strptr) into the while loop to see what is going on. And maybe reduce your delimiter list to " \t", as Adak points out linebuf will only have one line in it, and the \n will be at the end.

    Keep in mind that if the .dat is not readable as text (ie. it is a "binary" file), you cannot read it this way.
    Last edited by MK27; 01-22-2010 at 09:48 AM.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  4. #4
    Registered User
    Join Date
    Nov 2009
    Posts
    59
    Thanks very much Adak, but that gives line number, rather than column number....are you saying I shouldn't even bother working out column number in order to assign 1 column to each dimension of the 2d array? (Not sure that the terminology is right there, what i mean is to create array[i][j] and assign column 1 of data to [i] and column 2 to [j])

    @MK27....i took out the other delimiters and pasted your code. Still hangs on newline....?

    Thanks

  5. #5
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by browser View Post
    @MK27....i took out the other delimiters and pasted your code. Still hangs on newline....?

    Thanks
    strtok() won't hang on a newline. Did the printf reveal anything?

    Code:
        while((tokptr=(char*)strtok(strptr, "  \t")) != NULL);
        {
            printf("DATA: %s\n",tokptr); fflush(stdout);
            strptr = NULL;
            col++;
        }
    Using fflush() guarrantees the data will be printed right away.

    If it does not print out anything (inc. "DATA: ") then the loop has not executed because strtok failed to find anything, meaning you need to check the actual contents of strptr before the loop.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  6. #6
    Registered User
    Join Date
    Nov 2009
    Posts
    59
    Code:
    int main(int argc, char* argv[])
    {
    	FILE*		input;
    	const char	input_fn[]="proj3input.dat";
    	char 		linebuf[1025];
    	char 		*tokptr, *strptr = linebuf;
    	int			col=0, line_num=0;
    	
    	
    	input=fopen("proj3input.dat","r");
    	
    	
    	while((fgets(linebuf, 1024, input) != NULL))
    	line_num++;
    
    	
    	
    	printf("Number of lines is %d \n", line_num);
    	while((tokptr=(char*)strtok(strptr, "  \t")) != NULL);
        {
            printf("DATA: %s\n",tokptr); fflush(stdout);
            strptr = NULL;
            col++;
        }
    	printf("Number of columns is %d \n", col);
    
    	return(0);
    }
    This prints "Number of lines is 10000" Then hangs on new line. I will have a look at the strtok() again in more detail, but I couldn't see anything wrong at first glance.

    Is there any other way of counting the columns?

  7. #7
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    There is absolutely no sense in believing strtok() "does not work" for some reason, unless you are using some bizarre and completely useless compiler.

    Here's an example of "premise testing". You can do this to evaluate how a function or element of syntax works. The idea is to write a short program as simple as possible.
    Code:
    #include <stdio.h>
    #include <string.h>
    
    int main(void) {
    	int n = 0;
    	char columns[]="hello\tthere world", *ptr = columns, *tok;
    
    	while ((tok=strtok(ptr," \t"))) {    /* same as using != NULL */
    		ptr = NULL;
    		printf("%s\n",tok);
    		n++;
    	}
    	printf("%d columns\n",n);
    
    	return 0;
    }
    The output should be:
    hello
    there
    world
    3 columns


    So, this proves that if your data has spaces and tabs in it, strtok will break the line. Therefore, your data does not have spaces and tabs in it.

    Print out your data right before the loop (it is only one line, after all, since you did not save the rest of it anywhere) and see if there are spaces or tabs. You may want to do this:
    Code:
    for (i=0;i<strlen(data);i++) printf("%d ",data[i]);
    This will print the ascii value (see ASCII Table / Extended ASCII Codes) for each character in a string. For example, "hello\tthere world" is
    104 101 108 108 111 9 116 104 101 114 101 32 119 111 114 108 100
    Notice, the \t is 9 and the space is 32. You can use this to determine what character is actually used to break the columns.

    PS. I notice you cast strtok() to return a char*, which is what it does anyway. Was that because you got a "assignment makes pointer from integer without a cast" type error? You must #include <string.h> to use strtok.
    Last edited by MK27; 01-22-2010 at 03:57 PM.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  8. #8
    Registered User
    Join Date
    Nov 2009
    Posts
    59
    I compiled the code for the premise test and it worked fine.

    I then tried to add the code you gave for printing the data but I'm getting a segmentation error....I am new to C so perhaps I have made a mistake...

    Code:
    int main(void)
    {
    	FILE*		input;
    	const char	input_fn[]="proj3input.dat";
    	char		linebuf[1025];
    	char 		*tokptr, *strptr = linebuf;
    	int			col=0, i;
    	const char	data[i];
    	
    	
    	input=fopen("proj3input.dat","r");
    	
    	
    	for (i=0;i<strlen(data);i++) 
    	{
    		printf("%d ",data[i]);
    	}
    	while((tokptr=(char*)strtok(strptr, "  \t")) != NULL);
        {
            printf("DATA: %s\n",tokptr); fflush(stdout);
            strptr = NULL;
            col++;
        }
    	printf("Number of columns is %d \n", col);
    
    	return(0);
    }
    oh, and I have included string.h for all these codes....

  9. #9
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    No, you did not:

    Code:
    while((tokptr=(char*)strtok(strptr, "  \t")) != NULL);
    Lose that semi-colon, and it would help if you would indent your code like you know it should be.

  10. #10
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Adak is right, but that is not the cause of your seg fault.

    Code:
    	int			col=0, i;
    	const char	data[i];
    	
    	
    	input=fopen("proj3input.dat","r");
    	
    	
    	for (i=0;i<strlen(data);i++) 
    	{
    		printf("%d ",data[i]);
    	}
    So, on the first line here you declare "i", but since it has not been initialized to any particular value, it could hold ANY value -- you can't know what it is. Then you declare "data[i]", meaning this will be an uninitialized char string of some random (probably excessive) length. Then for some reason you want to print this out?

    My intent with the previous example
    for (i=0;i<strlen(data);i++) printf("%d ",data[i]);
    was that "data" stood in for some other variable, to illustrate that you can do this with any valid C string. I should have made this clearer: in your case, you do not need to create a new variable, "data", you would use strptr instead, before the while loop, and after you have read some data (ie, content) from the file into strptr. This is because you need to check:
    1) that there is valid content in strptr before you apply strtok
    2) what character is used to separate the columns in that content.

    Get it? Ie:
    -open file and fread data into linebuf. close the file.
    -print the ascii values for the data in strptr (which points to linebuf):
    Code:
    for (i=0;i<strlen(strptr);i++) printf("%d ",strptr[i]);
    -now apply your strtok loop
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  11. #11
    Registered User
    Join Date
    Nov 2009
    Posts
    59
    thanks Adak, i got rid of the semi colon on my other while as well and removed a printf that I had within the loop.

    It is now counting it fine. Thanks guys!

    edit: sorry MK27.....didn't refresh the page before posting a reply!

    I tried it your way as well and it worked as well! Thanks
    Last edited by browser; 01-23-2010 at 12:41 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Help with mallocing a 2d array please?
    By Gatt9 in forum C Programming
    Replies: 5
    Last Post: 10-10-2008, 03:45 AM
  2. 2D array becoming "deallocaded"
    By Aaron M in forum C Programming
    Replies: 2
    Last Post: 09-23-2006, 07:53 AM
  3. 2D array pointer?
    By willc0de4food in forum C Programming
    Replies: 4
    Last Post: 04-23-2006, 08:16 AM
  4. Read file in 2D array
    By Chook in forum C Programming
    Replies: 1
    Last Post: 05-08-2005, 12:39 PM
  5. Class Template Trouble
    By pliang in forum C++ Programming
    Replies: 4
    Last Post: 04-21-2005, 04:15 AM