0

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

这些/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);
4

1 回答 1

0

您使用strtok_rstrtok拆分名称的方法不起作用。

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

name="Konstantina Pavlova Rusenkova"

你得到这个名字name = strtok(NULL, ":,");。因此它不能包含任何','. 如果有的话',',绳子就会在那里被砍断。

','除了返回完整的字符串本身之外,任何使用分隔符的进一步标记化都无法获得任何有用的结果。

这意味着在您的内部循环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和朋友分开名字是没有用的。如果将字符串分开,则不会将两个名称放在一起。空格替换为\0.

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

    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]
于 2019-10-17T17:37:02.950 回答