#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 のときの実行結果
引数が nb0900 のときの実行結果
引数が jkl のときの実行結果
コード:
検索結果:nb0400,jkl
検索結果:nb0401,jkl
検索結果:nb0402,jkl
引数が nb0600 のときの実行結果
コード:
検索結果:nb0600,pqr
検索結果:nb0601,pqr1
検索結果:nb0600,pqr2
引数が hoge のときの実行結果
[list]
[*]全角スペースがある。
[*]インデントがおかしい。
[*]fscanf の書式は "%[^,],%s\n" より " %[^,],%s" のほうがよい。
[*]main の right は最後の要素の次を指している。
[*]Bsearch が値をを返さない。
[*]Bearch を呼ぶ前に mid を求めているが、Bsearch の中でやればよい。
[*]見つからない場合の処理がない。
[*]同じ名前が複数ある場合の処理がない。
[*]fclose がない。[/list]
直してみました。
[code=c]
#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;
}
[/code]
gakusei.csv
[code=text]
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
[/code]
引数が def のときの実行結果
[code=text]
検索結果:nb0200,def
[/code]
引数が nb0900 のときの実行結果
[code=text]
検索結果:nb0900,xy
[/code]
引数が jkl のときの実行結果
[code=text]
検索結果:nb0400,jkl
検索結果:nb0401,jkl
検索結果:nb0402,jkl
[/code]
引数が nb0600 のときの実行結果
[code=text]
検索結果:nb0600,pqr
検索結果:nb0601,pqr1
検索結果:nb0600,pqr2
[/code]
引数が hoge のときの実行結果
[code=text]
not found
[/code]