Reputation: 1
I am trying to build a program that will search for anything the user inputs in a 2d array that I have built with a bunch of letters and numbers. The program needs to find the word, say the location of the word in index number form and somehow a way of telling how many times the word has appeared. I have found ways off doing this however they require me to use other libraries other than include and
include which I am not allowed to. I know that this is a very specific question but any help would be greatly appreciated. Thank you. There are a total of 117 characters and letters in the char meaningless if that helps at all.
`
void wordSearch()
{
int i;
char search[30];
char meaningless[5][30]=
printf("\"
printf("Please enter the word you would like to search for in the above text\n");
scanf("%s", &search);
for(i=0, i<117, i++)
{
}
}
`
Upvotes: 0
Views: 95
Reputation: 84652
You wordsearch is fairly straight forward. You want to write a useful function that can be reused to search for any word that is a substring of a larger string. What that means in your case is you want to write a function that will look for search
within each string (row) contained in meaningless
.
To begin, do NOT add a dangling '\n'
to the last row in meaningless
just to gain an extra newline when meaningless
is output. Handle your output spacing with your output function, either adding an additional '\n'
to your printf
format string or simply outputting a newline with putchar('\n');
Let's start with your main()
and how you will loop over each row in meaningless
, both for outputting it and for passing each line to the wordsearch
function. Let's start with your declaration of meaningless
. Avoid using Magic Numbers in your code. If you need a constant, #define
one, e.g.
#define MAXC 32 /* if you need a constant, #define one (or more) */
...
int main (void) {
char search[MAXC], /* array to hold search term */
meaningless[][MAXC] ={ "AMENFELANGUAGEFERVZ0PIBMOU", /* to search */
"ZBPOINTERSSKLM12PMNOCOT",
"YCPROGRAMMERWQKNULTHMD",
"UKUNIXFIMWXIZEQZINPUTEX",
"P0DSTRINGGDIWHIMERCERLS" };
int rows = sizeof meaningless / sizeof *meaningless; /* no. of rows */
...
The recommended way of handling a line of input is to read the input with fgets()
. That way you consume a line of input each time and what remains in stdin
doesn't depend on the format-string used. In your case, presumably you want to be able to enter multiple search terms each time your program runs. To do that you can simply loop continually, displaying your meaningless
block of characters and prompting for input from the user.
The nice thing about fgets()
is it will read the '\n'
created by the user pressing Enter which provides a simple way to end input -- just press Enter without any input and check to see if the 1st character in search
is '\n'
. If it is, break the loop. If it isn't, then you need to trim the '\n'
from the end of search which is easily done with strcspn()
, e.g.
/* prompt for search, read and VALIDATE input, comparse 1st char with '\n' */
fputs ("\nenter search term: ", stdout);
if (!fgets (search, MAXC, stdin) || *search == '\n')
break;
search[strcspn (search, "\n")] = 0; /* trim trailing '\n' from search */
(note: by checking !fgets(...)
you also handle the case where the user generates a manual EOF
by pressing Ctrl+d on Linux or Ctrl+z on windows)
You also want to know how many times search
was matched. So within your continual loop, simply declare an int
variable and initialize the value to zero (e.g. int matches = 0;
). Adding that, your complete main()
searching for search
withing meaningless
for as many terms as the user cares to search for until Enter alone is pressed (or a manual EOF
generated) could be:
int main (void) {
char search[MAXC], /* array to hold search term */
meaningless[][MAXC] ={ "AMENFELANGUAGEFERVZ0PIBMOU", /* to search */
"ZBPOINTERSSKLM12PMNOCOT",
"YCPROGRAMMERWQKNULTHMD",
"UKUNIXFIMWXIZEQZINPUTEX",
"P0DSTRINGGDIWHIMERCERLS" };
int rows = sizeof meaningless / sizeof *meaningless; /* no. of rows */
for (;;) { /* loop continually until no search term provided */
int matches = 0; /* no. of matches of search found */
putchar ('\n'); /* provide newline */
for (int i = 0; i < rows; i++) /* loop over each meaningless row */
printf ("%s\n", meaningless[i]); /* output */
/* prompt for search, read and VALIDATE input, comparse 1st char with '\n' */
fputs ("\nenter search term: ", stdout);
if (!fgets (search, MAXC, stdin) || *search == '\n')
break;
search[strcspn (search, "\n")] = 0; /* trim trailing '\n' from search */
for (int i = 0; i < rows; i++) /* loop over each meaningless row */
matches += wordsearch (meaningless[i], search); /* check for matches */
printf ("\n\"%s\" found %d times.\n", search, matches); /* output results */
}
}
Your wordsearch()
function is straight forward. You will pass the string to look through (haystack
) and the term to find (needle
) and then see if you can find the needle in the haystack. The approach is to declare a pointer to the first char in the haystack, and then use strchr
to find if and where the first character of needle
occurs in the haystack
. If it is found, then you just check the next needle
length worth of characters to see if they match needle
using strncmp()
and then advance the pointer to the next char and repeat.
The only caveat is you want to stop searching if you are less than the length of needle
chars away from the end of haystack
(obviously you can't match in less than needle
no. of characters) -- and more importantly, you prevent reading beyond the end of your string invoking Undefined Behavior...
With that said, your wordsearch()
could put those pieces together as follows, returning the number of times needle
is found in haystack
, e.g.
/* seach haystack for needle, return no. of times needle occurs */
int wordsearch (const char *haystack, const char *needle)
{
const char *p = haystack; /* string to search within */
int found = 0; /* no. of matches found */
size_t hlen = strlen (haystack), /* lenght of string to search within */
nlen = strlen (needle); /* length of seach string */
/* loop while pointer more than nlen chars from end and 1st char in needle found */
while ((size_t)(p - haystack) < (hlen - nlen) && (p = strchr (p, *needle))) {
if (strncmp (p, needle, nlen) == 0) /* if next nlen chars match needle */
found += 1; /* increment found by 1 */
p += 1; /* increment point to next char */
}
return found; /* return no. of needles in haystack */
}
Adding the required headers and a complete example could be:
#include <stdio.h>
#include <string.h>
#define MAXC 32 /* if you need a constant, #define one (or more) */
/* seach haystack for needle, return no. of times needle occurs */
int wordsearch (const char *haystack, const char *needle)
{
const char *p = haystack; /* string to search within */
int found = 0; /* no. of matches found */
size_t hlen = strlen (haystack), /* lenght of string to search within */
nlen = strlen (needle); /* length of seach string */
/* loop while pointer more than nlen chars from end and 1st char in needle found */
while ((size_t)(p - haystack) < (hlen - nlen) && (p = strchr (p, *needle))) {
if (strncmp (p, needle, nlen) == 0) /* if next nlen chars match needle */
found += 1; /* increment found by 1 */
p += 1; /* increment point to next char */
}
return found; /* return no. of needles in haystack */
}
int main (void) {
char search[MAXC], /* array to hold search term */
meaningless[][MAXC] ={ "AMENFELANGUAGEFERVZ0PIBMOU", /* to search */
"ZBPOINTERSSKLM12PMNOCOT",
"YCPROGRAMMERWQKNULTHMD",
"UKUNIXFIMWXIZEQZINPUTEX",
"P0DSTRINGGDIWHIMERCERLS" };
int rows = sizeof meaningless / sizeof *meaningless; /* no. of rows */
for (;;) { /* loop continually until no search term provided */
int matches = 0; /* no. of matches of search found */
putchar ('\n'); /* provide newline */
for (int i = 0; i < rows; i++) /* loop over each meaningless row */
printf ("%s\n", meaningless[i]); /* output */
/* prompt for search, read and VALIDATE input, comparse 1st char with '\n' */
fputs ("\nenter search term: ", stdout);
if (!fgets (search, MAXC, stdin) || *search == '\n')
break;
search[strcspn (search, "\n")] = 0; /* trim trailing '\n' from search */
for (int i = 0; i < rows; i++) /* loop over each meaningless row */
matches += wordsearch (meaningless[i], search); /* check for matches */
printf ("\n\"%s\" found %d times.\n", search, matches); /* output results */
}
}
Example Use/Output
$ ./bin/wordsearch
AMENFELANGUAGEFERVZ0PIBMOU
ZBPOINTERSSKLM12PMNOCOT
YCPROGRAMMERWQKNULTHMD
UKUNIXFIMWXIZEQZINPUTEX
P0DSTRINGGDIWHIMERCERLS
enter search term: foo
"foo" found 0 times.
AMENFELANGUAGEFERVZ0PIBMOU
ZBPOINTERSSKLM12PMNOCOT
YCPROGRAMMERWQKNULTHMD
UKUNIXFIMWXIZEQZINPUTEX
P0DSTRINGGDIWHIMERCERLS
enter search term: STRING
"STRING" found 1 times.
AMENFELANGUAGEFERVZ0PIBMOU
ZBPOINTERSSKLM12PMNOCOT
YCPROGRAMMERWQKNULTHMD
UKUNIXFIMWXIZEQZINPUTEX
P0DSTRINGGDIWHIMERCERLS
enter search term: POINTER
"POINTER" found 1 times.
AMENFELANGUAGEFERVZ0PIBMOU
ZBPOINTERSSKLM12PMNOCOT
YCPROGRAMMERWQKNULTHMD
UKUNIXFIMWXIZEQZINPUTEX
P0DSTRINGGDIWHIMERCERLS
enter search term: WHIMERCERLS
"WHIMERCERLS" found 1 times.
AMENFELANGUAGEFERVZ0PIBMOU
ZBPOINTERSSKLM12PMNOCOT
YCPROGRAMMERWQKNULTHMD
UKUNIXFIMWXIZEQZINPUTEX
P0DSTRINGGDIWHIMERCERLS
enter search term: BYE
"BYE" found 0 times.
AMENFELANGUAGEFERVZ0PIBMOU
ZBPOINTERSSKLM12PMNOCOT
YCPROGRAMMERWQKNULTHMD
UKUNIXFIMWXIZEQZINPUTEX
P0DSTRINGGDIWHIMERCERLS
enter search term:
Digest the code one line-at-a-time. Read the man page for each unfamiliar function and learn how it is used, the type of parameters it takes and the type and value it returns (both on success and on failure). Let me know if you have further questions.
Per the Comment, strstr()
effectively combines both strchr()
and strncmp()
for you. It does everything done manually in wordsearch()
in a single function call, but hides most of the details from you. You can loop finding each occurrence of search
in meaningless
reducing your wordsearch()
to:
/* seach haystack for needle, return no. of times needle occurs */
int wordsearch (const char *haystack, const char *needle)
{
const char *p = haystack; /* string to search within */
int found = 0; /* no. of matches found */
/* loop while pointer more than nlen chars from end and 1st char in needle found */
while ((p = strstr (p, needle))) { /* loop finding each needle in haystack */
found += 1; /* increment found by 1 */
p += 1; /* increment point to next char */
}
return found; /* return no. of needles in haystack */
}
There are many ways to write the function.
Upvotes: 1