C言語のタグの抽出について

このQ&Aのポイント
  • C言語を学習しているものです。main関数内で定義した<pro><name>chad smith</name><id>1234</id><live>America<live></pro>を抽出し表示するプログラムの作成を考えております。
  • 第一パラメータに抽出したいタグ名を書くと表示されるようにします。>>プログラム名 idで1234を、>>プログラム名 nameでchad smithを、>>プログラム名 proで<name>chad smith</name><id>1234</id><live>America<live>のような表示にされるようにします。
  • 上記のプログラムに対して自分なりにstrstr()とmemcpy()を使用してみましたがうまくいきませんでした。strstr()を用いますと文字列の最初から検索していきますが、第一パラメータでタグ名だけを宣言しますので、前半の<○○>に辿りつきますが、後半の</○○>に辿りつけません。何か良い対策がありましたらよろしくお願いいたします。
回答を見る
  • ベストアンサー

C言語のタグの抽出について

C言語を学習しているものです。 main関数内で定義した "<pro><name>chad smith</name><id>1234</id><live>America<live></pro>" を抽出し表示するプログラムの作成を考えております。 第一パラメータに抽出したいタグ名を書くと表示されるようにします。 >>プログラム名 id 1234 >>プログラム名 name chad smith >>プログラム名 pro <name>chad smith</name><id>1234</id><live>America<live> のような表示にされるようにします。 自分なりに考えてみましたが結果がうまくいかないため質問させて頂きます。 #include<stdio.h> #include<string.h> #define BUF 256 int main(int argc ,char *argv[]) { char str1[]="<pro><name>chad smith</name><id>1234</id><live>America<live></pro>"; char str2[BUF]; printf("%s",&str2[0]); return 0; } 上記のプログラムに対して自分なりにstrstr()とmemcpy()を使用してみましたがうまくいきませんでした。 strstr()を用いますと文字列の最初から検索していきますが 第一パラメータでタグ名だけを宣言しますので 前半の<○○>に辿りつきますが、後半の</○○>に辿りつけません。 何か良い対策がありましたらよろしくお願いいたします。

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

  • ベストアンサー
noname#227064
noname#227064
回答No.1

質問するカテゴリは [技術者向] コンピューター > プログラミング > C&C++ の方が良いです。 > 前半の<○○>に辿りつきますが、後半の</○○>に辿りつけません。 ひょっとして、「strstr(str1, str2)」というようにしか書いていないのでしょうか? 後半のタグの検索には、str1の代わりに最初のタグ以降のポインタを入れてやらないといけません。 一応、使用例をつけておきます。 念のためいっておきますが、ご質問の仕様も満たしていないし、同じタグが入れ子になっていた場合にも対応していないし、更に入力にscanfも使用していますので、完成されたソースではありません。 後はご自分で完成させてみてください。 わからないところがあれば、補足してください。 #include<stdio.h> #include<string.h> #define BUF 256 int main(int argc ,char *argv[]) { char str1[]="<pro><name>chad smith</name><id>1234</id><live>America<live></pro>"; char str2[BUF]; char *p1, *p2; while(1) { printf("%s\nの中から検索したいタグを入力してください。\n終了したい場合はendを入力してください。\n", str1); scanf("%s", str2); if (!strcmp(str2, "end")) break; printf("%sタグを検索します。\n", str2); p1 = strstr(str1, str2); p2 = strstr(p1 + strlen(str2), str2); printf("%.*s\n", p2 - p1, p1); } return 0; }

windy0508
質問者

お礼

回答ありがとうございます。 strstrに関してご指摘の通りにしか使用したことがございませんでした。 作成してくださったソースを参考にして自分なりに再度試行錯誤してみます。 そしてカテゴリのご指摘ありがとうございます。 現在のプログラムで何か疑問がありましたらそちらで質問いたします。 ご丁寧な回答ありがとうございました。

