0

そのため、以前の C プログラミングの探求に関連する問題がいくつかあります。今回はor/etc/passwdを使ってファイルと名前を分ける方法について。取り決めは、ユーザー名を 2 つの部分に分けたいということです。最初の名前とミドル ネーム (1 つを取得したと仮定) で、2 番目の名前で姓です。しかし、名前を正しく区切る方法が見つかりません。最初の部分ではファースト ネームで動作するようにしましたが、ラスト ネームにミドル ネームが付けられます。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_r名前を使用または分割するアプローチは機能しstrtokません。

(完全な) 名前をトークン化すると、次のようになります。

name="Konstantina Pavlova Rusenkova"

この名前は によって取得されname = strtok(NULL, ":,");ます。したがって、 を含むことはできません','。があった場合','、文字列はそこで切り刻まれていたでしょう。

完全な文字列自体を返すことを除いて、 delimiter を使用してさらにトークン化する','と、有用な結果は得られません。

これは、内側のループで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]

2 番目のプリントは、 に何をフィードするかを示していますtmps=strtok(tmps,",");。前述のように、デリミタは決して存在せず、すべてを 2 番目のブラケットに残します。

一般にstrtok、友人は名前を分割するのに役立ちません。2 つの名前が一緒にならないように文字列を切り離します。空白は に置き換えられ\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]

合計で名前が 1 つしかない場合は、少し調整する必要があります。

ノート:

何らかの理由strtokで名前の分割にも使用する必要がある場合は、区切り文字を使用してから' '、最初と 2 番目の部分文字列を接着する必要があります。

これは次のようになります。

    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 に答える