ページ 11

ある文字,または文字列まで読み込む方法

Posted: 2012年1月17日(火) 01:45
by ファイブマン
ある文字,または文字列まで読み込む方法がわかりません.下のテキストファイルの内容から,To: 以下の2つのメールアドレスを読みとり,後の処理に使えるようにそれぞれを
char *pt1, *pt2;
に格納したいと考えています.
このプログラムはコマンドラインの引数1にテキストファイルの名前を入力してその中身を呼び出すのですが,
(例:%
./program "text.txt"

pt1に1個目のアドレスのみを格納する方法がわかりません.
私の考えとしては
pt1 = rindex(pt1, ':');以降,
文字','までを読み込んでその値をまた新たなpt1として1個目のアドレスを格納したいのですがどうすればいいのでしょうか.
回答宜しくお願いします.

コード:

fp=fopen(argv[1], "r");
 while ((fgets(buf,  MAX_LEN - 1, fp)) != NULL) {
   buf[strlen(buf) - 1] = '\0';     /* 余分な改行コードを削除 */
   pt1 = strstr(buf,"To:");
   pt2 = strstr(buf,",");
   if(pt1 != NULL && pt2 != NULL)
     break;	
   
 }
 
 pt1 = rindex(pt1, ':');//このままだと,pt1はmail2.co.jp, tegami.mail.comと出力される

 pt2 = index(pt2, ',');//これは,pt2が tegami.mail.comと出力されるのでOK


テキストファイルの中身

コード:

Subject: uaoh
From: mail.co.jp
To: mail2co.jp,  tegami.mail.com
Date: Mon Jan 2012

ohre
また,アドレスは完全にテキトーです.

Re: ある文字,または文字列まで読み込む方法

Posted: 2012年1月17日(火) 01:54
by 沖 滉均
文字列をトークンで区切るstrtokという関数がありますのでそれを使用してみては如何でしょうか?
strtokで検索すれば例が幾つか引っかかると思いますので見てみてください。

Re: ある文字,または文字列まで読み込む方法

Posted: 2012年1月18日(水) 14:50
by ファイブマン
沖 滉均 さんが書きました:文字列をトークンで区切るstrtokという関数がありますのでそれを使用してみては如何でしょうか?
strtokで検索すれば例が幾つか引っかかると思いますので見てみてください。
回答ありがとうございます.
strtokを使ってみたのですが,どういうわけか,思ったようにいきません.
strtok(pt1, ', ');//カンマまたはスペースで区切る
としたのですが,printfした結果,
tegami.mail.com
のみしか出力されません.
私は
printf("%s\n", pt1);
において,
mail2co.jp,
tegami.mail.com
出力したいのですがこうなってしまう理由は何なのでしょうか.
また, pt_to = index(pt_to, ' ');
の行において,コンパイルの結果,
警告: 代入により、キャストなしで整数からポインタを作りました
と出たのも,警告を回避する方法がわかりません.
これらのこと,回答宜しくお願いします.

コード:

 fp=fopen(argv[1], "r");
 while ((fgets(buf, MAX_LEN - 1, fp)) != NULL) {
   buf_4[strlen(buf) - 1] = '\0';     /* 余分な改行コードを削除 */
   pt_to = strstr(buf,"To:");
   pt_to2 = strstr(buf,",");
   if(pt_to != NULL && pt_to2 != NULL)
     break;	
   
 }
 
 pt_to = index(pt_to, ' ');
 printf("%s\n", pt_to); //ここではindex()での結果を出力
pt_to = strtok( pt_to, " " );
 while ( pt_to != NULL ) {
   pt_to = strtok( NULL," " );
   if ( pt_to != NULL ) 
printf("%s\n", pt_to); //ここで各アドレスを1行毎に出力したい
 }


Re: ある文字,または文字列まで読み込む方法

Posted: 2012年1月18日(水) 16:29
by 沖 滉均
部分コードだったり変数名が以前から変わっていたり、意味のある変数名でもなさそうでわかりにくいですね。
まぁ、それは置いておいて11行目のindex関数はなんのために使用しているのでしょうか?
こちらにUNIX環境がないためindex関数の動作は確認できませんが不要だと思います。

11~12行目をコメントアウトし、実行したところ下記のように出力されますが期待通りでは無いということでしょうか?

コード:

mail2co.jp
tegami.mail.com
ちょっとindex関数の動作忘れましたが、最初の空白文字まで読み飛ばしているのだとしたら
ファイブマンさんのコードだと後半のtegami.mail.comしか表示されないという動作はコードに書かれたとおりの動作です。

1回目

コード:

To: mail2co.jp,  tegami.mail.com
   ^この位置が区切り文字(空白)だから'\0'にして先頭を返す
2回目

コード:

mail2co.jp,  tegami.mail.com
          ^この位置が区切り文字(カンマ)だから'\0'にして先頭を返す
3回目

コード:

tegami.mail.com
               ^終端を見つけたので先頭を返す
4回目

コード:

分解するトークンが無いのでNULLを返す
というような動きになっているはずです。
デバッガなど使えるのでしたら、ステップ実行して確認するか
strtok関数の直後にそれぞれprintfを入れて確認してみてください。

Re: ある文字,または文字列まで読み込む方法

Posted: 2012年1月18日(水) 23:30
by かずま
"To:" を見つけて、strtok で切り出すだけですよね。

コード:

#include <stdio.h>
#include <string.h>
 
int main(void)
{
    char buf[1024], *p, *pt[100];  int i, n = 0;

    while (fgets(buf, sizeof buf, stdin) && !(p = strstr(buf, "To:"))) ;
    for (p = strtok(p + 3, ", \n"); p && n < 100; p = strtok(NULL, ", \n"))
        pt[n++] = p;
    for (i = 0; i < n; i++) puts(pt[i]);
    return 0;
}

Re: ある文字,または文字列まで読み込む方法

Posted: 2012年1月19日(木) 00:35
by かずま
かずま さんが書きました:"To:" を見つけて、strtok で切り出すだけですよね。
"To:" がない場合に備えるなら、 p = NULL の初期化と、for 文の前に if (p) が必要です。