プログラムのアルゴリズムとIPアドレス抽出手順

このQ&Aのポイント
  • ファイルlog.txtの文章中からIPアドレスを抜き出し、ip.txtに書き込むプログラムのアルゴリズムと手順を教えてください。
  • 具体的に、どのようにIPアドレスを検出しているのでしょうか。
  • プログラムの要点や処理の流れなどについても教えていただけると嬉しいです。
回答を見る
  • ベストアンサー

このプログラムのアルゴリズムを教えていただけませんか?

ファイルlog.txtの文章中からIPアドレスを抜き出し、ip.txtに書き込むというプログラムです。文章は 日付 http attempt from xxxx.xxxx.xxxx.xxxx:ポート番号とう具合に並んでいます。 /* ・・・ from IP:portなフォーマットが前提*/ より下でIPを検出しているとおもうのですが、具体的にどういう手順で検出しているのかわかりません。 どうか宜しくお願いします。 #include <stdio.h> #include <string.h> void addLine(const char*,FILE*); char* getFromIP(const char*,char*); int main() { FILE* pFileA = fopen("log.txt","rt"); char buff[256]; if(pFileA){ FILE* pFileB = fopen("ip.txt","wt"); if(pFileB){ for(;fgets(buff,256,pFileA) != NULL;){ char buff2[32] = {'\0'}; addLine(getFromIP(buff,buff2),pFileB); } fclose(pFileB); } fclose(pFileA); } return 0; } /* ・・・ from IP:portなフォーマットが前提*/ char* getFromIP(const char* line,char* buff){ const size_t length = strlen(line); size_t top,back = length-1,i,k; for(back = length-1;line[back] != ':';--back); for(i=0,top = back - 1;i<3;++i){ for(;line[top] != '.';--top); } for(;line[top-1] != ' ';--top); for(i=top,k=0;i<back;buff[k++] = line[i++]); return buff; } void addLine(const char* str,FILE* pFile){ char buff[1024]; sprintf(buff,"%s\n",str); fputs(buff,pFile); }

質問者が選んだベストアンサー

  • ベストアンサー
  • rentahero
  • ベストアンサー率53% (182/342)
回答No.1

