0
\$\begingroup\$

This is a question from a CS diploma question set :

Make a program that will create an abbreviation of any given name using the initials. For example if the name if "John Doe", the program will output "J.D".

My Code:

#include <stdlib.h>
#include <string.h>
#include <stdio.h>

char *abbr (const char *s) {

    int keywords = 1;
    for (int i = 0; s[i]; i++)
        if (s[i] == ' ') keywords++;

    char *ret = (char *)malloc(2*keywords);
    if (!ret) {
        perror("malloc");
        exit (EXIT_FAILURE);
    }

    char *str = strdup(s);
    int i = 0;
    for (char *tok=strtok(str, " "); tok; tok=strtok(NULL, " "))
    {
        ret [i++] = *tok;
        ret [i++] = '.';
    }
    ret [--i] = 0;
    free(str);
    return ret;
}

int main (void) {
    char name[] = "John Doe";
    char *s = abbr(name);
    puts (s);
    free(s);
    return 0;
}

With respect to the question, is this a good enough solution? Is there a better way to achieve the same thing?

Thank you.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ Is that a direct quote of the problem statement? In particular, is only one . required for that example input, that we'd normally write in English as J.D.? \$\endgroup\$ Commented Apr 4, 2021 at 13:51

2 Answers 2

2
\$\begingroup\$
char *abbr (const char *s) {

Good - appropriate use of const here.

char *ret = (char *)malloc(2*keywords);

The cast is unnecessary, as malloc() returns a void* - which can be assigned to any pointer type in C (unlike C++). See Do I cast the result of malloc()?

if (!ret) {

Again, good - avoid dereferencing a null pointer. I would take a different action if the allocation fails - just return a null pointer to the caller, who is in a better position to decide whether to abort the whole program, and whether to write an error message to stderr.

char *str = strdup(s);

strdup() allocates memory, so this must be checked for a null return just like malloc(). There's an additional complication here that if we return from this point, we'll need to free ret before doing so. Personally, I'd remove the use of strtok() so that we don't need to copy the input here. strtok() has a terrible interface, and I consider it a misfeature of the C library.

char name[] = "John Doe";
char *s = abbr(name);

The requirement is for a program to create an abbreviation of any given name. This is a program that creates an abbreviation of one hard-coded name. I don't think it's really in the spirit of the requirements to have a program that needs to be edited and recompiled to be given a different name. All the user to provide the name as program arguments, or on the standard input stream.

\$\endgroup\$
0
\$\begingroup\$

I would rather start with a very simple approach. Why not just print out the capital letters?

#include <stdio.h>

int main(void) {
    char *namestr = "Hi my Four Names";

    char *pos = namestr;
    char c = ' ';
    while (c) {
        c = *pos++;
        if (c >= 'A' && c <= 'Z') {
            putchar(c);
            putchar('.');
        }
    }
    putchar('\n');
}

output : H.F.N.

Followed by a discussion about human names and strings in C. This is something that has to be defined in a question. Names can be very complicated, not only in exotic languages (McEnroe, van Gogh, Jean-Marie). And the rules for the initials are based on that.

You should at least describe your approach. And not silently complicate a simple task (simple, but unclear).

Create a new string (with malloc)? Or just output the initials "J.D." if the string is "John Doe"? Do a sanity check on the name?

good enough?

Yes that is the problem: it is too good in some ways.

Can you tell me what kind of CS diploma that is? Is there a context? How is the code entered and evaluated?

achieve the same thing

What exactly? How did you interpret this unclear task?

if the name if

Are you citing or paraphrasing?

\$\endgroup\$
1
  • 1
    \$\begingroup\$ c >= 'A' && c <= 'Z' is less portable than isupper((unsigned char)c). \$\endgroup\$ Commented Apr 4, 2021 at 13:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.