Thread: MENSA Puzzle Solver: Question on char arrays and passing to/from functions

  1. #1
    Nub SWE
    Join Date
    Mar 2008
    Location
    Dallas, TX
    Posts
    133

    MENSA Puzzle Solver: Question on char arrays and passing to/from functions

    MENSA puts out these weekly word puzzles. For whatever reason I decided to try and write something which would solve them. The puzzles take the following format:
    A_I_T_C_A_I_
    ... where the underscore characters signify blanks that you have to fill in to find the word in the puzzle. Simple concept, fun to try and solve in your head. But I am bored at work, so here we are.

    I have really only started the process of getting my ideas down into code, and since this isn't for work or any assignment, I wanted to get some input from you guys on the problem I'm having. I have a char * that I pass into a GetWord() function. This GetWord() function prompts the user for the length of the word puzzle and then asks the user to input the word puzzle in the above format, with underscores indicating blanks to be filled in.

    Unfortunately, when I try to print the word puzzle in my main(), I get a bunch of garbage, whereas it prints perfectly in the GetWord() function. I'm thinking it's a problem with 1) how I'm utilizing malloc() inside the GetWord() function or 2) how I'm utilizing the char * back in the main().

    Here is the relevant code:
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    void GetWord(char *word, int *unknowns, int *word_length, int *num_unknowns);
    
    int main(void)
    {
    	int word_length;		/**< Length of the word puzzle. */
    	int num_unknowns;		/**< Number of unknown letters in the puzzle. */
    	char *word;				/**< The word puzzle. */
    	int *unknowns;			/**< An array containing the locations of unknown letters. */
    	
    	GetWord(word, unknowns, &word_length, &num_unknowns);
    	
    	printf("The puzzle to be solved is '%s', %d letters long.\n", word, word_length);
    	printf("There are %d unknowns.\n", num_unknowns);
    	
    	
    	printf("Press ENTER to exit.");
    	fflush(stdout);
    	scanf("%*c");
    	
    	return 0;
    }
    
    void GetWord(char *word, int *unknowns, int *word_length, int *num_unknowns)
    {
    	int j = 0;
    	int k = 0;
    	
    	*word_length = 0;
    	*num_unknowns = 0;
    	
    	while (*word_length <= 0)
    	{
    		printf("Please enter the total number of letters in the word: ");
    		fflush(stdout);
    		scanf("%d%*c", word_length);
    		
    		if (*word_length <= 0)
    		{
    			printf("Please enter a valid word length.\n");
    			fflush(stdout);
    		}
    		else
    		{
    			printf("You've input a word length of %d. Thank you.\n", *word_length);
    			fflush(stdout);
    			word = malloc(sizeof(char) * (*word_length + 1));
    			unknowns = malloc(sizeof(char) * (*word_length + 1));
    		}
    	}
    	
    	printf("Please enter the word puzzle to solve with length %d.\n", *word_length);
    	printf("Enter a _ character for each blank letter in the word.\n");
    	fflush(stdout);
    	
    	scanf("%s%*c", word);
    	strcat(word, "\0");				/**< Append a null to the end of the word puzzle. */
    	
    	for (k = 0; k < *word_length; k++)
    	{
    		/** If we have a blank space in the word puzzle ... */
    		if(word[k] == '_')
    		{
    			/** Add the current index into the 'unknowns' array for later. */
    			unknowns[j] = k;
    			/** Increment the number of unknowns. */
    			*num_unknowns = (*num_unknowns) + 1;
    			/** Increment the index of the 'unknowns' array. */
    			j++;
    		}
    	}
    	/** Place a '-1' at the end of the 'unknowns' array to signify the end of the array. */
    	unknowns[j] = -1;
    	
    	printf("The puzzle to be solved is %s. There are %d unknowns.\n", word, *num_unknowns);
    }
    And the output:
    Code:
    Please enter the total number of letters in the word: 12
    You've input a word length of 12. Thank you.
    Please enter the word puzzle to solve with length 12.
    Enter a _ character for each blank letter in the word.
    A_I_T_C_A_I_
    The puzzle to be solved is A_I_T_C_A_I_. There are 6 unknowns.
    The puzzle to be solved is 'Y[]Ã1Àƒ=ä@', 12 letters long.
    There are 6 unknowns.
    Press ENTER to exit.
    ... where the first "The puzzle to be solved is..." is found inside GetWord(), and the second is found back inside main().

    I haven't even begun to tackle the 'unknowns' array, but I can tell you that it basically just contains garbage at this point despite my attempts to populate it. Any general guidance on how to tackle the program as a whole is also welcome. Let me know if you have any ideas on the problem presented here, most importantly.

    Thanks,
    Jeremy

    P.S. The answer to the puzzle is aristocratic.

  2. #2
    Registered User
    Join Date
    Oct 2001
    Posts
    2,934
    > GetWord(word, unknowns, &word_length, &num_unknowns);
    C passes all arguments to a function by value. So for the case of word and unknowns, the function could change the data to which word pointed, but not the address of the pointer (because a copy of the address is passed). So to make it possible to change the pointer, you'd use the same method you used for word_length and num_unknowns, that is pass the address of the pointer:
    Code:
    	GetWord(&word, &unknowns, &word_length, &num_unknowns);
    And the function declaration would look like:
    Code:
    void GetWord(char **word, int **unknowns, int *word_length, int *num_unknowns);
    Another option would be to declare GetWord() to return either word or unknowns, but since a function can only return one value, this isn't feasible, unless you made a struct containing both. A third option would be to simply declare word and unknowns as fixed size arrays in main().

  3. #3
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    I have the same calendar!
    I'm not worried about the fact that you spoiled the answer for me as I would not have gotten it. However, allow me to tell you the answer to todays question: PORT.
    I know, I wouldn't have gotten that one either, I didn't even know two of those were words.

    Oh that reminds me, I must go back and do that Tom Swifty one that I skipped earlier.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  4. #4
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    Imo you should be dealing with the word as one string. No location of the unknowns is needed, and you pass one char array to any function you want.

    Actually, I wouldn't have the user tell you how long the word is, etc. Just have them enter the string, including the underlines, and your program does the figuring, from there on.

  5. #5
    Nub SWE
    Join Date
    Mar 2008
    Location
    Dallas, TX
    Posts
    133
    Thanks for the ideas here.

  6. #6
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Code:
    strcat(word, "\0");				/**< Append a null to the end of the word puzzle. */
    Note: that's completely unnecessary. scanf(), and nearly all standard string-handling functions, automatically add NULLs. (Notable exception: strncpy().)

    Plus, any string literal like "" or "hello" in your program automatically has a NULL at the end. In other words, "is" actually consists of three characters, 'i', 's', and '\0'.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  7. #7
    Registered User winfuk's Avatar
    Join Date
    Dec 2007
    Posts
    2
    $ grep -iR '^a[a-z]i[a-z]t[a-z]c[a-z]a[a-z]i[a-z]$' --color=auto /usr/share/dict/

    aristocratic ?

    cya

  8. #8
    Ex scientia vera
    Join Date
    Sep 2007
    Posts
    477
    Quote Originally Posted by winfuk View Post
    $ grep -iR '^a[a-z]i[a-z]t[a-z]c[a-z]a[a-z]i[a-z]$' --color=auto /usr/share/dict/

    aristocratic ?

    cya
    Awesome, you managed to find the solution, and thus doing nothing of what the OP asked.

    Congratulations.

    I think I'll start answering posts with "I know I can do it, haha!" just to prove how smart I am.
    "What's up, Doc?"
    "'Up' is a relative concept. It has no intrinsic value."

  9. #9
    Registered User guesst's Avatar
    Join Date
    Feb 2008
    Location
    Lehi, UT
    Posts
    179
    Quote Originally Posted by winfuk View Post
    $ grep -iR '^a[a-z]i[a-z]t[a-z]c[a-z]a[a-z]i[a-z]$' --color=auto /usr/share/dict/

    aristocratic ?

    cya
    That's funny to me. It'd not as input friendly, but then that's not what Linux is about it is?
    Type-ins are back! Visit Cymon's Games at http://www.cymonsgames.com for a new game every week!

  10. #10
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Code:
    $ grep a.i.t.c.a.i. /usr/share/dict/words
    aristocratic

  11. #11
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by IceDane View Post
    Awesome, you managed to find the solution, and thus doing nothing of what the OP asked.
    Why help the OP pound nails with a screwdriver?

  12. #12
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Quote Originally Posted by brewbuck View Post
    Why help the OP pound nails with a screwdriver?
    You've forgotten the key phrase: "bored at work".

  13. #13
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Did everyone miss this or something? . . .
    P.S. The answer to the puzzle is aristocratic.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Passing arrays of pointers into functions
    By ashley in forum C Programming
    Replies: 5
    Last Post: 01-13-2007, 06:48 PM
  2. Troubles passing 2D arrays of char
    By paulovitorbal in forum C Programming
    Replies: 5
    Last Post: 04-05-2006, 06:37 AM
  3. Passing pointers to arrays of char arrays
    By bobthebullet990 in forum C Programming
    Replies: 5
    Last Post: 03-31-2006, 05:31 AM
  4. Help Understanding Passing Arrays To Functions
    By jrahhali in forum C++ Programming
    Replies: 7
    Last Post: 04-10-2004, 02:57 PM
  5. Functions returning char arrays
    By turmoil in forum C Programming
    Replies: 3
    Last Post: 05-27-2003, 01:43 AM