例外がスローされるとはどういうことなのか

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
ヒロ修羅
記事: 2
登録日時: 2週間前

例外がスローされるとはどういうことなのか

#1

投稿記事 by ヒロ修羅 » 2週間前

自分は以下のようなプログラムを作っています。
・古いファイル(A)を読み込む。Aのファイルには”文,小数値A,小数値B”のようになっている。
・Aにある単語を比較ファイル(B)と比較する。Bのファイルには”文(tabによる空白)小数値”のようになっている。
・AとBの単語が同じであればAの小数値AにBの小数値を代入する。
・Aにある単語を比較ファイル(C)と比較する。CのファイルにはBのファイルと同じようになっている。
・AとBの単語が同じであればAの小数値BとCの小数値を代入する。
・出来上がった単語を新しいファイル(D)に書き込む。書き込む際にはAのファイルと同じように書き込む。
・これらをAのファイルがNULLになるまで繰り返す。
このようなプログラムを作成しています。
一応仮ではありますが、作成したソースコードを載せます。

コード:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char origin_word[50];
double origin_happy;
double origin_unhappy;
int old_file_flag;
int new_happy_file_flag;
int new_unhappy_file_flag;
int file_output_flag = 0;

//ファイルのチェック
FILE *File_check(const char fname[],const char mode[])
{
	FILE *fp;
	fopen_s(&fp,fname,mode);

	if(fp == NULL){
		printf("ファイルオープン失敗\n");
		exit(1);
	}
	return(fp);
}

//旧ファイルとの比較
void comparison_old_file() {

}

//新幸福ファイルとの比較
double comparison_new_happy_file(char word[30],double happy)
{
	FILE *fp;
	char h_word[30];
	char str[50];
	double new_happy;

	fp = File_check("New_happy.txt","r");

	while (fscanf_s(fp, "%s %lf", h_word, &new_happy,sizeof(str)) == NULL) {
		if (strstr(word, h_word) != NULL) {
			if (origin_word == h_word) {
				strcpy_s(origin_word,word);
			}
			break;
		}
	}
	fclose(fp);
	return(new_happy);
}
//新不幸ファイルとの比較
double comparison_new_unhappy_file(char word[30],double unhappy) {
	FILE *fp;
	char u_word[30];
	char str[50];
	double new_unhappy;

	fp = File_check("New_unhappy.txt", "r");

	while (fscanf_s(fp, "%s %lf", u_word, &new_unhappy,sizeof(str)) == NULL) {
		if (strstr(word, u_word) != NULL) {
			if (origin_word == u_word) {
				strcpy_s(origin_word, word);
			}
			break;
		}
	}
	fclose(fp);
	return(new_unhappy);
}

//ファイルの書き込み
void File_output(void) 
{
	FILE *fp;
	const char *file = "/*個人情報のため隠します。*/";

	if (file_output_flag == 0) {
		fp = File_check(file,"w");
		fprintf_s(fp,origin_word,origin_happy,origin_unhappy);
		file_output_flag = 1;
		printf("保存できました\n");
	}
	else {
		fp = File_check(file,"a");
		fprintf_s(fp,origin_word,origin_happy,origin_unhappy);
	}

	fclose(fp);

}


//古いファイルと新しいファイルの比較
void old_and_new()
{
	FILE *fp;
	char word[30];
	char str[80];
	double happy;
	double unhappy;

	fp = File_check("social_evaluation.txt","r");

	while (fscanf_s(fp, "%s,%lf,%lf", word, &happy, &unhappy,sizeof(str)) != NULL ) {
		origin_happy = comparison_new_happy_file(word,happy);
		origin_unhappy = comparison_new_unhappy_file(word,unhappy);
		File_output;
	}
	fclose(fp);
}

int main(void)
{
	old_and_new();

	return 0;
}
開発環境はVisualStudio2015Communityで言語はC言語です。
このプログラムをデバッグすると添付された画像が出てきます。
このようなメッセージ画面が出てきて対処方法に困っています。
どのように対処をすればいいか教えてください。
よろしくお願いします。
添付ファイル
エラー.PNG
エラー.PNG (27.89 KiB) 閲覧数: 513 回

かずま

Re: 例外がスローされるとはどういうことなのか

#2

投稿記事 by かずま » 2週間前

実行可能ファイルが kanryaku.exe になっていますが、
ソースファイルは kanryaku.c ですか?
それとも kanryaku.cpp ですか?

kanryaku.cpp だとして、ビルドすると、warning(警告) がたくさん出ます。
fscanf_s の使い方が間違っています。次のように修正してみてください。

