0

I'm having real trouble working with strings and string arrays, and using strcpy correctly. I'm using a dictionary of words scanned in a 2D array dictionary. Then I take a start word, alter every letter of it to create many different variants, i.e cat -> cbt, cct, cdt, etc. From there I copy each generated word into a 2D array and to compare these generated words to the dictionary to see if they are real words. I then want to print these real words, i.e cat as a start word will generate bat if its in the dictionary, but zat won't be. When I run the code it prints all the generated words but when It gets to check_dictionary function it prints no words.

The text file it reads from is like:

mat
yes
cat
hat

The code:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define MAX_WORDS 20000
#define MAX_WORD_LENGTH 30
#define ARGS_REQUIRED 2

typedef struct scanned_words
{
  char startword[MAX_WORD_LENGTH];
  char endword[MAX_WORD_LENGTH];
} Scanned_words;

Scanned_words scan_two_words(Scanned_words words);
void get_next_word(Scanned_words words,
    char parentwords[MAX_WORDS][MAX_WORD_LENGTH]);
void read_file(char * argv[], char dictionary[MAX_WORDS][MAX_WORD_LENGTH]);
void check_dictionary(char dictionary[MAX_WORDS][MAX_WORD_LENGTH],
    char parentwords[MAX_WORDS][MAX_WORD_LENGTH]);
void usage(char * argv[]);

int main(int argc, char * argv[])
{
  char dictionary[MAX_WORDS][MAX_WORD_LENGTH];
  char nextword[MAX_WORDS][MAX_WORD_LENGTH];
  char parentwords[MAX_WORDS][MAX_WORD_LENGTH];
  Scanned_words words;

  if (argc == ARGS_REQUIRED)
  {
    system("clear");
    read_file(&argv[1], dictionary);
    words = scan_two_words(words);
    get_next_word(words, parentwords);
    check_dictionary(dictionary, parentwords);
  }
  else
  {
    usage(&argv[0]);
  }

  return 0;
}

void read_file(char * argv[], char dictionary[MAX_WORDS][MAX_WORD_LENGTH])
//reads the text file and stores the dictonary as a 2D array
{
  FILE * file_name;
  int word_count = 0, i;

  if ((file_name = fopen(argv[0], "r")) == NULL )
  {
    printf("Cannot open file ... \n");
  }
  while (fscanf(file_name, "%s", dictionary[i++]) == 1)
  {
    printf("%s ", dictionary[word_count]);
    word_count++;
  }

  printf("\n");
  printf("\n%d words scanned in from: %s\n\n", word_count, argv[0]);
}

Scanned_words scan_two_words(Scanned_words words)
//takes an empty structure, scans both words in and returns them in the same structure
{
  printf("Enter the start word: \n");
  scanf("%s", words.startword);
  printf("\nEnter the end word: \n");
  scanf("%s", words.endword);
  printf("\n");

  return words;
}

void get_next_word(Scanned_words words,
    char parentwords[MAX_WORDS][MAX_WORD_LENGTH])
//get all eligible second words from original start word
{
  char character;
  char currentword[MAX_WORD_LENGTH];
  int i;

  strcpy(currentword, words.startword);

  for (i = 0; currentword[i] != '\0'; i++)
  {
    strcpy(currentword, words.startword);
    for (character = 'a'; character <= 'z'; character++)
    {
      currentword[i] = character;
      strcpy(parentwords[i], currentword);
      printf("%s ", parentwords[i]);
    }
  }
  parentwords[i][0] = '\0';

  printf("\n\n");
}

void check_dictionary(char dictionary[MAX_WORDS][MAX_WORD_LENGTH],
    char parentwords[MAX_WORD_LENGTH][MAX_WORD_LENGTH])
//checks a generated word for eligibility against the dictionary, prints next generation words
{
  int i, j;

  printf("\nSecond words: \n\n");

  for (j = 0; parentwords[j][0] != '\0'; j++)
    ;
  {
    for (i = 0; dictionary[i][0] != '\0'; i++)
    {
      if ((strcmp(dictionary[i], parentwords[j])) == 0)
      {
        printf("%s \n", parentwords[j]);
      }
    }
  }
}

void usage(char * argv[])
//prints error message
{
  printf("Incorrect usage, try: ./program_name %s\n", argv[1]);
}
alk
  • 69,737
  • 10
  • 105
  • 255
Finlandia_C
  • 385
  • 6
  • 19
  • 2
    The indentation is atrocious... And you should do your own debugging. If `check_dictionary` prints nothing, then the code inside the loops is most likely not executed. Print the variables you're using as conditions and see why. – user4520 Nov 15 '15 at 17:38
  • Why is that? variables arent't indented, loops are indented with one tab and +1 tab further in. Other code lines up with the loops brackets. – Finlandia_C Nov 15 '15 at 17:39
  • The problem is I think that when I copy a generated word into the 2D array it isnt doing it, but I'm not sure why. – Finlandia_C Nov 15 '15 at 17:42
  • Do not use TABs when pasting code in here (or probably just stop using TABs at all ;-)) – alk Nov 15 '15 at 17:42
  • `char dictionary[MAX_WORDS][MAX_WORD_LENGTH];` - yeah, 600,000 bytes on the stack! Great idea! – Tom Zych Nov 15 '15 at 17:49
  • @TomZych Appropriate to be so sarcastic? I've been struggling with this for days, constructive criticism at least would be better. – Finlandia_C Nov 15 '15 at 17:51
  • @Finlandia_C: Well, read up on `malloc()` and find out how to allocate space without filling up the stack. – Tom Zych Nov 15 '15 at 17:52

1 Answers1

1

The formatting revealed this:

  for (j = 0; parentwords[j][0] != '\0'; j++)
;

which most probably was meant to be:

 for (j = 0; parentwords[j][0] != '\0'; j++)

Here

  while (fscanf(file_name, "%s", dictionary[i++]) == 1)

the i is used uninitialised

So change it definition to include an initialisation:

  int word_count = 0, i = 0;
alk
  • 69,737
  • 10
  • 105
  • 255
  • 1
    So when the following (supposedly?) nested `i` loop iterates, `j` was out of range. – Weather Vane Nov 15 '15 at 17:51
  • @WeatherVane ... and with this the infamous Undefined Behaviour gets invoked and from then on anything could happen. – alk Nov 15 '15 at 17:53