関連するQ&A

  • C言語でタグの抽出について

    main関数で定義した文字列 "<pro><name>chad smith</name><id>1234</id><live>America</live></pro>" があり第一パラメータで検索したいタグを入力すると その中身を表示するプログラムを作成したいと思います。 >>プログラム名 id 1234 >>プログラム名 name chad smith >>プログラム名 pro <name>chad smith</name><id>1234</id><live>America</live> のようになります。 自分なりに作成したのが以下の通りです。 #include<stdio.h> #include<string.h> #define BUF 256 int main(int argc ,char *argv[]) { char str1[]="<pro><name>chad smith</name><id>1234</id><live>America</live></pro>"; char *p1, *p2; int length; if(argc != 2) { fprintf(stderr,"\nUsage :プログラム名 検索したいタグ名\n"); return 1; } p1 = strstr(str1, argv[1]); if(p1==NULL) { fprintf(stderr,"\n検索したタグは見つかりませんでした。\n"); return 1; } length =strlen(argv[1]); p2 = strstr(p1 + length, argv[1]); fprintf(stdout,"\n%.*s\n", (p2-2) - (p1+length+1), p1+length+1); return 0; } 一応自分の期待通りに実行されますが あまり自分の中では良いプログラミングではないような気がします。 後半の部分の(p2-2) - (p1+length+1), p1+length+1あたりがわかりづらいと思います。 もっと良い方法がありましたらよろしくお願いします。

  • C言語 strstrの実装

    課題で strstr()と同じ働きをするmy_strstr()を実装しなさいという課題がでています。 strstr()は char *strstr(const char *s1, const char *s2) という形で、 文字列s2が文字列s1の中に含まれていれば、文字列1の文字列2が含まれている先頭のアドレス(ポインタ)を返す関数です。(すいません、説明が下手で) 例えば、 strstr(Japanese, pan)は Japanese にpan が 含まれるのでpan 以降の文字列を返します→panese *********************** 質問ですが、 strstrの実装は完成して、正常に動くのですが 警告がでてきます。 str1= Japanese str2 = pan とすると、 私のプログラムでは、次のようなプロセスで動きます。 一文字ずつ調べる ↓ str1のJと str2の pを比較        J != p → str1++; //str1の次の文字へ str1のaと str2の pを比較        a != p, str1++; //str1の次の文字へ str1のpと str2の pを比較        p == p, rec = str1 // str1のアドレスを記録         str1++; str2++; //次の文字へ str1のaと str2の aを比較        a == a, str1++; str2++; //次の文字へ str1のnと str2の nを比較        n == n, str1++; str2++; //次の文字へ str1のeと str2 nullを比較    *str2 = null //search 終了。 return rec; とこんな感じです。 このプロセスの3行目の rec = str1; つまり、関数の戻り値のために記録したstr1のところで、 「問題のあるポインタ変換」 という警告がでます。 これは s1がconstだからでしょうか? どのようにしたらこの警告が消えるでしょうか? どなたかよろしければアドバイスをいただけませんか。 お願いします。

  • C言語で可変長から固定長に変換方法は??

    C言語で可変長から固定長に変換方法は?? ある可変長のファイルがあって、レコード長を全て40にそろいたいと思って以下のようにプログラム作りました: ・・・・・(省略) len = strlen(buf); // fscanf使ってファイルから読みみ込んだものbufに格納 n = 40-len; char * str = (char *)malloc(n+1); memset(str, ' ', n); strcat(buf,str); //レコード40バイトになるまで空白を詰めていく fprintf(fpt,buf);//fprintf使って新しいファイルに書き込み ・・・・・・(省略) 実行してみたところ、全部40という長さになっていない、40超えるものも多数出ました。 これは何がだめですか?fprintfをつかったからだめですか?それともmalloc freeにする必要ありますか?まったく検討つかないです。どうかよろしくお願いします

  • C言語に詳しい方お願い致しいます

    文字列Aから文字列Bを除いた結果を表示するプログラムなのですが 一ヶ所分からない部分があります。 #include <stdio.h> #include <string.h> int main(void){  char str1[] = "abcdefg";  char str2[] = "cde";  char str3[128] = "";  char *p1 = str1, *p2;  size_t len;  len = strlen(str2);  while((p2 = strstr(p1,str2)) != NULL) {   strncat(str3,p1,p2 - p1);   p1 = p2 + len;   printf("----\n");   printf("p2=%s\n", p2);   printf("str3=%s\n", str3);   printf("p1=%s\n", p1);  }  strcat(str3,p1);  printf("%s\n",str3);  return 0; } while文中の p1 = p2 + len; なのですが、何故これでp1の内容が「fg」になるのでしょう。

  • C言語でセグメンテーションエラーの原因がわからず困っています。

    こんにちは。いつもお世話になっております。 C言語なのですが、何故かプログラムを実行するとセグメンテーション違反が表示されてしまい全く動きません。皆さんのお力を貸して頂けないでしょうか。 以下が問題のプログラムです。 前提条件: ・別プログラムによりfile.txtは末尾に文章が追加され続けている ・本プログラムは永劫的に動き続ける #include<stdio.h> #include<stdlib.h> #include<string.h> #include<unistd.h> #include<errno.h> #include<signal.h> #include<sys/types.h> int main () { int i = 1, a; FILE *fp, *fp2; char *tok; //NULLを入れて初期化 char buf[1024] = ""; char str[1024] = ""; char str2[1024] = ""; //出力するファイルを開く if ((fp2 = fopen ("out.txt", "a")) == NULL) { printf ("out.txt:open error\n"); exit (-1); } while (1) { //何度もfopenするのでループ二週目以降は一旦fpを閉じる if (str2 != NULL) { fclose (fp); } //一度読み込み、2週目以降もさらに読み込み続ける if ((fp = fopen ("file.txt", "r")) == NULL) { printf ("file.txt:open error\n"); exit (-1); } //str2はループ2週目以降で使われる if (str2 != NULL) { while (1) //新しい行を見つけ出す { fgets (str, 1024, fp); if (strstr (str, str2) != NULL) { printf ("前回の最終行です:%s\n", str); break; } } } else { printf ("str2はNULLです:%s\n", str2); } //fopenで読み込んだ現段階のテキストファイルをout.txtに移す while (1) { if( (fgets (str, 1024, fp) ) == NULL)break; if ((a = strlen (str)) >= 2) { str[a - 1] = '\0'; } else { printf ("抽出した文字列が1文字以下です:%s\n", str); break; } if (strlen (str) >= 17) { strcpy (str2, str); } else { printf ("抽出した文字列が16文字以下です:%s\n", str); break; } printf ("%s\n", buf); fprintf (fp2, "%s\n", buf); strcpy (buf, ""); strcpy (str2, str); } printf ("これが検索語です:%s\n", str2); } fclose (fp2); return 0; } プログラムの内容は、 更新され続けるテキストファイル(file.txt)から、別のテキストファイル(out.txt)に出力するというプログラムです。(file.txtの内容を若干変えつつ、out.txtに出力することが本来の目的ですが、その部分は省略させて頂きました。) fopenで開くと、「その時点まで」のfile.txtしか開かれません。更新され続けているfile.txtの内容をコンスタントに読み取る為に、while文でfopenし続ける方法を取っていますが、そうするとout.txtに移し終わった行まで読み込んでしまい重複した文章をout.txtに移すことになりますので、strstrを使い、「前回fopenで開いたfile.txt」の最終行を検索してその位置からまたout.txtに移す、という方法を取りました。しかし、結果は何故かセグメンテーション違反でした。 以上のプログラムや私の意図する所で何か気づかれた点や、おかしいと思われた点等ありましたら是非ご教授頂きたく思います。 どんな些細なことでも構いませんので、教えて頂けないでしょうか。 環境はCentosです。どうぞよろしくお願いします。

  • C言語の使い方を教えてください。-C言語入門者

    C言語のプログラムの処理の対象となるファイルはどこに保存したらよいのでしょうか?たとえば下記のプログラムで #include <stdio.h> #include <stdlib.h> #include <string.h> void main(void) { char *line[100], *buf; int i = 0, len, lines; FILE *fp; fp = fopen("textfile.txt", "r"); buf = calloc(128, sizeof(char)); while (i < 100 && fgets(buf, 128, fp) != NULL) { len = strlen(buf); line[i] = calloc(len + 1, sizeof(char)); strcpy(line[i], buf); i++; } fclose(fp); lines = ((i <= 100) ? i :100); free(buf); for(i = 0; i < lines; i++) printf("%s", line[i]); for(i = 0; i < lines; i++) free(line[i]); } で [textfile.txt]という名のファイルをマイドキュメントやコンパイラーを保存しているのと同じ領域に保存してコンパイラーを実行しても所要の結果が得られません。テキストにはプログラムの作り方しか書いてありません。

  • 文字列の途中から途中までを抽出

    文字列の一部を抽出したいときのプログラムです。 絶対条件は ・文字列はchar*型 ・ある文字で区切られた区間を抽出 です。 以下のコードだとstrncpyの部分でsegmantation faultになってしまいます。 -------------------------- char array[10] = "abcd/efgh"; char* str0 char* str1; char* str2; int = len; str0 = array; len = strstr(str0, "/") - str0; strncpy(str1, str0, len); str2 = array + len + 1; -------------------------- 各変数が str1 = abcd str2 = fghi となるようにしたいです。 char str1[10];などにすればいいのですが、それ以外の方法でお願いします。

  • xmegaのstrstr関数で文字検索

    現在ATMEL社のATxmega128A1というCPUでプログラミングを行っております。 テンキーパネルでのコマンド操作機能というのを設置しているのですが、テンキー操作で、”#”ボタンが押されると u8 key_proc(u8 * buf,int length) この関数が必ず呼ばれます。 bufという引数に”#”ボタンが押されるまでに押されたボタンのキャラクタデータが収納されたSRAMの番地が格納されています。 例えば、端末の設定などを変更したい場合に使用する4文字のキーがEEPROMに格納されていて、それを変更したい場合のコマンドを追加したいと思っています。 そのEEPROMに格納されている4文字キーというのは (u16)gEnv.main_set.key; というEEPROMに”1234”というデータが入っているのですが、 bufというSRAMのメモリに例えば”1234Z4321#” このようなコマンドが来たらもともと”1234”という現在のkeyと合致して、なおかつ次の文字が”Z”という文字が来たら、次の”4321”というデータに(u16)gEnv.main_set.key;のEEPROMの内容を変更するというプログラムが作りたいと思っています。 現在このようなプログラムでこの機能を実現しています。 #if 1 pass16 = (u16)gEnv.main_set.key; sprintf((char *)str,"%04d",pass16); str[4] = 0; memcpy(value,buf,4); if(strstr((char *)value,(char *)str) != 0) { if(buf[4] == 'Z' && buf[9] == '#') { value[0] = buf[5]; value[1] = buf[6]; value[2] = buf[7]; value[3] = buf[8]; gEnv.main_set.key = strtoul(value,NULL,10); env_save(&gEnv); return true; } } #endif このプログラムを作ったことで疑問に思っていることなのですが、 buf[4] == 'Z' であるかどうかをstrstrとは別のコードで判定しているのですが、 sprintf((char *)str,"%04dZ",pass16); このようなコードで"1234Z"という文字列をstrstr検索して判定することはできないのでしょうか? 現在”sprintf((char *)str,"%04dZ",pass16);”としてしまうと、プログラムが暴走したような状態になり、正常な動作ができなくなってしまう現象が出てしまいます。 どうぞ、ご教示よろしくお願い致します。

  • C言語の変換する関数について教えてください。

    キーボードからローマ字で入力された名前の英文字を変換する関数を定義し、その関数の機能を確認するプログラムを作成する問題について教えてください。 (1)英小文字であればそれを英大文字に変換する関数 (2)英大文字であればそれを英小文字に変換する関数 (3)英小文字であればそれを英大文字に、英大文字であればそれを英小文字に変換する関数 ただし、キーボードから入力された名前を格納する配列と、変換後の名前を格納する配列を別にする。 また、名前は関数main()内で表示する #include <ctype.h> #include <stdio.h> void name_toupper(char str[]) { unsigned i = 0; while (str[i]) { str[i] = toupper(str[i]); i++; } } void name_tolower(char str[]) { unsigned i = 0; while (str[i]) { str[i] = tolower(str[i]); i++; } } int main(void) { char str[100]; printf("文字"); scanf("%s", str); name_toupper(str); printf("大文字: %s\n", str); name_tolower(str); printf("小文字: %s\n", str); return 0; } 自分で作った上のプログラムではKa siと入力すると(1)ではKA、(2)ではkaと表示されsiが消えてしまいます。原因がよくわかりません。 あと(3)ができないし、ただしを満たしているのかもあいまいです。 文字列の入力の形式:char *gets(char *buffer)を用いればどうにかなるのではと思っていますがどうですか? 説明が長くなって申し訳ありませんが教えてください。 よろしくお願いします。

  • C言語のint型の配列が分かりません

    #include<stdio.h> int main(void) { int str[ ]={0,1,2} printf("%s\n", str); return 0; } というプログラムをC言語でつくってみましたが動きません.(012と表示されて欲しかったのですが) int str[ ]={1,2,3}の部分をchar str[ ]={'0','1','2'}とすれば動きます. そこで質問なのですが, printf("~%s~", (配列名));  はchar型の配列にしか適応できないのですか? ※追記 puts関数の定義は int puts (const char *str); であるそうなので char型の仮引数にはchar型のアドレスを渡さなければいけません. ではprintf関数の定義は一体どんなものなのですか?