Thread: Real problems reading from a text file into an array

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

    Real problems reading from a text file into an array

    Hello all, firstly I'm happy to join this forum, secondly, I need some help. I'm trying to write a hangman game in c but I cannot for the life of me get my array filled properly. Here is the code so far:

    Code:
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <time.h>
    #include <getopt.h>
    
    char *dict = "/usr/dict/words";
    int numGuess = 10;
    
    void dictAtrb()
    {
    	FILE *dictFile;
    	char c;
    	int words = 0, max = 0, current = -1;
    	
    	if((dictFile = fopen(dict,"r")) == NULL)
    	{
    		printf("Could not load dictionary");
    		exit (1);
    	}
    	
    	while(c!=EOF)
    	{
    		c = fgetc(dictFile);
    		
    		if(c == '\n')
    		{
    			words++;
    			
    			if(current > max)
    			{
    				max = current;
    			}
    			current = -1;
    		}
    		else
    		{
    		current++;
    		}
    	}
    	
    	fclose(dictFile); 
    		
    	printf("%d words with max length %d\n",words,max);
    }
    
    void buildDict()
    {
    	FILE *dictFile;
    	char tempArray[BUFSIZ];
    	char dictArray[6];
    	char *p;
    	int i = 0, count = 0, maxCount = 6;
    	
    	if((dictFile = fopen(dict,"r")) == NULL)
    	{
    		printf("Could not load dictionary");
    		exit (1);
    	}
    	
    	while(fgets(tempArray, BUFSIZ, dictFile) != NULL)
    	{
    		if((p = strchr(tempArray, '\n')) != NULL)
    		{
    			*p = '\0';
    		}
    		if(count == maxCount)
    		{
    			break;
    		}
    		strcpy(dictArray[count], tempArray);
    		count++;
    	}
    	
    	for(i; i < count; i++)
    	{
    		printf("%s\n", dictArray[i]);
    	}
    	
    	fclose(dictFile);
    }
    
    int main( int argc, char* argv[] )
    {
    	srand(time(NULL));
    	
    	if(argc > 1)
    	{
    		char c;
    		while ((c = getopt(argc, argv, "g:s:f:n")) != -1)
    		{
    			switch(c)
    			{
    				case 'g':
    					numGuess = atoi(optarg);
    					break;
    				case 's':
    					srand(atoi(optarg));
    					break;
    				case 'f':
    					dict = optarg;
    					break;
    				/*case 'n':*/
    				default:
    					printf("Invalid argument. Use -g, -s, -f or -n\n");
    				break;
    			}
    		}
    	}
    	/*display welcome*/
    	printf("\nWelcome to Hangman\n");
    	printf("-\n");
    
    	/*display random seed*/
    	printf("Random seed was %d\n",rand());
    
    	/*load and display dictionary*/
    	printf("Load dictionary from file: %s\n",dict);
    
    	dictAtrb();
    	buildDict();
    	
    	return 0;
    }
    My issues occur in the buildDict function, where I am trying to read words from a text file into an array. I'm currently using an array of size 6 to work with my test dictionary of 6 words, before I try to make it dynamically create it's own size. I realise this could probably be done by passing in the "words" value from the dictAtrb function but I'm not too hot on this and so not too sure how to do this.

    When I compile the code I get:

    hangman.c: In function 'buildDict':
    hangman.c:69: warning: passing arg 1 of 'strcopy' makes pointer from integer without a cast

    When I run it, it crashes with a segmentation fault
    Last edited by cherryduck; 11-03-2009 at 05:50 PM.

  2. #2
    {Jaxom,Imriel,Liam}'s Dad Kennedy's Avatar
    Join Date
    Aug 2006
    Location
    Alabama
    Posts
    1,065
    Quote Originally Posted by man fgetc
    NAME
    fgetc, fgets, getc, getchar, gets, ungetc - input of characters and strings

    SYNOPSIS
    #include <stdio.h>

    int fgetc(FILE *stream);
    You are attempting to get a char from fgetc() which returns an int.

  3. #3
    Registered User
    Join Date
    Nov 2009
    Posts
    11
    fgetc is made for char's as far as I'm aware? And I only use fgetc in the dictAtrb function, which is not where I am having my issues. It quite happily reads through the file and counts the number of words and the longest word. It's when I try to use fgets to read the strings into my array in the buildDict function that I encounter issues.

  4. #4
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by cherryduck View Post
    fgetc is made for char's as far as I'm aware? And I only use fgetc in the dictAtrb function, which is not where I am having my issues. It quite happily reads through the file and counts the number of words and the longest word. It's when I try to use fgets to read the strings into my array in the buildDict function that I encounter issues.
    fgetc() returns an integer which is the character code of the next character in the input stream. The reason it doesn't return a plain old char is because it needs to be able to return the special value of EOF, which is outside of the range 0..255. If the return value of fgetc() is not EOF, then it is guaranteed to be a character in the range 0..255. So you can process and store these inputs as chars, but when you call fgetc(), you must use an integer (and check for EOF!)

    Otherwise, fgetc() would have no way of reporting that it hit end-of-file.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  5. #5
    Registered User
    Join Date
    Nov 2009
    Posts
    11
    Okay, well I've changed it to int c = 0; and it works exactly the same as before, with the same error. Still having issues with my buildDict function

  6. #6
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    The dictArray[] only has room for six char's. Wow! that's not much. You'll really have to watch out for array over-runs.

    Code:
    void buildDict()
    {
    	FILE *dictFile;
    	char tempArray[BUFSIZ];
    	char dictArray[6];
    	char *p;
    	int i = 0, count = 0, maxCount = 6;
    	
    	if((dictFile = fopen(dict,"r")) == NULL)
    	{
    		printf("Could not load dictionary");
    		exit (1);
    	}
    	
    	while(fgets(tempArray, BUFSIZ, dictFile) != NULL)
    	{
    		if((p = strchr(tempArray, '\n')) != NULL)
    		{
    			*p = '\0';
    		}
    		if(count == maxCount)
    		{
    			break;
    		}
    		strcpy(dictArray[count], tempArray);
    		count++;
    	}
    	
    	for(i; i < count; i++)
    	{
    		printf("%s\n", dictArray[i]);
    	}
    	
    	fclose(dictFile);
    }
    Then, strcpy() is being given an array element as the destination, when strcpy needs a pointer to char. Maybe you meant:

    strcpy(&dictArray[count], tempArray); //??

    The size problem remains, however. You can't copy tempArray into dictArray[] - just not nearly enough room.

    I recommend using strncpy() instead, and giving maxCount as the last parameter to it:

    strncpy(dictArray, tempArray, maxCount);

    Then, in the for loop that prints dictArray, you're mixing printing char by char, with printing by an entire string.

    printf("\n %s", dictArray); should be all you need *IF* your strings have an '\0' char on the end of them to mark them as strings, and not just as a bunch of char's.

    I haven't run your code yet, but will do so, if this doesn't help you resolve the problem.

  7. #7
    Registered User
    Join Date
    Nov 2009
    Posts
    11
    Thank you very much for the reply and the assistance...after code corrections the program now compiles without error, but runs in an infinite loop.

    It now prints the welcome and the other information up to the point where it tells me how many words there are and the length of the longest word, then prints the word "check" 6 times over, which is the last word in my test dictionary, and repeats.

    It does this over and over so fast, that the only way I was able to see what was happening was by print screening to Paint.

    I have also adjusted the dictArray to be able to contain 100 char's, purely for testing and trying to get it to work. Ideally I want to be using the words or max value from the dictAtrb function, not sure which as I'm unsure how these arrays work? And not sure quite how to as well, I'm used to Java and all this pointer business is confusing me so much :S

    EDIT:

    Nvm, the loop is caused because I added a while loop in the main for other functions I'm also trying to implement...commented it out, it runs once and prints the last word in the dictionary file 6 times. It doesn't seem to matter what I set my maxCount too, it still prints "check" 6 times.
    Last edited by cherryduck; 11-04-2009 at 08:51 AM.

  8. #8
    Registered User
    Join Date
    Nov 2009
    Posts
    11
    I decided to try a different approach, and voila it seems to be working! To an extent...

    Code:
    void buildDict()
    {
    	FILE *dictFile;
    	char dictArray[100];
    	int c = 0;
    	int i = 0, count = 0, maxCount = 6;
    	
    	if((dictFile = fopen(dict,"r")) == NULL)
    	{
    		printf("Could not load dictionary");
    		exit (1);
    	}
    	
    	while(c != EOF)
    	{
    		c = fgetc(dictFile);
    		dictArray[i] = c;
    		i++;
    	}
    	
    	int length = strlen(dictArray);
    	
    	i = 0;
    	
    	for(i;i < length; i++)
    	{
    		printf("%c",dictArray[i]);
    	}
    	
    	fclose(dictFile);
    }
    Only problem now is that for whatever reason it prints my dictionary successfully, but with a weird y and E at the end, with two dots above each word

  9. #9
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    Those last two char's are showing a fault to your logic. Somehow, someway, your program is not putting an end of string char to mark the end of the word, where it needs to go.

    Myself, I am wondering why you're reading in an entire file, when you only are using one word. What's with that?

    Trim down your input to what you need, get each word marked with an end of string char, and it will all come together for you.

  10. #10
    Registered User
    Join Date
    Nov 2009
    Posts
    11
    I'm reading in every word because I then need to be able to use the list of words to choose a random word to be guessed. I'm not sure if I can randomly choose a word directly from the input file without loading them into an array first?

  11. #11
    Registered User
    Join Date
    Nov 2009
    Posts
    11
    My latest attempt:

    Code:
    void buildDict()
    {
    	FILE *dictFile;
    	char dictArray[100];
    	int c = 0;
    	int i = 0;
    	
    	if((dictFile = fopen(dict,"r")) == NULL)
    	{
    		printf("Could not load dictionary");
    		exit (1);
    	}
    	
    	while(c != EOF)
    	{
    		c = fgetc(dictFile);
    		
    		if(c == '\n')
    		{
    			dictArray[i] = '\0';
    			i++;
    		}
    		else
    		{
    			dictArray[i] = c;
    			i++;
    		}
    	}
    	
    	int length = strlen(dictArray);
    	
    	i = 0;
    	
    	for(i; i < length; i++)
    	{
    		printf("%c",dictArray[i]);
    	}
    	
    	fclose(dictFile);
    }
    The problem now is that it won't print ANYTHING from the array.

  12. #12
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    Quote Originally Posted by cherryduck View Post
    I'm reading in every word because I then need to be able to use the list of words to choose a random word to be guessed. I'm not sure if I can randomly choose a word directly from the input file without loading them into an array first?
    Then why not use a 2D char array?

    It's easy to stick some words into a 1D array, but it's a PITA to go ahead and work with them, from a 1D array:

    Code:
    words[] = {"I like riding"};
    
    words[3][] {
    {"I"},
    {"like"},
    {"riding"}};
    Now it's so simple to work with the words in the 2D array.
    Code:
    for(i = 0; i < 3; i++)
      printf("\n %s ", words[i]);
    Because every word is in it's own row (the first index of the 2D array. You can work with a char *pointer the same way, but ONLY (AFAIK), if the data is put into it, when it's declared, and that's not what you want.

    This is the normal C array type for working with strings (An array of char pointers along with an array of char's, is the very best way to do this, but not needed for a small word list).

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Dikumud
    By maxorator in forum C++ Programming
    Replies: 1
    Last Post: 10-01-2005, 06:39 AM
  2. struct question
    By caduardo21 in forum Windows Programming
    Replies: 5
    Last Post: 01-31-2005, 04:49 PM
  3. Unknown Memory Leak in Init() Function
    By CodeHacker in forum Windows Programming
    Replies: 3
    Last Post: 07-09-2004, 09:54 AM
  4. Reading in text file into an array, white spaces...
    By error in forum C++ Programming
    Replies: 12
    Last Post: 01-14-2003, 09:39 AM
  5. File I/O problems!!! Help!!!
    By Unregistered in forum C Programming
    Replies: 4
    Last Post: 05-17-2002, 08:09 PM