c言語

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
梅こんぶ
記事: 3
登録日時: 8年前

c言語

#1

投稿記事 by 梅こんぶ » 8年前

c言語で、関数の再帰を使った自作のバイナリサーチを作っています。
番号は名前はアルファベット順に昇順で並び替えてあります。
検索できるところまでは完成したのですが、検索したい値がなかった時と検索値に該当する名前が、複数個あった時の処理をどうやって作ればよいか悩んでいます。検索したい値がないときは、もっとも左の値と右の値が同じになった時に-1をmai= Bsearch(fname, name,m,left, right);}
最後に編集したユーザー 梅こんぶ on 2017年6月15日(木) 10:01 [ 編集 1 回目 ]

Math

Re: c言語 バイナリサーチ

#2

投稿記事 by Math » 8年前

コードに全角スペースが下記の通り入っていたので半角スペースに置き換えWindows10、VS2017Communityでビルド出来ました。
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 スキップ ==========
[/size]

かずま

Re: c言語 バイナリサーチ

#3

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

  • 全角スペースがある。
  • インデントがおかしい。
  • 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;
}
gakusei.csv

コード:

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
引数が def のときの実行結果

コード:

検索結果:nb0200,def
引数が nb0900 のときの実行結果

コード:

検索結果:nb0900,xy
引数が jkl のときの実行結果

コード:

検索結果:nb0400,jkl
検索結果:nb0401,jkl
検索結果:nb0402,jkl
引数が nb0600 のときの実行結果

コード:

検索結果:nb0600,pqr
検索結果:nb0601,pqr1
検索結果:nb0600,pqr2
引数が hoge のときの実行結果

コード:

not found

かずま

Re: c言語

#4

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

梅こんぶ さんが書きました:c言語で、関数の再帰を使った自作のバイナリサーチを作っています。
番号は名前はアルファベット順に昇順で並び替えてあります。
検索できるところまでは完成したのですが、検索したい値がなかった時と検索値に該当する名前が、複数個あった時の処理をどうやって作ればよいか悩んでいます。検索したい値がないときは、もっとも左の値と右の値が同じになった時に-1をmai= Bsearch(fname, name,m,left, right);}
件名から「バイナリサーチ」が消え、本文からプログラムが削除されていますが、なぜですか?
こういうことは、フォーラムルールで禁止されています。
新たな返信で、説明をお願いします。

返信

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