如何扫描带有某人姓名的字符串并为其创建首字母缩写?



所以基本上我需要从用户(用户名(获取输入,然后迭代用户名并创建一个新的首字母字符串。然后我必须输出首字母。我对如何在 C 中执行此操作感到非常困惑。

要记住的一件事是我必须使用指针。我不能按照家庭作业说明中使用数组操作。我认为我走在正确的道路上,但我对如何将字符连接到字符串感到困惑。有人可以在这里帮助我吗?

这是到目前为止的代码:

#include <stdio.h>
#include <string.h>
int main() {
    char *name = malloc(100);
    char c[5];
    char *initials = c;
    printf("Enter your full name in the following format 'First Middle Last':n");
    fgets(name, 100, stdin);
    for(int i = 0; i < strlen(name); i++){
        if(name[i] == ' '){
            strcat(&name[i + 1], initials);
            printf("%s", initials);
        }
    }
}

谢谢!

示例输入:Charles Edwin Roberts

示例输出:C.E.R

我会手动扫描输入,当我找到一个单词的第一个字母并将其大写版本复制到首字母数组中,并带有以下点; 单词的后续字母将被忽略; 非字母将标记单词的结尾。

源代码 ( caps.c (

#include <ctype.h>
#include <stdio.h>
int main(void)
{
    char name[100];
    while (printf("Please enter the name (First Middle Last): ") > 0 &&
           fgets(name, sizeof(name), stdin) != 0)
    {
        char *s = name;
        int inword = 0;
        unsigned char c;
        char initials[20] = "";
        char *p = initials;
        char *e = initials + sizeof(initials) - 2;
        while ((c = (unsigned char)*s++) != '')
        {
            if (!isalpha(c))
                inword = 0;
            else if (inword == 0)
            {
                *p++ = toupper(c);
                *p++ = '.';
                inword = 1;
                if (p >= e)
                    break;
            }
        }
        if (p > initials)
            *(p - 1) = '';   /* Zap the final dot to meet the spec */
        printf("Initials: %sn", initials);
    }
    putchar('n');
    return 0;
}

我拒绝重复运行该程序,所以我添加了一个简单的循环。 由于printf()返回它打印的字符数,因此> 0测试是安全的。 如果您担心 I/O 包在从标准输入读取之前不会刷新标准输出,则可以在循环条件中添加&& fflush(stdout) == 0

示例运行

$ gcc -O3 -g -std=c11 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes 
>     -Wold-style-definition -Werror caps.c -o caps  
$ caps
Please enter the name (First Middle Last): Charles Edwin Roberts
Initials: C.E.R
Please enter the name (First Middle Last): john michael doe
Initials: J.M.D
Please enter the name (First Middle Last): john.m.doe   
Initials: J.M.D
Please enter the name (First Middle Last): the artist formerly known as "prince"
Initials: T.A.F.K.A.P
Please enter the name (First Middle Last): he who has far too many words in his name was here     
Initials: H.W.H.F.T.M.W.I.H
Please enter the name (First Middle Last):     antiquated    (old)     man!!!
Initials: A.O.M
Please enter the name (First Middle Last): ajaykumar
Initials: A
Please enter the name (First Middle Last):   @(#)$!!!
Initials: 
Please enter the name (First Middle Last): 
$

您可以采取多种方法。您可以使用 strtokstrsep 等函数标记输入,您可以使用 strchr 等函数找到每个空格,或者,对于像 names 这样的短输入,最有效的方法可能是简单地使用指针循环输入并找到您有一个' '后跟字母的所有实例。要在每个首字母之间放置一个'.',只需在添加第一个首字母后在每个后续首字母之前添加一个'.'

由于您知道您的首字母缩写将包含字符串的第一个字符,因此您可以将第一个字符作为首字母,然后循环访问输入的其余部分。通过查找后跟字母' ',可以避免名称的各个部分之间有多个空格的情况。(如果名称的各个部分可以tab分开,您也可以将其作为检查包括在内(。您还需要确定可以组成首字母的最大字符数。这只会阻止输入 18 个单词,从而生成 18 个字符的首字母集。

可以将最大数量作为参数传递,也可以使用全局常量或#define 。注意:在首字母之间添加'.'时,首字母缩写所需的空格将n(首字母缩写(+ n - 1('.' s(或简称2 * n - 1。添加 nul 终止字符,这相当于2 * n 个字符在缩写数组中的总存储空间。

一个简单的方法可能如下所示:

enum { MAXI = 7, MAXC = 128 };   /* constants for max initials and chars */
...
char *initials (char *intls, char *s)
{
    int n = 0;
    if (!intls || !s)
        return NULL;
    if (isalpha(*s))
        intls[n++] = toupper(*s);              /* add first initial */
    for (; n < MAXI && *s && *(s + 1); s++)
        if (*s == ' ' && isalpha(*(s + 1))) {
            intls[n++] = '.';                  /* add . separator before */
            intls[n++] = toupper (*(s + 1));   /* each remaining initial */
        }
    return intls;
}

您可以通过多种方式使用它。通过将常量限制设置为 2 * n - 1(例如,由 enum { MAXI = 7... 创建的常量(来限制接受4的首字母数量的一个简单示例是:

#include <stdio.h>
#include <string.h>
#include <ctype.h>
enum { MAXI = 7, MAXC = 128 };   /* constants for max initials and chars */
char *initials (char *intls, char *s);
int main (void) {
    char intls[MAXI + 1] = {0};
    char name[MAXC] = {0};
    size_t len = 0;
    printf("Enter your full name ('First Middle Last'): ");
    if (!fgets (name, MAXC, stdin)) {
        fprintf (stderr, "error: invalid namen");
        return 1;
    }
    len = strlen (name);    /* get length and validate min   */
    if (len > 1)            /* of 2 chars to acount for 'n' */
        name[len - 1] = 0;  /* remove 'n' */
    else {
        fprintf (stderr, "error: empty string for name.n");
        return 1;
    }
    if (!initials (intls, name)) return 1;
    printf ("n name     : %sn initials : %snn", name, intls);
    return 0;
}
char *initials (char *intls, char *s)
{
    int n = 0;
    if (!intls || !s)
        return NULL;
    if (isalpha(*s))
        intls[n++] = toupper(*s);
    for (; n < MAXI && *s && *(s + 1); s++)
        if (*s == ' ' && isalpha(*(s + 1))) {
            intls[n++] = '.';
            intls[n++] = toupper (*(s + 1));
        }
    return intls;
}

示例输出

$ ./bin/initials
Enter your full name ('First Middle Last'): john joe lee
 name     : john joe lee
 initials : J.J.L
$ ./bin/initials
Enter your full name ('First Middle Last'): j
 name     : j
 initials : J
$ ./bin/initials
Enter your full name ('First Middle Last'): john joe lee frank marvin
 name     : john joe lee frank marvin
 initials : J.J.L.F
$ ./bin/initials
Enter your full name ('First Middle Last'): john    joe    lee    bin     foo
 name     : john    joe    lee    bin     foo
 initials : J.J.L.B

没有绝对正确的方法可以做到这一点。您可以根据需要使其健壮或简单,只要它提供正确的首字母并避免超出数组边界的读取/写入等错误。

根据strcat()的定义

char *strcat(char *dest, const char *src)

所以你的这行,

strcat(&name[i + 1], initials);

实际上是将initial[]数组的未初始化内容复制到name[i+1]中。我敢肯定这不是你想要的。

最新更新