コード:

41c41
< 	while (fscanf_s(fp, "%s %lf", h_word, &new_happy,sizeof(str)) == NULL) {
---
> 	while (fscanf_s(fp, "%s %lf", h_word, sizeof(h_word), &new_happy) == NULL) {
61c61
< 	while (fscanf_s(fp, "%s %lf", u_word, &new_unhappy,sizeof(str)) == NULL) {
---
> 	while (fscanf_s(fp, "%s %lf", u_word, sizeof(u_word), &new_unhappy) == NULL) {
106c106
< 	while (fscanf_s(fp, "%s,%lf,%lf", word, &happy, &unhappy,sizeof(str)) != NULL ) {
---
> 	while (fscanf_s(fp, "%s,%lf,%lf", word, sizeof(word), &happy, &unhappy) != NULL ) {
109c109
< 		File_output;
---
> 		File_output();
106行目の fscanf_s の書式は "%s,%lf,%lf" と「,」が入っていますが、
social_evaluation.txt がそうなっているんですか?
New_happy.txt や New_unhappy.txt には「,」が入っていないのですか?

ヒロ修羅
記事: 2
登録日時: 2週間前

Re: 例外がスローされるとはどういうことなのか

#3

投稿記事 by ヒロ修羅 » 2週間前

修正したらエラーがなくなりました。ありがとうございます。
あと、ソースファイルは Source.cです。
それと、106行目のfscanf_sの書式ですが、
social_evaluation.txtが "%s,%lf,%lf" のようになっており
New_happy.txt や New_unhappy.txt には「,」が入っておらず、"%s(tabによる空白)%lf"のようになっています。

tanu_kichi
記事: 12
登録日時: 2ヶ月前

Re: 例外がスローされるとはどういうことなのか

#4

投稿記事 by tanu_kichi » 2週間前

ちょっと気になった点を書きます。

コード:

double comparison_new_happy_file(char word[30],double happy)
{
	FILE *fp;
	char h_word[30];
	char str[50];
	double new_happy;
	fp = File_check("New_happy.txt","r");
	while (fscanf_s(fp, "%s %lf", h_word, &new_happy,sizeof(str)) == NULL) {
		if (strstr(word, h_word) != NULL) {
			if (origin_word == h_word) {
				strcpy_s(origin_word,word);
			}
			break;
		}
	}
	fclose(fp);
	return(new_happy);
}
1)>> if (origin_word == h_word)
のような文字列(char配列)の比較は、
size_t len_o = strlen(origin_word);
size_t len_h = strlen(h_word);
if ((len_o == len_h) && (strncmp(origin_word, h_word, len_o) == 0))
のようにするべきだと思います。

2)>> ・AとBの単語が同じであればAの小数値AにBの小数値を代入する。
とありますが、
上のコードだと、同じ単語がない場合、New_happy.txtの最後の行のnew_happyの値が返されると思います。
同様にdouble comparison_new_unhappy_file()関数も、New_unhappy.txtの最後の行のnew_unhappyの値が返されると思います。
「100%同じ単語がある」を想定しているならば、問題ないとは思いますが、そうでなければ意図しない結果になる可能性があります。

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

Re: 例外がスローされるとはどういうことなのか

#5

投稿記事 by みけCAT » 2週間前

tanu_kichi さんが書きました:
2週間前
1)>> if (origin_word == h_word)
のような文字列(char配列)の比較は、
size_t len_o = strlen(origin_word);
size_t len_h = strlen(h_word);
if ((len_o == len_h) && (strncmp(origin_word, h_word, len_o) == 0))
のようにするべきだと思います。
strcmp一発ではいけないと思う理由はありますか?
バッファの内容がNUL終端されていない場合にバッファオーバーランするというのは、strlenでも同じでしょう。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

tanu_kichi
記事: 12
登録日時: 2ヶ月前

Re: 例外がスローされるとはどういうことなのか

#6

投稿記事 by tanu_kichi » 2週間前

>> strcmp一発ではいけないと思う理由はありますか?

strcmp一発でOKだと思います。
strlenで比較するのは、私の癖(くせ)でしょうか。

実際は、

コード:

while(...)
  size_t len_o = strlen(origin_word);
  size_t len_h = strlen(h_word);
  if ((len_o != len_h) continue;
  if (strncmp(origin_word, h_word, len_o) != 0)) continue;
  ... // 処理
}

のようにコーディングしており、頻繁に文字列比較する場合や、文字列が長い場合、先にstrlenで比較することで、処理が速くなるかなと思ってるだけで、実際に実行時間を測定したことはないです。申し訳ありません。

かずま

Re: 例外がスローされるとはどういうことなのか

#7

投稿記事 by かずま » 2週間前

tanu_kichi さんが書きました:
2週間前
頻繁に文字列比較する場合や、文字列が長い場合、先にstrlenで比較することで、処理が速くなるかなと思ってるだけで、実際に実行時間を測定したことはないです。
文字列が長い場合ですか?

"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
"bcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"

この 2つの比較するのに、strcmp は それぞれの文字列の先頭 1文字を見ただけで
結果を返します。
strlen を呼び出すと、長い文字列全体を走査し '\0' を見つけて初めて
長さが分かります。

かずま

Re: 例外がスローされるとはどういうことなのか

#8

投稿記事 by かずま » 2週間前

ヒロ修羅 さんが書きました:
2週間前
修正したらエラーがなくなりました。ありがとうございます。
あと、ソースファイルは Source.cです。
コンパイラは何を使っていますか?
本当に Cコンパイラですか?

マイクロソフトのコンパイラなら、ファイルの拡張子が .c でも
/TP オプションを付けて、C++ としてコンパイルできます。

MSDN の strcpy_s を見ると
C の場合、strcpy_s の引数は 3つです。
C++ なら、引数が 2つのものと、3つのものが用意されています。

C で 引数が 2つの strcpy_s を呼び出そうとすると、エラーになるはずです。

tanu_kichi
記事: 12
登録日時: 2ヶ月前

Re: 例外がスローされるとはどういうことなのか

#9

投稿記事 by tanu_kichi » 2週間前

みけCATさん、かずまさんへ

申し訳ありません。私の認識が間違ってました。
文字列比較の場合、strlen , strncmp を併用するより、strcmp をする方が処理速度が速いようです。
以下は、gcc 7.4.0 の strlen , strcmp のソースコードをユーザ関数としてコールして、
実行時間を測定したものです。

コード:

// strcmp.c
#include <stdio.h>
#include <time.h>
//-------------------------------------------------------------------------
unsigned int internal_strlen(const char *s) 
{
  unsigned int i = 0;
  while (s[i])
    i++;
  return i;
}
//-------------------------------------------------------------------------
int internal_strcmp(const char *s1, const char *s2)
{
  while (1) {
    unsigned c1 = *s1;
    unsigned c2 = *s2;
    if (c1 != c2) 
      return (c1 < c2) ? -1 : 1;
    if (c1 == 0)
      break;
    s1++;
    s2++;
  }
  return 0;
}
//-------------------------------------------------------------------------
int main(void)
{
  char *a = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
  char *b = "bcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
  char *c = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345678";
  // strlen cmpare a b
  clock_t strlen_start = clock();
  size_t a_len = internal_strlen(a);
  size_t b_len = internal_strlen(b);
  if (a_len == b_len)
    fprintf(stdout, "strlen a_string = b_string\n");
  else  
    fprintf(stdout, "strlen a_string != b_string\n");
  clock_t strlen_stop = clock();
  fprintf(stdout, "strlen_exec_time %.6lf\n",
          (double)(strlen_stop - strlen_start) / CLOCKS_PER_SEC);
  // strcmp a b
  clock_t strcmp_start = clock();
  if (internal_strcmp(a, b) == 0)
    fprintf(stdout, "strcmp a_string = b_string\n");
  else
    fprintf(stdout, "strcmp a_string != b_string\n");
  clock_t strcmp_stop = clock();
  fprintf(stdout, "strcmp_exec_time %.6lf\n",
          (double)(strcmp_stop - strcmp_start) / CLOCKS_PER_SEC);
  // strcmp a c
  clock_t strcmp_start2 = clock();
  if (internal_strcmp(a, c) == 0)
    fprintf(stdout, "strcmp2 a_string = b_string\n");
  else
    fprintf(stdout, "strcmp2 a_string != b_string\n");
  clock_t strcmp_stop2 = clock();
  fprintf(stdout, "strcmp2_exec_time %.6lf\n",
          (double)(strcmp_stop2 - strcmp_start2) / CLOCKS_PER_SEC);
  return 0;
}
出力

コード:

strlen a_string != b_string
strlen_exec_time 0.000114
strcmp a_string != b_string
strcmp_exec_time 0.000001
strcmp2 a_string != b_string
strcmp2_exec_time 0.000002

返信

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