繰り返し出てくるものから

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
mo-fu

繰り返し出てくるものから

#1

投稿記事 by mo-fu » 4年前

いつも楽しく見ております。
今回も少し知恵を貸していただきたいと思っています。

C言語/ windows7 /Microsoft Visual C++ 2010 Expressを用いています。

例えば
テキストファイルに

 A = [数値1]
 A = [数値2]
 A = [数値3]
 中略
 A = [数値N]
File End.

とあり、私はそこから 数値Nだけ(最後に現れる数値)だけを取り出したいと思っています。Nは定数ではなく、ファイルによってさまざまです。実際はこんなにシンプルではなくこれ以外の情報が大量に書き込まれたテキストですが、「A =」という文字列はその他の行には現れず、特異的な文字列です。
そのテキストファイルを一行ずつ読み 「A =」という文字列を見つけたときだけ、以下の手順を踏んで

コード:

if(strstr(str,key)){//「A =」がある行を探す
 tok = strtok( str, s1 );//その行をバックスペースで区切る
 while( tok != NULL ){
  tokcounter ++;
  if(tokcounter == 3){//区切ったものから数値を選ぶ
   LastTok = tok;
   }
  }
 }
*LastTok に数値N(実際には文字列として扱ってますが)を収納しています。

このあとファイルをケツまで読み終わったら、LastTokをoutputファイルに書き出すのですが、なぜかそのとき 「File End.」の文字列が書き出されてきます。

この行に「A =」は現れませんし、「A =」が現れたときしかLastTokに文字列を収納(引き渡し)してないはずなのに!と自分では思うのですが、結果は正直なものでこの現象から抜け出せません。

具体的なファイルやプログラムの全体像を載せることが出来ないので、伝わりづらいかもしれませんが、何か打開策があればよろしくお願いします。

アバター
Tatu
記事: 445
登録日時: 9年前
住所: 北海道

Re: 繰り返し出てくるものから

#2

投稿記事 by Tatu » 4年前

このような感じですか?

コード(1つ下のみけCATさんの投稿も確認してください)
► スポイラーを表示
テストファイル(test.txt)
► スポイラーを表示
実行結果
► スポイラーを表示
最後に編集したユーザー Tatu on 2015年6月19日(金) 13:54 [ 編集 1 回目 ]

アバター
みけCAT
記事: 6227
登録日時: 9年前
住所: 千葉県
連絡を取る:

Re: 繰り返し出てくるものから

#3

投稿記事 by みけCAT » 4年前

Tatu さんが書きました:

コード:

			if (strstr(str, "A =") != NULL){
				//整数を取り出して表示する(注:str+3は「A =」が3バイトだから)
				sscanf(str+3,"%d", &data);
				printf("%d\n", data);
			}
せっかく検索したので、その結果を利用した方がいいと思います。

コード:

			char* str2;
			if ((str2 = strstr(str, "A =")) != NULL){
				//整数を取り出して表示する(注:str2+3は「A =」が3バイトだから)
				sscanf(str2+3,"%d", &data);
				printf("%d\n", data);
			}
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
Tatu
記事: 445
登録日時: 9年前
住所: 北海道

Re: 繰り返し出てくるものから

#4

投稿記事 by Tatu » 4年前

LastTokが思った通りの内容にならない理由について

LastTokはtokと同じ場所を参照するようになっています。
tokはstrtok()が返す場所を参照するようになっています。
何らかの理由(strstr()でしょうか?)でstrtok()が返す場所が書き換えられると
LastTokが参照している場所のデータは書き換えられた後のデータとなります。

文字型変数のポインタLastTokにtokを代入するのではなく、
文字列LastTokにtokが指している文字列をコピーするようにしたらどうなりますか?


>>みけCATさん
確かに「A =」の後のデータが欲しいのだということを示すために検索した結果を利用したほうがいいですね。

mo-fu

Re: 繰り返し出てくるものから

#5

投稿記事 by mo-fu » 4年前

Tatu様、みけCAT様

早急な返信ありがとうございます。やはり困ったときの神頼みだなと思います。(いけないことですが。)

