質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Objective-C

Objective-Cはオブジェクト指向型のプログラミング言語のひとつです。C言語をベースにSmalltalkが取り入れられています。

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

XML

XMLは仕様の1つで、マークアップ言語群を構築するために使われています。

Q&A

解決済

1回答

413閲覧

[C]idを取得したのに表示ができない.

studyprg

総合スコア57

Objective-C

Objective-Cはオブジェクト指向型のプログラミング言語のひとつです。C言語をベースにSmalltalkが取り入れられています。

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

XML

XMLは仕様の1つで、マークアップ言語群を構築するために使われています。

0グッド

0クリップ

投稿2022/06/13 09:43

編集2022/06/13 14:39

やりたいこと

自然言語処理について勉強しています。
Wikipediaのdumpデータから本文を抜き出して処理をしようと思ってます。
、出力結果が想定とは全然違って困っています。
欲しい出力は,,<title>hoge</title><id>hoge</id>の中身です。(hoge部分)
後述の出力のidが表示されず困っています。
プログラミングはあまり得意ではないです。
外部ライブラリはすぐできてしまうのでなるべく自力で行いたいです.

実行環境

Macbook pro(2017)
OS:11.6.7

以下に用意したファイル(<page>~~</page>)の一部とソースコードを貼り付けます。

get_text_All.txt

1 <page> 2 <title>遠山景晋</title>//ここが欲しい 3 <ns>0</ns> 4 <id>114795</id>//ここも欲しい. 5 <revision> 6 <id>86493646</id> 7 <parentid>81273289</parentid> 8 <timestamp>2021-11-12T08:36:31Z</timestamp> 9 <contributor> 10 <ip>27.85.204.9</ip> 11 </contributor> 12 <model>wikitext</model> 13 <format>text/x-wiki</format> 14 <text bytes="9434" xml:space="preserve">{{基礎情報 武士 15| 氏名 = 遠山景晋 16| 画像 = 17| 画像サイズ = 18| 画像説明 = 19| 時代 = [[江戸時代]]後期 20| 生誕 = [[宝暦]]14年[[1月14日 (旧暦)|1月14日]]([[1764年]][[2月15日]])&lt;ref&gt;本妙寺の墓碑による([[氏家幹人]]『旗本御家人―驚きの幕臣社会の真実』(洋泉社歴史新書y 2011年)72頁)。&lt;/ref&gt;&lt;ref group=&quot;†&quot;&gt;『[[寛政重修諸家譜]]』などの幕府編纂の資料では宝暦2年([[1752年]])生まれとされているが、それは[[官年]]とみられる(氏家幹人『旗本御家人―驚きの幕臣社会の真実』(洋泉社歴史新書y 2011年)72頁)。&lt;/ref&gt; 21 22 23 24 25中略 26 27 28 29 30[[Category:1837年没]]</text> 31 <sha1>chmmooepsrvwuo4n0ziki50nn5rvhj7</sha1> 32 </revision> 33 //</page>の手前までで終わっている. 34 <page>//次のページ 35... 36...

ソースコード

Wiki_getter3_title.c

1#include <stdio.h> 2#include <stdlib.h> 3#include <string.h> 4#define SIZE 256 * 1024 * 1024 5int main() 6{ 7 8 int p = 0; 9 int b = 0; 10 int pb[5] = {}; 11 int id = 0; 12 char *idnum = malloc(SIZE); 13 char *line = malloc(SIZE); 14 char *title = malloc(SIZE); 15 FILE *fp = NULL; //読み込み 16 FILE *fw = NULL; //書き込み 17 fp = fopen("get_text_all.txt", "r"); 18 fw = fopen("get_title_id.txt", "w"); 19 if ((fp == NULL) || (fw == NULL)) 20 { 21 printf("failed load ファイル"); 22 abort(); 23 } 24 25 while (p = ftell(fp), fgets(line, BUFSIZ, fp)) 26 { 27 char *p1, *p2; 28 p1 = strstr(line, "<title>"); 29 p2 = strstr(line, "</title>"); 30 if (p1 && p2) // 1行に両方見つかった 31 { 32 b = strlen("<title>"); 33 p1 += strlen("<title>"); // <title>の次の位置 34 int len = p2 - p1; 35 if (len >= 0) 36 { 37 memcpy(title, p1, len);//これをやるべきなのか?参考までに 38 //fseek(fp, -b, SEEK_CUR); 39 //fseek(fp, p + (p1 - line), SEEK_SET); //<title>まで戻る 40 //fgets(title, len + 1, fp); //読み込んでタイトルに格納 41 title[len] = '\0'; // 終端記号を忘れずに追加 42 43 char *p3, *p4; 44 p3 = strstr(line, "<id>"); 45 p4 = strstr(line, "</id>"); 46 // frite(); 47 // fprintf(fw, "%s\n", title); 48 49 if (p3 && p4) // 1行に両方見つかった 50 { 51 b = strlen("<id>"); 52 p3 += strlen("</id>"); // <title>の次の位置 53 int len = p4 - p3; 54 if (len >= 0) 55 { 56 memcpy(idnum, p1, len);//これをやるべきなのか?参考までに 57 // fseek(fp, -b, SEEK_CUR); 58 //fseek(fp, p + (p3 - line), SEEK_SET); //<id>まで戻る 59 //fgets(idnum, len + 1, fp); //読み込んでタイトルに格納 60 idnum[len] = '\0'; // 終端記号を忘れずに追加 61 62 63 64 } 65 } 66 } 67 printf("title\tis\t%s\tID:%s\n", title, idnum);//ここのidnumが表示されてない 68 fprintf(fw, "%s\t%s\n", line,idnum); 69 } 70 71 72 } 73 printf("process ok"); 74 free(line); 75 free(idnum); 76 free(title); 77 fclose(fp); 78 fclose(fw); 79} 80

