thatboinick
thatboinick

Reputation: 11

Having a problem only printing the first capital letter in a string

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

Answers (2)

autistic
autistic

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:

  1. #include <ctype.h>, typically somewhere near the top of your file. This is the way we most often see.
  2. 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

Barmar
Barmar

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

Related Questions