2012-04-11 13 views
0

私はCの新機能で、whoamiを実装しようとしています。私は次のコードを持っています:getlineとstrtokをループで一緒に使用する

#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で使用する前に、行をコピーする必要があるか、行の先頭アドレスをコピーする必要があるかわかりません。

+0

'atoi'や' strtol'を使って文字列をカスタム関数の代わりに整数に変換することができます。 –

答えて

1

strtokは恐ろしい機能です。私はどのドキュメントを読んでいるのかわかりませんが(もしあれば)、両方ともバッファを変更してバッファに内部ポインタを保持します。バッファを最初にに渡すだけで、与えられた行でそれを使用し、その後NULLを渡すことになるので、最初から再開するのではなく、中断していた場所を拾うことができます。それはバッファを踏んだ...)。

さらに、構文解析してstrtokから遠く離れた他の方法を見つけてください。

+1

私は多くの人々がこの正確なことを言うと聞いたことがありますが、なぜあなたはそれを "恐ろしい"にしているのか見当たりません。 Cのテキストをパースするのは非常に便利でクリーンな方法です。オリジナルの文字列を変更したくない場合は、文字列を複製して 'strtok'に渡します。さらに、 'strtok_r'は実際にはスレッドセーフなので、高性能なコードには最適です。 – Macslayer

0

strtok_rを使用する方が安全です。マルチスレッド環境ではより安全です。それはこのケースでは当てはまらないかもしれませんが、あなたが書くスニペットがマルチスレッドアプリケーションに終わるかもしれないと仮定するほうが良い場合もあります。以下は、strtok_rを使用するように修正されたOPコードです。

​​

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

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

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を渡す必要があります。彼のコメントを言い換え、次のように上記のコードを変更することができます。

関連する問題