strstr is the easy, obvious answer, though you probably want to lowercase your input string first to do a case-insensitive search.
You may also want to consider checking to see if a word matches one of those terms. Otherwise a word like "retired" would trigger a response. That is somewhat more difficult since you need to take word boundaries into account.
A reasonably straightforward way to accomplish this would be to tokenize on whitespace and iterate over those tokens. You'll also want to remove punctuation (from the beginning and end of each word) and lowercase each word.
#include <string.h>
#include <ctype.h>
#include <stdio.h>
int main(void) {
char input[1024] = "";
printf("How are you feeling right now? ");
if (!fgets(input, sizeof(input), stdin)) {
fprintf(stderr, "Oops. I didn't hear from you.\n");
return 1;
}
char *tok;
for (tok = strtok(input, " "); tok; tok = strtok(NULL, " ")) {
// Downcase token
for (char *ch = tok; *ch; ch++) {
*ch = tolower(*ch);
}
// Remove leading punctuation
for (char *ch = tok; *ch; ch++) {
if (isalpha(*ch) || isdigit(*ch)) {
tok = ch;
break;
}
}
// Remove trailing punctuation
for (char *ch = tok + strlen(tok) - 1; ch >= tok; ch--) {
if (isalpha(*ch) || isdigit(*ch)) {
ch[1] = '\0';
break;
}
}
if (strcmp(tok, "good") == 0) {
printf("I'm glad to hear that!\n");
break;
}
else if (strcmp(tok, "tired") == 0) {
printf("Take some rest!\n");
break;
}
}
/ tok will be NULL if we reached the end of the input
// without finding a match.
if (tok == NULL) {
printf("Thank you for sharing.\n");
}
}
Testing:
% ./a.out
How are you feeling right now? Hello! Good!
I'm glad to hear that!
For the sake of flexibility, we could take this and replace the hard-coded tests for "good" and "tired" with a lookup table. This readily allows us to add other tests without having to rewrite later code.
#include <string.h>
#include <ctype.h>
#include <stdio.h>
typedef struct Response {
char *word;
char *response;
} Response;
int main(void) {
Response responses[] = {
{"good", "I'm glad to hear that!"},
{"tired", "Take some rest!"}
};
size_t num_responses = sizeof(responses) / sizeof(responses[0]);
char input[1024] = "";
printf("How are you feeling right now? ");
if (!fgets(input, sizeof(input), stdin)) {
fprintf(stderr, "Oops. I didn't hear from you.\n");
return 1;
}
char *tok;
for (tok = strtok(input, " "); tok; tok = strtok(NULL, " ")) {
// Downcase token
for (char *ch = tok; *ch; ch++) {
*ch = tolower(*ch);
}
// Remove leading punctuation
for (char *ch = tok; *ch; ch++) {
if (isalpha(*ch) || isdigit(*ch)) {
tok = ch;
break;
}
}
// Remove trailing punctuation
for (char *ch = tok + strlen(tok) - 1; ch >= tok; ch--) {
if (isalpha(*ch) || isdigit(*ch)) {
ch[1] = '\0';
break;
}
}
size_t i;
for (i = 0; i < num_responses; i++) {
if (strcmp(tok, responses[i].word) == 0) {
printf("%s\n", responses[i].response);
break;
}
}
// Test to see if a match was found.
if (i < num_responses) {
break;
}
}
if (tok == NULL) {
printf("Thank you for sharing.\n");
}
}
A further refinement would be to break some of the logic cluttering your loop out into functions.
#include <string.h>
#include <ctype.h>
#include <stdio.h>
typedef struct Response {
char *word;
char *response;
} Response;
void downcase(char *str);
void strip_leading(char *str);
void strip_trailing(char *str);
char *lookup_response(char *word, Response *responses, size_t n);
int main(void) {
Response responses[] = {
{"good", "I'm glad to hear that!"},
{"tired", "Take some rest!"}
};
size_t num_responses = sizeof(responses) / sizeof(responses[0]);
char input[1024] = "";
printf("How are you feeling right now? ");
if (!fgets(input, sizeof(input), stdin)) {
fprintf(stderr, "Oops. I didn't hear from you.\n");
return 1;
}
char *tok;
for (tok = strtok(input, " "); tok; tok = strtok(NULL, " ")) {
downcase(tok);
strip_leading(tok);
strip_trailing(tok);
char *response = lookup_response(tok, responses, num_responses);
if (response) {
printf("%s\n", response);
break;
}
}
if (tok == NULL) {
printf("Thank you for sharing.\n");
}
}
void downcase(char *str) {
for (char *ch = str; *ch; ch++) {
*ch = tolower(*ch);
}
}
void strip_leading(char *str) {
for (char *ch = str; *ch; ch++) {
if (isalpha(*ch) || isdigit(*ch)) {
tok = ch;
break;
}
}
}
void strip_trailing(char *str) {
for (char *ch = str + strlen(str) - 1; ch >= str; ch--) {
if (isalpha(*ch) || isdigit(*ch)) {
ch[1] = '\0';
break;
}
}
}
char *lookup_response(char *word, Response *responses, size_t n) {
for (i = 0; i < n; i++) {
if (strcmp(word, responses[i].word) == 0) {
return responses[i].response;
}
}
return NULL;
}
You could also look at including a regular expression library, but that seems like overkill in this kind of case.
strstris the correct way, but what was your difficulty to use it?strstr. You want to checkstrstr(str, "good") != NULL. If that doesn't work it's probably becusescanf("%c")reads a single character, not a string. You probably want to usegetlinefor that.scanf("%c", str);will write no more than a single character intostr. After that,strmay not be null terminated, and any attempt to passstrto a function that expects a null terminated string results in undefined behavior.strstr(word, string)should bestrstr(string, word)