追記:実行はできましたがidが表示されてません.

wiki_getter3_title.c(更新版)

1#include <stdio.h> 2#include <stdlib.h> 3#include <string.h> 4 5int main() 6{ 7 8 size_t p, pb[3]; 9 char line[BUFSIZ]; 10 char title[BUFSIZ]; 11 char idnum[BUFSIZ]; 12 FILE *fp = fopen("jawiki-20211220-pages-articles-multistream2.xml", "r"); 13 FILE *fw = fopen("get_text_byte3_title_and_id.txt", "w"); 14 if ((NULL == fp) || (NULL == fw)) 15 abort(); 16 while (p = ftell(fp), fgets(line, BUFSIZ, fp)) 17 { 18 /* 19 if (strstr(line, "<page> ")) 20 pb[0] = p; 21 else if (strstr(line, "</page>")) 22 { 23 pb[1] = p - pb[0]; 24 printf("%zu\t%zu\n", pb[0], pb[1]); 25 fprintf(fw, "%zu\t%zu\n", pb[0], pb[1]); // ... 26 // fprintf(fw, "%d\t%d\n", pb[0], pb[1]); ... テキスト形式で観察可能 27*/ 28 char *p1, *p2; 29 p1 = strstr(line, "<title>"); 30 p2 = strstr(line, "</title>"); 31 32 if (p1 && p2) 33 { // 1行に両方見つかった 34 p1 += strlen("<title>"); // <title>の次の位置 35 int len = p2 - p1; 36 int nowp = atoi(p1); 37 if (len >= 0) 38 { 39 memcpy(title, p1, len); //出力  40 title[len] = '\0'; // 終端記号を忘れずに追加 41 } 42 } 43 else 44 { 45 char *p3, *p4; 46 p3 = strstr(line, "<id>"); 47 p4 = strstr(line, "</id>"); 48 if (p3 && p4) 49 { 50 p3 += strlen("<id>"); // <id>の次の位置 51 int len = p4 - p3; 52 if (len >= 0) 53 { 54 memcpy(idnum, p3, len); //出力  55 idnum[len] = '\0'; // 終端記号を忘れずに追加 56 } 57 printf("title:%s\tID:%s\n", title, idnum); 58 fprintf(fw, "%s\t%s\n", line, idnum); 59 } 60 } 61 } 62 fclose(fw); 63 fclose(fp); 64}

エラーについて.

タイトルは取得できましたが,idnumが表示されてないです.

terminal

1 2最後の方を表示 3 4 5

ループの終了位置をミスしているのかな?
idnumが空っぽいですね.

参考程度にget_all_textの一例と欲しい部分です。これが大量に入ったファイルが欲しいです。

get_all_text.txt

