Reputation: 3042
Write a program that takes nouns and forms their plurals on the basis of these rules: a. If noun ends in “y” remove the “y” and add “ies” b. If noun ends in “s” , “ch”, or “sh”, add “es” c. In all other cases, just add “s” Print each noun and its plural. Try the following data: chair
dairy boss circus fly dog church clue dish
This is what I've got so far but it just isn't quite functioning like it's supposed to:
#include<stdlib.h>
#include <Windows.h>
#include <stdio.h>
#include <string.h>
#define SIZE 8
char *replace_str(char *str, char *orig, char *rep)
{
static char buffer[4096];
char *p;
if(!(p = strstr(str, orig)))
return str;
strncpy(buffer, str, p-str);
buffer[p-str] = '\0';
sprintf(buffer+(p-str), "%s%s", rep, p+strlen(orig));
return buffer;
}
int main(void)
{
char plural[SIZE];
printf("Enter a noun: ");
scanf("%c",&plural);
bool noreplace = false;
puts(replace_str(plural, "s","es"));
puts(replace_str(plural, "sh","es"));
puts(replace_str(plural, "ch","es"));
puts(replace_str(plural, "y", "ies"));
if(noreplace) {
puts(replace_str(plural, "","s"));
}
system("pause");
return 0;
}
I haven't taken a C class in a while can anyone help me out? Thanks.
Upvotes: 1
Views: 13541
Reputation: 881363
For a start, scanf("%c")
gets a single character, not a string. You should use fgets
for that, along the lines of:
fgets (buffer, SIZE, stdin);
// Remove newline if there.
size_t sz = strlen(buffer);
if (sz > 0 && buffer[sz-1] == '\n') buffer[sz-1] = '\0';
Once you've fixed that, we can turn to the function which pluralises the words along with a decent test harness. Make sure you keep your own main
(with a fixed input method) since there's a couple of things in this harness which will probably make your educator suspect it's not your code. I'm just including it for our testing purposes here.
Start with something like:
#include <stdio.h>
#include <string.h>
char *pluralise(char *str) {
static char buffer[4096];
strcpy (buffer, str);
return buffer;
}
int main(void) {
char *test[] = {
"chair", "dairy", "boss", "circus", "fly",
"dog", "church", "clue", "dish"
};
for (size_t i = 0; i < sizeof(test)/sizeof(*test); i++)
printf ("%-8s -> %s\n", test[i], pluralise(test[i]));
return 0;
}
This basically just gives you back exactly what you passed in but it's a good start:
chair -> chair
dairy -> dairy
boss -> boss
circus -> circus
fly -> fly
dog -> dog
church -> church
clue -> clue
dish -> dish
The next step is to understand how to detect a specific ending and how to copy and modify the string to suit. The string is an array of characters of the form:
0 1 2 3 4 5
+---+---+---+---+---+---+
| c | h | a | i | r | $ |
+---+---+---+---+---+---+
where $
represents the null terminator \0
. The numbers above give the offset from the start or the index that you can use to get a character from a particular position in that array. So str[3]
will give you i
.
Using that and the length of the string (strlen(str)
will give you 5), you can check specific characters. You can also copy the characters to your target buffer and use a similar method to modify the end.
Like any good drug pusher, I'm going to give you the first hit for free :-)
char *pluralise(char *str) {
static char buffer[4096]; // Risky, see below.
size_t sz = strlen(str); // Get length.
if (sz >= 1 && str[sz-1] == 'y') { // Ends with 'y'?
strcpy(buffer, str); // Yes, copy whole buffer,
strcpy(&(buffer[sz-1]), "ies"); // overwrite final bit,
return buffer; // and return it.
}
strcpy(buffer, str); // If no rules matched,
strcat(buffer, "s"); // just add "s",
return buffer; // and return it.
}
Of particular interest there is the sequence:
strcpy(buffer, str);
strcpy(&(buffer[sz-1]), "ies");
The first line makes an exact copy of the string like:
0 1 2 3 4 5
+---+---+---+---+---+---+
| d | a | i | r | y | $ |
+---+---+---+---+---+---+
The second line copies the "ies"
string into the memory location of buffer[sz-1]
. Since sz
is 5, that would be offset 4, resulting in the following change:
0 1 2 3 4 5
+---+---+---+---+---+---+
| d | a | i | r | y | $ |
+---+---+---+---+---+---+---+---+
| i | e | s | $ |
+---+---+---+---+
so that you end up with dairies
.
From that, you should be able to use the same methods to detect the other string endings, and do similar copy/modify operations to correctly pluralise the strings.
Keep in mind that this is basic code meant to illustrate the concept, not necessarily hardened code that I would use in a production environment. For example, the declaration static char buffer[4096]
has at least two problems that will occur under certain circumstances:
static
, the buffer will be shared amongst all threads calling this function if used in a multi-threaded environment. That's unlikely to end well as threads may corrupt the data of each other.A relatively easy fix would be for the caller to also provide a buffer for the result, at least long enough to handle the largest possible expansion of a word to its plural form. But I've left that as a separate exercise since it's not really relevant to the question.
(a) Such as Donaudampfschiffahrtselektrizitätenhauptbetriebswerkbauunterbeamtengesellschaft :-)
Upvotes: 4
Reputation: 455000
You are reading a word as:
scanf("%c",&plural);
which is incorrect as it only reads one character.
Change it to:
scanf("%s",plural);
or even better use fgets
as:
fgets (plural,SIZE, stdin);
But note that fgets
might add a newline at the end of the string. If it does you need to remove it before you do the replacement as your replacement depends on the last character in the word.
Also your replacement part is incorrect. You are replacing any s
with es
(same with other replacements). You need to replace only the last s
.
Upvotes: 2
Reputation: 4631
first of all u need to find last position of occurance and then call replace_str() function and secondly scanf("%s",&plural);or use fgets()
Upvotes: 0
Reputation: 104050
puts(replace_str(plural, "ch","es"));
Consider the input: church
strstr(3)
will find the first ch
, not the last ch
. Ooops.
Furthermore, once you modify replace_str()
to find the the last ch
, you're still ripping it off and not putting it back on: chures
. (Assuming your replace_str()
functions as I think it does; that's some hairy code. :) So add the ch
back on:
puts(replace_str(plural, "ch","ches"));
Upvotes: 0