Reputation: 11
I need it to only print the first capital of each word The point of this is to make acronyms from sentences by calling the function above. EX.
input: Hello output: H.
input: MACinery Bean output: M.C.B. Desired output: M.B.
void CreateAcronym(char userPhrase[50], char userAcronym[50]){
int len, up, uptwo;
char upper[50];
int isupper();
len = strlen(userPhrase);
for (int i = 0; i < len; i++){
up = isupper(userPhrase[i]);
uptwo = isupper(userPhrase[i+1]);
if (up != 0 && uptwo == 0){
strcpy(&upper[i], &userPhrase[i]);
printf("%c.", upper[i]);
}
}
printf("\n");
Upvotes: 1
Views: 183
Reputation: 15642
int isupper();
This is a strange prototype for the <ctype.h>
function isupper
. I'm not really sure if it's well defined. There are two ways I know to get a correct prototype for this function:
#include <ctype.h>
, typically somewhere near the top of your file. This is the way we most often see.int isupper(int);
will also introduce the correct prototype.Nonetheless I have no doubt the default argument promotions that occur are causing the correct type to be passed, so even if the behaviour is undefined it's probably no trouble.
We need to talk some more about that int
argument, though, hence bringing it to your attention. We're expected to ensure that int
argument is either an unsigned char
value or EOF
, but the value you passed is instead a char
value that may be neither. When passing char
values to <ctype.h>
functions, we should (generally, but not always) cast the argument to unsigned char
like so:
up = isupper((unsigned char) userPhrase[i]);
As far as the rest of your code goes, I think perhaps you may need to think more about what your algorithm is meant to do. I'ma use a functional style, because I think it makes sense for the sake of explanation here. You should translate this to a procedural style for class. So for my example (which may not even compile 🤷♂️ but is there to help you think about your algorithm) you can expect my continuations to be facilitated by something like:
typedef int fun(), contin(char *, char const *, fun **);
It seems to me like you want to skip leading non-alphabet characters, extract the first alpha, then skip any alpha until you reach non-alpha again. For example, the first step:
int skip_nonalpha(char *dst, char const *src, fun **f) {
if (!*src) return *dst = 0;
if (!isalpha((unsigned char) *src)) return skip_nonalpha(dst, src + 1, f);
return ((contin *) *f)(dst, src, f + 1);
}
In the function above you can see the argument passed to isalpha
is explicitly converted to unsigned char
, as I mentioned earlier. Anyhow, the next step is to extract and convert to upper:
int extract_toupper(char *dst, char const *src, fun **f) {
*dst = toupper(*src);
return ((contin *) *f)(dst + 1, src + 1, f + 1);
}
We don't need the explicit conversion in the function above because we already know src
is alpha, which makes it a positive value (within the range of [0..UCHAR_MAX]). Next, skip the rest of the alpha characters:
int skip_alpha(char *dst, char const *src, fun **f) {
if (!*src) return *dst = 0;
if (isalpha((unsigned char) *src)) return skip_alpha(dst, src + 1, f);
return ((contin *) *f)(dst, src, f + 1);
}
Finally, wrapping it all up:
int make_acronym_tail(char *dst, char const *src, fun **f) {
return skip_nonalpha(dst, src,
(fun *[]){ (fun *) extract_alpha
, (fun *) skip_alpha
, (fun *) make_acronym_tail)
});
}
int make_acronym(char *dst, char const *src) { return make_acronym_tail(dst, src, NULL); }
Now assuming this compiles you should be able to use it like:
char phrase[] = "hello world", acronym[strlen(phrase) + 1];
make_acronym(acronym, phrase);
Upvotes: 0
Reputation: 781750
The first letter of each word is either the beginning of the string or the previous character being a space. So you must test for that in your condition, not compare the current character and the next character.
for (int i = 0; i < len; i++){
if ((i == 0 || userPhrase[i-1] == ' ') && isupper(userPhrase[i]) {
printf("%c.", userPhrase[i]);
}
}
Upvotes: 2