0

So I need to create a word search program that will read a data file containing letters and then the words that need to be found at the end for example:

f a q e g g e e e f


o e q e r t e w j o


t e e w q e r t y u


government


free

and the list of letters and words are longer but anyway I need to save the letters into an array and i'm having a difficult time because it never stores the correct data. here's what I have so far

#include <stdio.h>

int main()
{
int value;
char letters[500];

while(!feof(stdin))
{
   value = fgets(stdin);

   for(int i =0; i < value; i++)
   {
      scanf("%1s", &letters[i]);
   }

   for(int i=0; i<1; i++)
   {
      printf("%1c", letters[i]);
   }
}
}

I also don't know how I am gonna store the words into a separate array after I get the chars into an array.

McLovinIt
  • 45
  • 1
  • 6
  • 1
    Please note that `feof()` does NOT say whether you are at the end of the file; It says whether you've encountered EOF yet or not. It is possible to be _exactly_ at the end of a file and yet not have attempted to go past it, and in that case `feof()` will return `0` until such time as you attempt to read one more byte (and fail). – Iwillnotexist Idonotexist Sep 27 '17 at 05:59
  • 1
    Consider using `getline` like [here](https://stackoverflow.com/a/9171511/841108) – Basile Starynkevitch Sep 27 '17 at 06:54
  • 1
    Is there a symbol or string of characters in the file that will enable your code to distinguish between where the _letters_ end, and the _words_ begin? – ryyker Sep 27 '17 at 12:51

4 Answers4

2

You said you want to read from a data file. If so, you should open the file.

FILE *fin=fopen("filename.txt", "r");
if(fin==NULL)
{
    perror("filename.txt not opened.");
}

In your input file, the first few lines have single alphabets each separated by a space.

If you want to store each of these letters into the letters character array, you could load each line with the following loop.

char c;
int i=0;
while(fscanf(fin, "%c", &c)==1 && c!='\n')
{
    if(c!=' ')
    {
        letters[i++]=c;
    }
}

This will only store the letters and is not a string as there is no \0 character.

Reading the words which are at the bottom may be done with fgets().

Your usage of the fgets() function is wrong.

Its prototype is

char *fgets(char *str, int n, FILE *stream);

See here.

Note that fgets() will store the trailing newline(\n) into string as well. You might want to remove it like

str[strlen(str)-1]='\0';

Use fgets() to read the words at the bottom into a character array and replace the \n with a \0.

and do

fgets(letters, sizeof(letters, fin);

You use stdin instead of the fin here when you want to accept input from the keyboard and store into letters.

Note that fgets() will store the trailing newline(\n) into letters as well. You might want to remove it like

letters[strlen(letters)-1]='\0';


Just saying, letters[i] will be a character and not a string.
scanf("%1s", &letters[i]);

should be

scanf("%c", &letters[i]);
J...S
  • 5,079
  • 1
  • 20
  • 35
1

One way to store the lines with characters or words is to store them in an array of pointers to arrays - lines,

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

#define MAXLET 500
#define MAXLINES 1000

int main()
{
    char *lptr;
    // Array with letters from a given line
    char letters[MAXLET];
    // Array with pointers to lines with letters
    char *lineptr[MAXLINES];

    // Length of current array
    unsigned len = 0;
    // Total number of lines
    int nlines = 0;

    // Read lines from stdin and store them in 
    // an array of pointers
    while((fgets(letters,MAXLET,stdin))!=NULL)
    {
        len = strlen(letters);
        letters[len-1] = '\0';
        lptr = (char*) malloc(len);
        strcpy(lptr, letters);
        lineptr[nlines++]=lptr;
    }

    // Print lines
    for (int i = 0; i < nlines; i++)
        printf("%s\n", lineptr[i]);

    // Free allocated memory
    for (int i = 0; i < nlines; i++)
        free(lineptr[i]);
}

In the following, pointer to every line from stdin is stored in lineptr. Once stored, you can access and manipulate each of the lines - in this simple case I only print them one by one but the examples of simple manipulation are shown later on. At the end, program frees the previously allocated memory. It is a good practice to free the allocated memory once it is no longer in use.

The process of storing a line consists of getting each line from the stdin, collecting it's length with strlen, stripping it's newline character by replacing it with \0 (optional), allocating memory for it with malloc, and finally storing the pointer to that memory location in lineptr. During this process the program also counts the number of input lines.

You can implement this sequence for both of your inputs - chars and words. It will result in a clean, ready to use input. You can also consider moving the line collection into a function, that may require making lineptr type arrays global. Let me know if you have any questions.

Thing to remember is that MAXLET and especially MAXLINES may have to be increased for a given dataset (MAXLINES 1000 literally assumes you won't have more than a 1000 lines).

Also, while on Unix and Mac this program allows you to read from a file as it is by using $ prog_name < in_file it can be readily modified to read directly from files.

Here are some usage examples - lineptr stores pointers to each line (array) hence the program first retrieves the pointer to a line and then it proceeds as with any array:

// Print 3rd character of each line
// then substitute 2nd with 'a'
char *p;
for (int i = 0; i < nlines; i++){
    p = lineptr[i];
    printf("%c\n", p[2]);
    p[1] = 'a';
}

// Print lines
for (int i = 0; i < nlines; i++)
    printf("%s\n", lineptr[i]);

// Swap first and second element
// of each line
char tmp;
for (int i = 0; i < nlines; i++){
    p = lineptr[i];
    tmp = p[0];
    p[0] = p[1];
    p[1] = tmp;
}

// Print lines
for (int i = 0; i < nlines; i++)
    printf("%s\n", lineptr[i]);

Note that these examples are just a demonstration and assume that each line has at least 3 characters. Also, in your original input the characters are separated by a space - that is not necessary, in fact it's easier without it.

atru
  • 4,699
  • 2
  • 18
  • 19
1

The code in your post does not appear to match your stated goals, and indicates you have not yet grasp the proper application of the functions you are using.
You have expressed an idea describing what you want to do, but the steps you have taken (at least those shown) will not get you there. Not even close.

It is always good to have a map in hand to plan to plan your steps. An algorithm is a kind of software map. Before you can plan your steps though, you need to know where you are going.

Your stated goals:

1) Open and read a file into lines.    
2) Store the lines, somehow. (using fgets(,,)?)     
3) Use some lines as content to search though.  
4) Use other lines as objects to search for  

Some questions to answer:

a) How is the search content distinguished from the strings to search for?
b) How is the search content to be stored?
c) How are the search words to be stored?
d) How will the comparison between content and search word be done?
e) How many lines in the file? (example)
f) Length of longest line? (discussion and example) (e & f used to create storage)
g) How is fgets() used. (maybe a google search: How to use fgets)
h) Are there things to be aware of when using feof()? (discussion and examaple feof)
i) Why is my input not right after the second call to scanf? (answer)

Finish identifying and crystallizing the list of items in your goals, then answer these (and maybe other) questions. At that point you will be ready to start identifying the steps to get there.

ryyker
  • 22,849
  • 3
  • 43
  • 87
0

value = fgets(stdin); is a terrible expression! You don't respect at all the syntax of the fgets function. My man page says

char * fgets(char * restrict str, int size, FILE * restrict stream);

So here, as you do not pass the stream at the right place, you probably get an underlying io error and fgets returns NULL, which is converted to the int 0 value. And then the next loop is just a no-op.

The correct way to read a line with fgets is:

if (NULL == fgets(letters, sizeof(letters), stdin) {
    // indication of end of file or error
    ...
}
// Ok letters contains the line...
Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252