1 <page> 2 <title>鳥取砂丘</title>//ここが欲しい 3 <ns>0</ns>//ここはいらない 4 <id>19812</id>//ここも欲しい 5 <revision> 6 <id>53717095</id> 7 <parentid>53211643</parentid> 8 <timestamp>2014-12-06T03:46:16Z</timestamp> 9 <contributor> 10 <ip>58.156.158.18</ip> 11 </contributor> 12 <comment>/* 砂丘の利用と周辺住民とのかかわり */</comment> 13 <model>wikitext</model> 14 <format>text/x-wiki</format> 15 <text xml:space="preserve">{{Coord|35|32|27.821|N|134|13|41.789|E|region:JP|display=title}} 16[[ファイル:Tottori-Sakyu Tottori Japan.JPG|thumb|300px|馬の背]] 17{{mapplot|134.2290|35.5407|鳥取砂丘}} 18'''鳥取砂丘'''(とっとりさきゅう)は、[[鳥取県]][[鳥取市]]の[[日本海]]海岸に広がる広大な砂礫地で、代表的な[[海岸砂丘]]。日本三大砂丘の1つである&lt;ref&gt;その他の2つについては、諸説ある。&lt;/ref&gt;。[[山陰海岸国立公園]]の特別保護地区に指定されており、南北2.4km、東西16kmに広がる日本最大の観光可能な[[砂丘]]である。(一般に立ち入れない物も含めると、日本最大の砂丘は&lt;!--(内陸にある砂丘を含めると--&gt;[[青森県]]の[[猿ヶ森砂丘]])。&lt;!--内陸砂丘は大陸内部の砂丘を示し、日本には内陸砂丘なないため編集しました--&gt; 19 20[[1955年]](昭和30年)に国の[[天然記念物]]に指定された。[[2007年]](平成19年)には[[日本の地質百選]]に選定された。 21 22== 砂丘の状況 == 23[[中国山地]]の[[花崗岩]]質の[[岩石]]が[[風化]]し、[[千代川]]によって日本海へ流されたあと、海岸に集まったものが砂丘の主な[[砂]]となっている。海中の砂を海岸に向けて流れ寄せる潮流と、海岸線に[[堆積]]した砂を内陸へ吹き込む[[卓越風]]の働きで形成された。 24 25砂丘は千代川の東西に広がっているが、通常「鳥取砂丘」というと、千代川の東側の545haの「浜坂砂丘」を指す。砂丘によって海から切り離されて出来た湖である[[多鯰ヶ池]]がすぐ南東にある。 26 27 28<中略> 29 30 31</text> 32 <sha1>axvz6j2vrmxe3n68ssg11m0w8qtcobn</sha1> 33 </revision> 34 </page> 35 36

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hoshi-takanori

2022/06/13 10:56

現状だと title と id が同じ行にないと id が取得できないですね。というか、XML を行単位で処理しようという考えがそもそも間違ってる気がします。 「外部ライブラリはすぐできてしまうのでなるべく自力で行いたい」という心がけは立派ですが、XML という構造を持ったフォーマットのデータを C 言語で外部ライブラリを使わずにパーズするのは現実的ではないと思います。「プログラミングはあまり得意ではない」なら特に。 C 言語による文字列操作の習得が主目的ならそれも良いとは思いますが、自然言語処理が目的なら、それに適した言語 (python とか?) で、適度にライブラリを使ってやるのが良いのでは…。
studyprg

2022/06/13 14:39 編集

追記:回答から修正したのですが,タイトルが2〜3回ずつ同じものが表示され,idがバラバラのものが出力されます. ループの中の処理ミスって流と思います. 以下実行時に表示されたものです. 修正版を追記しておきます. title:庄内川 ID:167064 title:庄内川 ID:86359689 title:庄内川 ID:1295347 title:小笠原忠真 ID:167065 title:小笠原忠真 ID:85625747
guest

回答1

0

ベストアンサー

いまのコードの構成は、

c

1 char *p1, *p2; 2 p1 = strstr(line, "<title>"); 3 p2 = strstr(line, "</title>"); 4 if (p1 && p2) // 1行に両方見つかった 5 { 6 ... 7 if (len >= 0) 8 { 9 ... 10 char *p3, *p4; 11 p3 = strstr(line, "<id>"); 12 p4 = strstr(line, "</id>");

となっていて、<title></title> が入っている行にさらに <id></id> が入ってないと動きません。

p1 && p2 ではない場合に <id> を探すべきなのでしょう。

c

1 char *p1, *p2; 2 p1 = strstr(line, "<title>"); 3 p2 = strstr(line, "</title>"); 4 if (p1 && p2) // 1行に両方見つかった 5 { 6 ... 7 if (len >= 0) 8 { 9 ... 10 } 11 } else { 12 char *p3, *p4; 13 p3 = strstr(line, "<id>"); 14 p4 = strstr(line, "</id>"); 15 if (p3 && p4) // 1行に両方見つかった 16 { 17 ... 18 printf("title\tis\t%s\tID:%s\n", title, idnum); 19 fprintf(fw, "%s\t%s\n", line,idnum); 20 }

p1 p2 p3 p4 などの意味のない変数名はやめましょう。title_start title_end id_start id_end などの意味のある名前のほうがミスが入りにくくなります。

投稿2022/06/13 13:08

int32_t

総合スコア20884

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問