Ok, I'm using gcc in ubuntu to compile.

Below is a boggle solver that basically loads a dictionary.txt file and then you would input a 5x5 grid of letters like below into the letter[][] array

a b c d e
f g h i j
k l m n o
p q r s t
u v w x y

one at a time at the terminal
a
b
c
ect.

however I'm trying to modify the program so that you can read in a second .txt file containing the above grid of letters in exactly that format directly into the letter[][] array (or any other combination of letters) instead of having to input each letter at the terminal and hitting enter. I've spent a few hours and it seems so simple but it's just not working. I keep getting segmentation faults and it's just not reading the grid of letters in the .txt file into the array correctly.

I've tried using both fgets and fscanf although probably incorrectly.

My problems are mostly occurring in int main() at the bottom for those who want to skip
down. I posted all the code in case you want to compile it on your own machine.

Working original version:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <ctype.h>
#include <time.h>

#define BOX_SIZE 5
#define MIN_WORD_LEN 3
#define NOT_SEEN 0
#define SEEN 1
#define FOUND_SIZE 1000
#define NUM_LETTERS 26
/* Define constants from dict.c */

 
 char *found[FOUND_SIZE];
 int graph[BOX_SIZE][BOX_SIZE];
 char choices[BOX_SIZE*BOX_SIZE];
 int letter[BOX_SIZE][BOX_SIZE];

 int num_found = 0; 

	
typedef struct trie_node TRIE_NODE;
struct trie_node {
	char let;
	char mark;
	TRIE_NODE *next[NUM_LETTERS];
};	

/* The grid of boggle letters. */




TRIE_NODE trie_root;
int trie_num_nodes;

void trie_init_node(TRIE_NODE *n)
{
	int i;
	n -> let = '\0';
	n -> mark = 0;

 for (i = 0; i < NUM_LETTERS; i++)
     n ->next[i] = NULL;
}

TRIE_NODE *trie_new_node(int let)
{
	TRIE_NODE *new_node;
	trie_num_nodes++;

	new_node = malloc(sizeof(TRIE_NODE));
	assert(new_node != NULL);

	trie_init_node(new_node);
	new_node -> let = let;

	return new_node;
}

void trie_init()
{
	trie_init_node(&trie_root);
	trie_num_nodes = 0;
}

void trie_add_word(char *word)
{
	TRIE_NODE *curr_node = &trie_root;
	char *curr_let;
	int next_let;

	if (word == NULL || *word == '\0')
	{
	  fprintf(stderr, "error: can't add null word to trie \n");
	}

	curr_let = word;

	while(*curr_let != '\0')
	{
	  next_let = tolower(*curr_let) - 'a';

	  if (next_let < 0 || next_let >= NUM_LETTERS)
	{
	   fprintf(stderr, "error: can't add word '%s' (illegal character)\n", word);
	   return;
	}

	if (curr_node->next[next_let] == NULL)
	curr_node->next[next_let] = trie_new_node(next_let);

	curr_node = curr_node->next[next_let];
	curr_let++;
	}

	curr_node->mark = 1;
}

char walk_buf[128];

void trie_walk_node(TRIE_NODE *n, int depth)
{
  int i;

  depth++;

  if (n->mark) 
  {
  walk_buf[depth] = '\0';
  puts(walk_buf);
  }


  for (int i = 0; i < NUM_LETTERS; i++)
	{
	  if (n->next[i] != NULL)
	    {
	      walk_buf[depth] = i + 'a';
	      trie_walk_node(n->next[i], depth);
            }
	}
}

void trie_walk()
{
     trie_walk_node(&trie_root, -1);
}


void try_print(int depth)
{

  int i;

  choices[depth] = '\0';

  if (num_found >= FOUND_SIZE)
   {
     printf("too many words found\n");
     return;
   }

  for (i = 0; i < num_found; i++)
    if (!strcmp(choices, found[i]))
       return;

     found[num_found++] = strdup(choices);
     printf("%s\n", choices);
}



void dfs(int x, int y, int depth, TRIE_NODE *trie_node)
{

    int i, j;


    if (x < 0 || y < 0 || x >= BOX_SIZE || y >= BOX_SIZE)
	return;

    if (graph[x][y] == SEEN)
        return;



    if ((trie_node = trie_node->next[letter[x][y]]) == NULL)
        return;

    choices[depth++] = letter[x][y] + 'a';

    if (trie_node->mark && depth >= MIN_WORD_LEN)
        try_print(depth);


    graph[x][y] = SEEN;

    for (j = -1; j <= 1; j++)
    for (i = -1; i <= 1; i++)
       if(i || j)
    dfs(x+i, y+j, depth, trie_node);

    graph[x][y] = NOT_SEEN;
}
int main ()
{



int i, j, let_number;
unsigned seed = (unsigned) time (0);
srand (seed);
char buf[128];

FILE *fp; 
FILE *fp2;
fp = fopen("wordlist.txt", "r");

if (fp == NULL)
{
  perror("Error opening dictionary.");
  exit(0);
}

trie_init();

while (fgets(buf, 128, fp))
{
   buf[strlen(buf)-1] = '\0';

   for (i = 0; i < strlen(buf); i++)
     buf[i] = tolower(buf[i]);
     trie_add_word(buf);
}


for (j = 0; j < BOX_SIZE; j++) {
    for (i = 0; i < BOX_SIZE; i++) {

      /* grab a char */
      do {
	scanf("%s", buf);
      } while (!isalpha(*buf));

      /* make sure it's legal */
      let_number = tolower(*buf) - 'a';
      if (let_number < 0 || let_number >= NUM_LETTERS) {
	fprintf(stderr, "illegal character '%c' in board\n", *buf);
	exit(1);
      }

      /* put it in our matrix */
      letter[i][j] = let_number;
      graph[i][j] = NOT_SEEN;
    }
  }

  /* walk the matrix */
  for (j = 0; j < BOX_SIZE; j++)
    for (i = 0; i < BOX_SIZE; i++)
      dfs(i, j, 0, &trie_root);

  return 0;

}

