如何使用某人的姓名扫描字符串并为其创建首字母?

时间:2016-02-15 06:03:10

标签: c

所以基本上我需要从用户那里获得一个输入(用户的名字)然后迭代用户的名字并创建一个新的首字母串。然后我必须输出首字母。我对在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

3 个答案:

答案 0 :(得分:1)

我会手动扫描输入,当我找到一个单词的第一个字母并将其大写版本复制到首字母数组时会发现,后面有一个点;随后的一个字母将被忽略;非字母标志着一个单词的结尾。

源代码(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++) != '\0')
        {
            if (!isalpha(c))
                inword = 0;
            else if (inword == 0)
            {
                *p++ = toupper(c);
                *p++ = '.';
                inword = 1;
                if (p >= e)
                    break;
            }
        }
        if (p > initials)
            *(p - 1) = '\0';   /* Zap the final dot to meet the spec */

        printf("Initials: %s\n", 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): 
$

答案 1 :(得分:1)

您可以采取多种方法。您可以使用strtokstrsep等函数标记输入,您可以找到具有strchr等函数的每个空格,或者可能是最有效的短输入类似名称只是使用指针循环输入,并查找所有具有' '后跟字母的实例。要在每个首字母之间放置'.',只需在添加第一个首字母后的每个后续初始之前添加'.'

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

您可以将最大数字作为参数传递,也可以使用全局常量或#define。注意:在首字母之间添加'.'时,首字母缩写所需的空间将为n(缩写)+ n - 1'.' s)或仅2 * n - 1 。添加 nul-terminatedating 字符,相当于首字母数组中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;
}

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

#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 name\n");
        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     : %s\n initials : %s\n\n", 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

没有绝对的正确方法。只要它提供正确的首字母并避免读取/写入超出数组边界等错误,您就可以使它变得健壮或简单。

答案 2 :(得分:0)

根据strcat()

的定义
char *strcat(char *dest, const char *src)

所以你的这一行,

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

实际上是将initial[]数组的未初始化内容复制到name[i+1]。我相信那不是你想要的。