1

私はCが初めてで、自分への練習としてwhoamiを実装しようとしています。私は次のコードを持っています:

#define _POSIX_SOURCE
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h> // strtok

int str_to_int(const char *str)
{
    int acc = 0;
    int i;
    for (i = 0; str[i] != '\0'; ++i) {
        acc = (10 * acc) + (str[i] - 48); // 48 -> 0 in ascii
    }
    return acc;
}

int main()
{
    FILE *passwd;
    char *line = NULL;
    size_t line_size;

    passwd = fopen("/etc/passwd","r");

    uid_t uid = getuid();

    while (getline(&line, &line_size,passwd) != -1) {
        char *name = strtok(line,":");
        strtok(line,":"); // passwd
        char *user_id = strtok(line,":");
        if (str_to_int(user_id) == uid) {
            printf("%s\n",name);
            break;
        }
    }

    fclose(passwd);
    return 0;
}

while ループ内に行ポインタを保存する必要がありますか。strtok は何らかの形でそれを変更すると思うので、行をコピーする必要があるかどうか、または strtok で使用する前に行の開始アドレスをコピーする必要があるかどうかはわかりません。

4

3 に答える 3

1

strtok恐ろしい機能です。どのドキュメントを読んだかはわかりませんが(もしあれば?)、渡されたバッファを変更し、バッファへの内部ポインタを保持します。特定の行で初めてバッファを使用するときにのみバッファを渡す必要があり、NULLその後に渡す必要があります。これにより、最初からやり直すのではなく、中断した場所を取得することがわかります(踏みつけられたため、実際には正しく機能しません)。バッファー...)。

より良いのは、他の解析方法を見つけて から遠ざけることですstrtok

于 2012-04-11T19:44:45.110 に答える
0

を使用した方が安全かもしれませんstrtok_r。マルチスレッドの状況ではより安全です。この場合は当てはまらないかもしれませんが、作成したスニペットがある時点でマルチスレッド アプリになる可能性があると想定したほうがよい場合もあります。以下は、 を使用するように変更された OP コードstrtok_rです。

  char *pos;
  char *name = strtok_r(line,":",&pos);
  strtok_r(NULL,":",&pos); // passwd
  char *user_id = strtok_r(NULL,":",&pos);

そして、はい、strtok(およびstrtok_r) 指定された入力バッファー (最初のパラメーター) を変更します。しかし、適切に使用すれば安全です。指定された文字列内のバッファへのポインタを返すためstrtok、使用方法に注意する必要があります。あなたの場合、ループから抜け出し、バッファ内の値を指すようになりますnameuser_idline

また、 のマニュアル ページを読む必要があるかもしれませんgetline。あなたがそれを使用している方法は、あなたのアプリケーションが解放する責任がある割り当てられたバッファを返します。freeそれはあなたが目指しているものかもしれませんが、投稿されたコードにその呼び出しが表示されないため、言及します。

于 2012-04-11T20:12:50.550 に答える
0

私はgeekosaur(およびMark)に完全に同意します。彼のコメントを言い換えると、上記のコードを次のように変更できます。

while (getline(&line, &line_size, passwd) != -1) {
    char *name = strtok(line,":");
    strtok(NULL,":"); // passwd
    char *user_id = strtok(NULL,":");
    if (str_to_int(user_id) == uid) {
        printf("%s\n",name);
        break;
    }
}

strtok最初の呼び出し以外の呼び出しには NULL を渡す必要があります。

于 2014-11-30T21:38:09.900 に答える