My attempt at what I'm trying to do //all my modifications are in main()

int main ()
{
int i, j, let_number;

char buf[128];
char buf2[128];
FILE *fp; 
FILE *fp2;
fp = fopen("wordlist.txt", "r");

if (fp == NULL)
{
  perror("Error opening dictionary.");
  exit(0);
}

trie_init();

while (fgets(buf, 128, fp))
{
   buf[strlen(buf)-1] = '\0';

   for (i = 0; i < strlen(buf); i++)
     buf[i] = tolower(buf[i]);
     trie_add_word(buf);
}


fp2 = fopen("puzzle.txt", "r");




for (j = 0; j < BOX_SIZE; j++)
 {
   
   for (i = 0; i < BOX_SIZE; i++)
 {
fscanf(fp2, "%c", &letter[i][j]);
let_number = tolower(letter[i][j]) - 'a';
letter[i][j] = let_number;
printf ("%d \n", letter[i][j]);

    graph[i][j] = NOT_SEEN;

   }
 }



  for (j = 0; j < BOX_SIZE; j++)
  for (i = 0; i < BOX_SIZE; i++)
     dfs(i, j, 0, &trie_root);


   return 0;

Recommended Answers

All 6 Replies

I figured it out, although the solution is probably not the best.

int main (int argc, char *argv[])
{

int i, j, let_number;
//BOX_SIZE = argv[3];
char buf[10000];

FILE *fp; 
FILE *fp2;
fp = fopen(argv[1], "r");

if (fp == NULL)
{
  perror("Error opening dictionary.");
  exit(0);
}

trie_init();

while (fgets(buf, 10000, fp))
{
   buf[strlen(buf)-1] = '\0';

   for (i = 0; i < strlen(buf); i++)
     buf[i] = tolower(buf[i]);
     trie_add_word(buf);
}

//trie_walk();

fp2 = fopen(argv[2], "r");





printf("The following grid was entered: \n");

for (j = 0; j < BOX_SIZE; j++)
 {
   
   for (i = 0; i < BOX_SIZE; i++)
 {

fscanf(fp2, "%c ", &letter[i][j]);
printf ("%c ", letter[i][j]);
let_number = tolower(letter[i][j]) - 'a';
letter[i][j] = let_number;

    graph[i][j] = NOT_SEEN;

   }
printf("\n");
 }

printf("The following words were found: \n");


  for (j = 0; j < BOX_SIZE; j++)
  for (i = 0; i < BOX_SIZE; i++)
     dfs(i, j, 0, &trie_root);


   return 0; 

}

However I'm stuck as how to set the grid size as the 3rd argument

1st argument = name of dictionary file
2nd argument = name of puzzle file
3rd argument = the size of the grid

However the size is already defined and if I try to change it through an argument
the compiler complains. What is the best solution around this or do I have to
re-structure the entire program?

I guess in a sense what I'm asking is: what is the best way to dynamically allocate my defined variables if I decide to set the grid size
at compilation time?

What are you doing with let_number = tolower(letter[i][j]) - 'a'; ?

Now, based on your description "it isn't reading correctly", do you think that's enough of a description for us to understand the problem? Please always give details so we can understand the problem. And where is the seg fault happening? 250 line of code is too much of a guess for us. Pinpoint at least the area of the error.

I understand, it's just I try to keep posts somewhat short since everytime I'm detailed, I either get no response or people say "dude keep your posts short next time ect."

But thanks for replying, I found a quick fix/hack to what I was having trouble with that I posted above.

However since you mention it, I tried googling doing -/+ 'a' operations in C and what they mean. I believe it's dealing with the ASCII values of character symbols? Am I wrong in that belief? What is the advantage of doing operations that way vs. normal character arrays?

I tried googling doing -/+ 'a' operations in C and what they mean. I believe it's dealing with the ASCII values of character symbols? Am I wrong in that belief?

'a' is an ASCII character symbol that has a value, so you are correct.

What is the advantage of doing operations that way vs. normal character arrays?

The question makes no sense. That way is an arithmetic technique. normal character arrays is a data storage technique. They are both useful.

What is the arithmetic technique behind it?

'a' has a numeric value. Addition and Subtraction work on the value. Therefore, 'a' - 'a' is 0. 'b' - 'a' is 1. 'D' - 'A' is 3. 'A' + 3 is 'D'.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.