在C

时间:2018-11-29 13:30:57

标签: c

所以我正在做一个小项目,而我想获取模拟数据并将其分离为结构。但是我想到的是具有多个姓氏和/或姓氏的人的问题。

我想像您一样写名字(例如“ Michael ”),并用所有大写字母写姓(例如“ JAMESON ”)。

但是,如果我读到 Michael Daniel VAN DOORNE 之类的名字怎么办?我不知道如何分隔“ Michael Daniel ” “”作为名字,“ VAN DOORNE ”作为姓氏。我试图通过以第一个大写字母开头来分隔,但我当然也将某人的名字中的第一个字母大写。

示例:

我想阅读 Michael Daniel VAN DOORNE ,并分别将其分为“ Michael Daniel ”和“ VAN DOORNE ”。姓

sscanf(buffer, "%s %s", firstName, lastName);

那自然不会起作用。但是我有点想提出一种解决方案,以解决具有多个名字和姓氏的模拟名字。

6 个答案:

答案 0 :(得分:5)

由于您似乎可以完全控制数据,因此我建议您使用另一种方法:

在姓氏和姓氏之间的特定分隔符。然后,您不再依赖于区分大小写,尤其是另一个答案中出现的单个字符名称问题不再是问题。

分隔符应该是一个永远不会出现的名称,例如制表符(与空格相反),#,'|',...,甚至逗号或分号也可以。 ,尽管句号可能以缩写名称出现,因此不应使用。

答案 1 :(得分:1)

因此,要知道它是名字的一部分还是姓氏是一个挑战,但是从声音的角度来看,您可以控制数据,因此可以小写名字并大写名字或使用其他方法。

分解字符串,使用strtok相对容易。

做出一些假设,即您正在逐行读取名称并将其填充到buffer中。

使用strtokbuffer分解为“名称”。

char *token
token = strtok(buffer, " "); //note the second parameter is what you want to parse the array by
while(token != NULL)
{
    if(isupper(token[0]))
        //store that token into your struct (first or last name) allow for multiple
    else
        //store into the other 

    token = strtok(NULL, " "); //keep looping on string for names
}

答案 2 :(得分:0)

strspnstrcspn可用于遍历字符串并找到第一个大写单词。

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

int main( void) {
    char line[] = "Michael Daniel VAN DOORNE";
    char upper[] = "ABCDEFGHIJKLMNOPQURSTUVWXYZ";
    int last = 0;
    int start = 0;
    int check = 0;
    do {
        last = start + check;
        check += start + 1;
        start = strspn ( line + check, upper);//span of characters that are uppercase
        if ( ' ' != line[start + check]) {//is the next character a space
            start = strcspn ( line + check, " ");//find the space
            if ( line[start + check]) {//not the terminatins zero
                start++;
            }
        }
    } while ( line[start + check] && ' ' != line[start + check]);

    printf ( "%s\n", &line[last]);

    return 0;
}

答案 3 :(得分:0)

假设姓氏始终用大写字母书写,请从末尾开始读取字符串,看看什么时候使用小写字母。

int i=strlen(buffer)-1;
while(!islower(buffer[i]) && i>0)
    i--;
strncpy(firstName,buffer,i+1);
strcpy(lastName,&buffer[i+2]);

答案 4 :(得分:0)

这是另一种解决方案。请阅读直到有两个大写字母或一个大写字母和一个空格为止。然后使用指针算法填充名字和姓氏。

char name[] = "Michael Daniel VAN DOORNE";

char *p = name;

char firstname[100] = { 0 };
char lastname[100] = { 0 };

while (*p)
{
    if (isupper(p[0]) && (isupper(p[1]) || p[1] == ' '))
    {
        strcpy(lastname, p);
        strncpy(firstname, name, p - name - 1);
        break;
    }
    p++;
}

答案 5 :(得分:0)

如果您使用的是ASCII,这是一个特定于字符集的技巧,可以帮助您:

#define TWOUPPER(c0, c1) (!((c0) & 32) && !((c1) & 32))

这对单个字符的姓氏也将起作用,因为空字符将不能通过第5位检查,并且由于以下空格将无法通过测试,因此单个字符的中间名将不会被用作姓氏。

通过比较字符串中的每两个字符并停止匹配,为我使用以下测试用例:

    char test1[100] = "Otto VON BISMARK",
    test2[100] = "Johannes Diderik VAN DER WAALS",
    test3[100] = "Vincent VAN GOGH",
    test4[100] = "Govind A B C D P"; // Only the "P" is counted as the last name here