あらまあ、わざとややこしく書いてるプログラムみたいですねえ。 じゃあもうちょっとわかりやすく書き直してみますか? char *getFromIP(const char *line, char *buff) {  char *src, *dst;       // 作業用ポインタ  src = strstr(line, "from"); // fromを見つける  src += 4;          // fromの文字の分進める  dst = buff;         // 作業用ポインタ while(1)  {   if(isspace(*src))   {    src++;    continue;        // スペースを読み飛ばす   }   else break;        // スペース以外なのでループを抜ける  }                 // ここでsrcはIPアドレスの先頭を指している                 // 当然dstはbuffの先頭を指している                 // ここから文字列をコピーする  while(1)  {   *dst = *src;        // 文字をコピーする   if(*dst == ':')      // コロンだったら   {    *dst = '\0';       // コロンを終端文字に書き換えて    break;          // ループを抜ける   }   if(*dst == '\0')      // コロンが見つからないまま文字列が終わった場合   {    break;          // 仕方がないのでループを抜ける   }   dst++;           // ポインタを進める   src++;           // ポインタを進める  }  return buff;         // 戻り値は渡されたbuffのポインタ } ということですね。 え、これじゃダメ? じゃ、コメントつけてみましょか? char* getFromIP(const char* line,char* buff){ const size_t length = strlen(line); // 文字列の長さを求めておく size_t top,back = length-1,i,k;   // 変数定義 for(back = length-1;line[back] != ':';--back);                    // 文字列の最後から':'(コロン)を探す。 for(i=0,top = back - 1;i<3;++i){   // 見つけたコロンの位置から3回ループ                    //(コロンの1文字手前の位置をtopにセットしておく) for(;line[top] != '.';--top);    // ピリオドを見つけるまで一文字ずつ戻っていく。 } for(;line[top-1] != ' ';--top);   // 3個目のピリオドの前の位置からさらにスペースを探して                    // 1文字ずつ戻っていく。                    //(ということは、さっきの                    // ピリオド探してたのは                    // どういう意味があるのだろう)                    // ともかく、この時点でやっと                    // IPアドレスの先頭位置をみつけた。                    // ここから文字列をコピー               for(i=top,k=0;i<back;buff[k++] = line[i++]);                    // さっき見つけたコロンの                    // 位置までbuffに文字をコピーする…                    // あれ?終端文字をセットしてないよ! return buff;                    // おわりかよ! } このソースのキモは、 forの構文の使い方です。 for(A;B;C);はA;while(B){C;]と同じですが、読みづらくなります。はっきり言って、わざとやってるとしか思えません。そうでなければforがよっぽど好きなんでしょうね。 すべての一行forをwhileを使って書き直して、適切にインデントをつけるだけで、ずっと見通しがよくなります。やってみてください。 あと、元のソースではbuff2[32]={'\0'}としてます。 これもわざとやってるんでしょうね。 char buff[32]; memset(buff, '\0', 32); と同じ効果が得られると思いますが、わかりにくいです。 でも、あらかじめ初期化しておかなくてもいいように、最後にちゃんと終端文字をつけてやるほうが安全ですね。

masarui
質問者

お礼

分かりやすい説明だけでなく新しいプログラムも教えていただき本当にありがとうございました。

関連するQ&A

  • 文章中から特定の文字列を抜き出すプログラムについて C言語

    log.txtの文章からIPを抜き出しip.txtに書き込むというものです。log.txtの文章は基本的にfrom IP:port の順です。しかし文章中にfromがないとip.txtで空欄になってしまいます。 例192.168.1.100  192.168.1.110 理想はfromがない行はなにも追加せず次に移りたいのですがどうすればいいでしょうか? 例192.168.1.120 192.168.1.130 192.168.1.140 void addLine(const char*,FILE*); char *getFromIP(const char*,char*); int main() { FILE *pFileA = fopen("log.txt","rt"); char buff[256]; if(pFileA){ FILE *pFileB = fopen("ip.txt","wt"); if(pFileB){ for(;fgets(buff,256,pFileA) != NULL;){ char buff2[32] = {'\0'}; addLine(getFromIP(buff,buff2),pFileB); } fclose(pFileB); } fclose(pFileA); } return 0; } char *getFromIP(const char *line, char *buff) {  char *src, *dst;        src = strstr(line, "from");  if(src==NULL) { return buff; }   src += 4;            dst = buff;          while(1) {   if(isspace(*src))  {    src++;    continue;          }   else break;         }                    while(1) {   *dst = *src;          if(*dst == ':')        {    *dst = '\0';          break;           }   if(*dst == '\0')       {   break;           }  dst++;            src++;           }  return buff;         } void addLine(const char *str,FILE *pFile){ char buff[1024]; sprintf(buff,"%s\n",str); fputs(buff,pFile); }

  • ファイルから読み取った「行の長さ」は・・?

    すみません。 while (fgets(buff, 256, pFile) != NULL) { ~~~ } として1行ずつファイルを読み込み、その中で1文字ずつ処理する為に 必要なforループのループ回数を得たいのですが・・ char buff[256]; // 先に確保した配列を、fgetsした後に int buff_length = sizeof(buff) /sizeof(buff[0]); // 長さを得ようとする こうすると確保したサイズ256が返ってきてしまい困っています。(当然かもですが・・ ファイルの1行の長さを毎回取得する方法は無いでしょうか?

  • 単語の出現頻度を調べるプログラム

     ファイルからデータを読み込んで、単語の出現頻度を調べるプログラムを作ろうと考えて、下記のようなプログラムを書いてみました。 #include <stdio.h> #include <string.h> main() { struct data {char word[128]; int freq;} word_data[128]; char words[128]; char term[128]; int i=0; int nw=0; int j; char buff[128]; FILE *fp_in=fopen("data.txt","r"); while(fgets(fp_in,128,buff)!=EOF){ char buff[128]; int k; for(k=0;k<=128;k++){ printf("%s",buff); if(('A'<=buff[k] && buff[k]<='Z')||('a'<=buff[k] && buff[k]<='z')) term[i++]=buff[k]; else if(i>0) term[i]='\0';} for(j=0;j<nw;j++){ if(strcmp(term,word_data[j].word)==0) break; if(j==nw) {strcpy(word_data[j].word,term); word_data[j].freq=1; nw++;} else if(j!=nw) {word_data[j].freq++; i=0;} }} for(j=0;j<nw;j++) printf("%s %d",word_data[j].word,word_date[j].freq); return 0;} コンパイルは通ったのですが、実行しても画面に何も表示されません。原因は何処にあるのでしょうか?分かる方がいましたら、ご回答宜しくお願いします。

  • プログラムが動きません。

    プログラムが動きません。 ファイルuniqipにはIPアドレスが書き込まれています。そのファイルからIPアドレスを文字列ipに格納します。 ファイルtmp4には、85.114.143.2 34f4ff4acb18802170a939ae42dcd5ee0eeccda4 のようにIPアドレスとハッシュ値が書き込まれています。 tmp4に現れるIPアドレスで、uniqipに一致するものに対応するハッシュ値を printf("file%d,%s\n",i,hash); の形で出力しようと思いましたが、うまくいきません。 何がまずいのでしょうか? #include <stdio.h> #include <string.h> //ひとつのIPアドレスに現れるユニークなハッシュ値の数をカウントする int main() { FILE *fp,*gp; char ip[269730][16]; char ip2[16]; char hash[42]; int i,j; fp = fopen("uniqip","r"); if(fp == NULL){ printf("can not open the file.\n"); return 1; } for(i=0;i<267930;i++) { fscanf(fp,"%s",ip[i]); //printf("%s\n",ip[i]); } fclose(fp); ////////////////////////////////////////////////////////////////////////////////////////////////////// gp = fopen("tmp4","r"); if(gp == NULL){ printf("can not open the file.\n"); return 1; } for(i=0;i<267930;i++){ for(j=0;j<2470766;j++){ fscanf(gp,"%s %s",ip2,hash); printf("%s\n",ip[i]); if(!strcmp(ip[i],ip2)) { printf("file%d,%s\n",i,hash); } } } return 0; }

  • VC++2005 型変換

    テキストファイルを開いて、そのファイルの中身をfgetsで読みながらそれを何回か繰り返すというようなことをするというプログラムを書いてます。プログラムは下になります。 int m; FILE* pFile; char buffer[128]; pFile=fopen("p1.txt","r"); pFile=textBox1->Text; if (pFile==NULL) { label1->Text="ファイルがありません。\n"; } for(m=1; m<=8; m++) { fgets(buffer,128,pFile); String^ buffer; buffer=textBox2->Text; } } デバックを行うと次のエラーが出てしまいます。 error C2440: '=' : 'System::String ^' から 'FILE *' に変換できません。 どのように直せばよいのでしょうか?

  • 文字列について

    textファイルをいくつかに分割して保存しようと思い、以下のプログラムを作りましたが、うまくいきません。 予定では "0000.txt", "0001.txt", ....と文字列を生成するはずです。 #include <stdio.h> #include <string.h> #define LENGTH 4 //番号の桁数 void filename(int n) {    char name[LENGTH +4 +1];    char text[5] = ".txt";    int i;    for(i = 0; i <= LENGTH; i++)       name[i] = '0';    i = LENGTH;    //自然数を文字列に変換    do{       name[i] = (char)(n%10 + 48);       i--;       n /= 10;    }while(n != 0 && i >= 0);    strcat(name, text);    printf("filename:%s", name); } int main(void) {    int i;    for(i = 0; i < 5; i++){       filename(i);       printf("\n");    }    return 0; } 実行結果は filename:00000@.txt filename:00001.txt filename:00002.txt filename:00003.txt filename:00004.txt このように、文字化けしています。 何が原因なのでしょうか。 よろしくお願いします。

  • 昇順ソート

    sort.txtから読み込んだ値を 昇順でソートして出力するにはどうしたらよいでしょうか? #include <stdio.h> #include <stdlib.h> #include <string.h> #include <search.h> /* 比較関数 */ int strcmp_asc(const void *, const void *); int main(void) { FILE *fin, *fout; int i; int length; char s[256], s2[256]; if( (fin=fopen("sort.txt","r"))==NULL) { printf("入力ファイルがオープンできません\n"); exit(EXIT_FAILURE); } if( (fout=fopen("file2.txt","w"))==NULL) { printf("出力ファイルがオープンできません\n"); exit(EXIT_FAILURE); } while(fgets(s, 256, fin) != NULL) { /* 要素数を求める */ length = sizeof(s) / 256; /* 昇順でソート */ qsort(s, length, 256, strcmp_asc); /* memset(s2, NULL, sizeof(s2)); for (i = 0; i < length; i++) { } */ fprintf(fout,"%s\n",s2); } fclose(fin); fclose(fout); return 0; } int strcmp_asc(const void *sa, const void *sb) { return strcmp((char *)sa, (char *)sb); } sort.txt 50 45 35 25 15 10 5 1 32 46 8 7 9 19 18 14 16 13 12 17 11 20 40 30 31 3 2 37 38 36 33 39 34 49 47 48 4 6 44 42 43 41 21 22 26 24 28 29 27 23

  • mallocがうまく動かない

    コマンドライン引数で指定された文字列を逆順に返すプログラムを作るため 下記のようなプログラムを組みました。 ところが変数strの大きさがargv[1]より大きくなってしまいます。 どうすればよいのでしょうか。 #include <stdio.h> #include <stdlib.h> char *mstrrev (char *s); int main(int argc, char *argv[]){ char *str; str = mstrrev(*(argv+1)); printf("%s",str); free(str); } char *mstrrev (char *s){ int length,i; char *str; for(length=0;*(s+length)!='\0';length++); str = (char *)malloc(sizeof(char)*length); for(i=0;i<length;i++){ str[i] = s[length-1-i]; } return str; }

  • ポインタ

    String String Mid(int start, int length) const { char *p="HelloWorld"; char s[100]; p+=start; for(int i=0;i<length;i++) { *s++=*p+;; } return s3; で++には左辺値が必要ですとでます。 stringクラスのMid関数を実装しているのですが start分ポインタを進めてlength取り出す関数なんですが ここまでは組んだのですが、うまくいきません。 どうすればうまくいきますか?

  • string から unsigned char へ

    unsigned char* uchar_string(string* str) { int length = str->length(); const char* cchar = str->c_str(); unsigned char* uchar = new unsigned char[length+1]; for(int i=0; i=length; i++) { uchar[i] = (unsigned char)cchar[i]; } return uchar; } int main() { string str; cin >> str; unsigned char* uc; uc = uchar_string(&str); cout << uc; delete uctest; return 0; } このようにしたところ、cout << uc; が出力されず入力待ちとなり正常に動きませんでした。 原因がわからないです。原因と解決方法のご教授願います。

専門家に質問してみよう