>>Tatu様
sscanfを使う方法もやってみたのですが、なぜかうまくいかなくて。でも、あれ?Tatuさんのだと出来てる…と思って再確認してみたら、渡している文字列が間違っていたようです。笑 もう一度試してみます。
Tatu さんが書きました:LastTokはtokと同じ場所を参照するようになっています。
tokはstrtok()が返す場所を参照するようになっています。
何らかの理由(strstr()でしょうか?)でstrtok()が返す場所が書き換えられると
LastTokが参照している場所のデータは書き換えられた後のデータとなります。
自分では 「A =」を見つけて、さらに特定の場所を見つけたときだけ、LastTokにTokと同じ場所を参照させているつもりでいましたが、そうはなっていなかったのですね。精進いたします。

解決後、また解決タグを付けに来ます。取り急ぎお礼まで。

ISLe()

Re: 繰り返し出てくるものから

#6

投稿記事 by ISLe() » 4年前

mo-fu さんが書きました:自分では 「A =」を見つけて、さらに特定の場所を見つけたときだけ、LastTokにTokと同じ場所を参照させているつもりでいましたが、そうはなっていなかったのですね。精進いたします。
そこは間違ってないです。

LastTokやTokの指している場所が、ファイルから読み込んだデータで上書きされるので、最終的に最後に読み込んだデータを指している状態になります。

質問の時点からいちばん手間がかからないのは
LastTokを(ポインタではなく)配列で宣言して、Tokから文字列をコピーしてやる方法です。

かずま

Re: 繰り返し出てくるものから

#7

投稿記事 by かずま » 4年前

mo-fu さんが書きました:sscanfを使う方法もやってみたのですが、なぜかうまくいかなくて。

コード:

#include <stdio.h>

int main(void)
{
	int data, lastData = 0;
	char str[1024];
	FILE *fp = fopen("foo.txt", "r");
	if (!fp) return 1;
	while (fgets(str, sizeof str, fp))
		if (sscanf(str, " A =%d", &data) == 1)
			printf("%d\n", lastData = data);
	fclose(fp);
	printf("last data = %d\n", lastData);
	return 0;
}
foo.txt

コード:

A = 123
B = 45
C = 6789

A = 987
B = 65
C = 4321

A = 753
B = 246

file End.
実行結果

コード:

123
987
753
last data = 753

mo-fu

Re: 繰り返し出てくるものから

#8

投稿記事 by mo-fu » 4年前

ISLe() 様 かずま様
返信ありがとうございます。

>>ISLe() 様
ISLe() さんが書きました:LastTokやTokの指している場所が、ファイルから読み込んだデータで上書きされるので、最終的に最後に読み込んだデータを指している状態になります。
tok・Lasttokに場所を渡すのはif文の中だけなので、tokもはLasttokも私が設けた条件の時に渡した場所をずっと覚えていてくれると思っていましたが、そうではないみたいですね。素人が下手にポインタを使おうとするとなかなか難しいです。

>>かずま様
ありがとうございます。実は簡単のために[A =]と表現したのですが、実際は[英文 = 数値 英文] とサイズ・内容共に出現するたびに変化していて、sscanfは上手い手が思いつかない時の最終手段かな と思ってました。 でもこういう教科書に載っているような小さなプログラムを短時間でエラーなく書けることが大切なんだなぁと実感させられました。

皆々様方ありがとうございました!無事動くものが完成しましたので、解決タグをつけに参りました。

また困ったら、神頼みしに来ますね!(笑) ありがとうございました。

ISLe()

Re: 繰り返し出てくるものから

#9

投稿記事 by ISLe() » 4年前

mo-fu さんが書きました:tok・Lasttokに場所を渡すのはif文の中だけなので、tokもはLasttokも私が設けた条件の時に渡した場所をずっと覚えていてくれると思っていましたが、そうではないみたいですね。素人が下手にポインタを使おうとするとなかなか難しいです。
『あそこの角にあった』コンビニがいつのまにかコンビニでなくなってたというようなふつうにあること(概念)です。
そこにコンビニがあったことを記録しておくために写真を撮っておいたりする(コピーを作っておく)というのも自然なことです。
コンビニは簡単に無くなるものなのに、多くのひとがそこにあるものが恒久であるという思い込みを持ちます。
それと同様の問題であって、ポインタ自体は難しいものではありません。

閉鎖

“C言語何でも質問掲示板” へ戻る