用 strtok_r 分隔名字和中间名以及姓氏

Separate first name with middle name and last name with strtok_r

所以我遇到了一些与我之前在 C 编程中的探索相关的问题。这次是关于如何使用 strtok_rstrtok 将名称与 /etc/passwd 文件分开。交易是我想将用户名分为两部分,第一部分是名字和中间名(假设他们有一个),第二部分是姓氏。但我找不到正确分隔名称的方法。我让它在第一部分使用他们的名字,但后来中间名附加到姓氏。

/etc/passwd 行如下所示:

s214907:x:1240:1251:Jonas Villa,,,:/home/s214907:/bin/bash
s212167:x:1297:1306:Konstantina Pavlova Rusenkova,,,:/home/s212167:/bin/bash

我得到的示例:

[Konstantina] [Pavlova Ruskenova] 

我希望它如何打印的示例:

[Konstantina Pavlova] [Ruskenova]

到目前为止,这是我的代码:

          char line[256], words[20];
          char *mname, *tmp, *uid, *sp, *lname, *uname, *name, *fname, *tmps;
          int bindex=0, index, cnt =0, count;
          char *rest = NULL;
          FILE*fp = fopen("/etc/passwd","r");
          size_t len = 0;
          char *next = NULL;
          while(fgets(line,256,fp)!=NULL)
          {
                  sp       = strtok(line, ":");
                  tmp      = strtok(NULL, ":");
                  uid      = strtok(NULL, ":");
                  tmp      = strtok(NULL, ":");
                  name     = strtok(NULL, ":,");




                  if(atoi(uid) > 999)
                  {
                          for(tmps = strtok_r(name, " ", &rest);
                                  tmps != NULL;
                                  tmps = strtok_r(NULL, ",", &rest)) {
                                  tmps = strtok(tmps, ",");
                                  printf("[%s]\n", tmps);
                          }
                  }
                  cnt++;
          }
          fclose(fp);

您使用 strtok_rstrtok 拆分名称的方法无效。

将(完整)名称标记化后,您会得到:

name="Konstantina Pavlova Rusenkova"

您通过 name = strtok(NULL, ":,"); 获得此名称。因此它不能包含任何 ','。如果有 ',' 字符串就会在那里被截断。

使用定界符 ',' 的任何进一步标记化无法获得任何有用的结果,除了 return 完整的字符串本身。

这意味着在你的内部循环中 tmps = strtok(tmps, ","); 不会做任何事情。

我添加了一些印刷品:

printf("name=%s\n",name);

    if(atoi(uid) > 999)
    {
        for(tmps = strtok_r(name, " ", &rest);
            tmps != NULL;
            tmps = strtok_r(NULL, ",", &rest))
        {
            printf("tmps:%s\n", tmps); 
            tmps = strtok(tmps, ",");
            printf("  [%s]\n", tmps);
        }
    }

结果是:

name=Konstantina Pavlova Rusenkova
tmps:Konstantina
  [Konstantina]
tmps:Pavlova Rusenkova
  [Pavlova Rusenkova]

第二个打印显示您输入 tmps=strtok(tmps,","); 的内容。如上所述,分隔符永远不会存在,将所有内容都留在第二个括号中。

一般来说,strtok and friends 对拆分名字没什么用。如果将字符串分开,则没有两个名字在一起。空格替换为 [=27=].

相反,您可以简单地搜索最后一个空格并在那里拆分:

    if(atoi(uid) > 999)
    {
        char *first = name;
        char *last = strrchr(name,' ');

        if (last != NULL)
        {
            *last = 0;
            last++;

            printf("[%s] [%s]\n", first, last);
        }
    }

这将得到

name=Konstantina Pavlova Rusenkova
[Konstantina Pavlova] [Rusenkova]

它仍然适用于只有 1 个名字的名字:

name=James Kirk
[James] [Kirk]

如果一共只有一个名字,你需要稍微调整一下。

注:

如果出于某种原因你坚持使用 strtok 来分割名称,你需要使用分隔符 ' ' 然后将第一个和第二个子字符串粘合在一起。

这看起来像这样:

    if(atoi(uid) > 999)
    {
        for(tmps = strtok_r(name, " ", &rest);
            tmps != NULL;
            tmps = strtok_r(NULL, " ", &rest))
            {
                printf("tmps:%s\n", tmps);
                printf("  [%s]\n", tmps);
        }
    }

有输出

name=Konstantina Pavlova Rusenkova
tmps:Konstantina
  [Konstantina]
tmps:Pavlova
  [Pavlova]
tmps:Rusenkova
  [Rusenkova]