c言語で、関数の再帰を使った自作のバイナリサーチを作っています。
番号は名前はアルファベット順に昇順で並び替えてあります。
検索できるところまでは完成したのですが、検索したい値がなかった時と検索値に該当する名前が、複数個あった時の処理をどうやって作ればよいか悩んでいます。検索したい値がないときは、もっとも左の値と右の値が同じになった時に-1をmai= Bsearch(fname, name,m,left, right);}
c言語
Re: c言語 バイナリサーチ
コードに全角スペースが下記の通り入っていたので半角スペースに置き換えWindows10、VS2017Communityでビルド出来ました。
gakusei.csvのデータと”検索できるところまでは完成した”コードを送ってくださればテストして考えてみましょう。それと環境と動作時コマンドを提示してください。
[/size]
gakusei.csvのデータと”検索できるところまでは完成した”コードを送ってくださればテストして考えてみましょう。それと環境と動作時コマンドを提示してください。
#include <stdio.h>
#include <stdlib.h>
#define DT 50
int Bsearch( char fname[10], char na[DT][10],int mid,int bottom, int top)
{
int ret,c;
□□ ret = strcmp(na[mid],fname);
□□ if(ret==0){return mid;}
else if(ret<0)
{c=(mid+top)/2; Bsearch(fname, na, c, mid, top);}
else
{c=(bottom+mid)/2; Bsearch( fname,na, c, bottom, mid);}
}
int main(int argc, char *argv[])
{
FILE *fp;
char num[DT][10],name[DT][10],fname[10];
int i=0,ret,m,temp,left=0,right,pac[3],n;
fp=fopen("gakusei.csv","r");
□□□/* メンバー情報入力 */
□□□while(fscanf(fp,"%[^,],%s\n", num[i],name[i])!=EOF)
{i++;}
strcpy(fname,argv[1]);
□□ right=i;m=i/2;
if (fname[2]=='0')
{temp = Bsearch(fname, num,m,left, right);}
else{temp = Bsearch(fname, name,m,left, right);}
printf("検索結果:\n%s,%s",num[temp],name[temp]);
}
1>------ すべてのリビルド開始: プロジェクト:ConsoleApplication8, 構成: Debug Win32 ------
1>c1.c
1>d:\z17\c\consoleapplication8\consoleapplication8\c1.c(8): warning C4013: 関数 'strcmp' は定義されていません。int 型の値を返す外部関数と見なします。
1>d:\z17\c\consoleapplication8\consoleapplication8\c1.c(37): warning C4013: 関数 'strcpy' は定義されていません。int 型の値を返す外部関数と見なします。
1>d:\z17\c\consoleapplication8\consoleapplication8\c1.c(29): warning C4996: 'fopen': This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
1>c:\program files (x86)\windows kits\10\include\10.0.15063.0\ucrt\stdio.h(207): note: 'fopen' の宣言を確認してください
1>d:\z17\c\consoleapplication8\consoleapplication8\c1.c(32): warning C4996: 'fscanf': This function or variable may be unsafe. Consider using fscanf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
1>c:\program files (x86)\windows kits\10\include\10.0.15063.0\ucrt\stdio.h(1195): note: 'fscanf' の宣言を確認してください
1>d:\z17\c\consoleapplication8\consoleapplication8\c1.c(27): warning C4101: 'pac': ローカル変数は 1 度も使われていません。
1>d:\z17\c\consoleapplication8\consoleapplication8\c1.c(27): warning C4101: 'n': ローカル変数は 1 度も使われていません。
1>d:\z17\c\consoleapplication8\consoleapplication8\c1.c(27): warning C4101: 'ret': ローカル変数は 1 度も使われていません。
1>d:\z17\c\consoleapplication8\consoleapplication8\c1.c(21): warning C4715: 'Bsearch': 値を返さないコントロール パスがあります。
1>ConsoleApplication8.vcxproj -> D:\z17\c\ConsoleApplication8\Debug\ConsoleApplication8.exe
1>ConsoleApplication8.vcxproj -> D:\z17\c\ConsoleApplication8\Debug\ConsoleApplication8.pdb (Partial PDB)
1>プロジェクト "ConsoleApplication8.vcxproj" のビルドが終了しました。
========== すべてリビルド: 1 正常終了、0 失敗、0 スキップ ==========
Re: c言語 バイナリサーチ
- 全角スペースがある。
- インデントがおかしい。
- fscanf の書式は "%[^,],%s\n" より " %[^,],%s" のほうがよい。
- main の right は最後の要素の次を指している。
- Bsearch が値をを返さない。
- Bearch を呼ぶ前に mid を求めているが、Bsearch の中でやればよい。
- 見つからない場合の処理がない。
- 同じ名前が複数ある場合の処理がない。
- fclose がない。
#include <stdio.h> // printf, fscanf, puts
#include <string.h> // strcmp, strcpy
#define DT 50
int Bsearch(const char fname[], char a[][10], int left, int right)
{
if (left > right) return -1;
int mid = (left + right) / 2;
int ret = strcmp(a[mid], fname);
if (ret < 0) return Bsearch(fname, a, mid+1, right);
if (ret > 0) return Bsearch(fname, a, left, mid-1);
return mid;
}
void range(const char *fname, char a[][10], int t, int right, int *r)
{
int i;
for (i = t; i > 0; i--)
if (strcmp(a[i-1], fname) ) break;
r[0] = i;
for (i = t; i < right; i++)
if (strcmp(a[i+1], fname) ) break;
r[1] = i;
}
int main(int argc, char *argv[])
{
char num[DT][10], name[DT][10];
int i, temp;
if (argc < 2) { printf("usage: %s name\n", argv[0]); return 1; }
FILE *fp = fopen("gakusei.csv", "r");
if (!fp) { puts("file open error"); return 2; }
for (i = 0; i < DT; i++)
if (fscanf(fp, " %[^,],%s", num[i], name[i]) != 2) break;
fclose(fp);
int left = 0, right = i-1;
char *fname = argv[1];
if (fname[2] == '0')
temp = Bsearch(fname, num, left, right);
else
temp = Bsearch(fname, name, left, right);
if (temp < 0)
puts("not found");
else {
int r[2];
if (fname[2] == '0')
range(fname, num, temp, right, r);
else
range(fname, name, temp, right, r);
for (int i = r[0]; i <= r[1]; i++)
printf("検索結果:%s,%s\n", num[i], name[i]);
}
return 0;
}
nb0100,abc
nb0200,def
nb0300,ghi
nb0400,jkl
nb0401,jkl
nb0402,jkl
nb0500,mno
nb0600,pqr
nb0600,pqr1
nb0600,pqr2
nb0700,stu
nb0800,vw
nb0900,xyz
Re: c言語
件名から「バイナリサーチ」が消え、本文からプログラムが削除されていますが、なぜですか?梅こんぶ さんが書きました:c言語で、関数の再帰を使った自作のバイナリサーチを作っています。
番号は名前はアルファベット順に昇順で並び替えてあります。
検索できるところまでは完成したのですが、検索したい値がなかった時と検索値に該当する名前が、複数個あった時の処理をどうやって作ればよいか悩んでいます。検索したい値がないときは、もっとも左の値と右の値が同じになった時に-1をmai= Bsearch(fname, name,m,left, right);}
こういうことは、フォーラムルールで禁止されています。
新たな返信で、説明をお願いします。