ページ 1 / 1
結果が出ません。
Posted: 2016年2月13日(土) 17:50
by pazumon_2525
./a.out printf file.c というように実行したら、
行 文字列
1: aaaa printf("aaaaa");
30: printf("aaaaa");
46: printf("abcd");
のようにコマンドラインで指定した文字を検索するようなプログラムを考えました。
しかし、何も出ませんでした。
指摘お願いします。
コード:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define str 300
int match_str(char *a, char *b);
int main(int argc,char *argv[])
{
FILE *fp;
char a[str] = {'\0'};
int cnt,num;
if(argc != 2)
{
return 1;
}
fp = fopen(argv[1],"r");
if(fp == NULL)
{
printf("ファイル %s が見つかりません\n",argv[1]);
return 1;
}
while(fgets(a,str,fp)!= NULL)
{
cnt++;
printf("%d\t:",cnt);
num = match_str(a,argv[2]);
if(num == 1)
{
printf("%s",a);
}
}
fclose(fp);
printf("\n");
}
int match_str(char *a, char *b)
{
int i = 0;
int j = 0;
int maxa,maxb;
int flg = 0;
while(flg == 0)
{
if(a[i] == '\0')
{
maxa = i;
flg == 1;
}
i++;
}
i = 0;
while(flg == 0)
{
if(b[i] == '\0')
{
maxb = 0;
flg = 1;
}
i++;
}
for(i=0;i<maxa;i++)
{
if(0==strncmp(&a[i],&b[j],1))
{
if(maxb-1 == j)
{
return 1;
}
else
{
j++;
}
}
}
return 0;
}
Re: 結果が出ません。
Posted: 2016年2月13日(土) 19:11
by みけCAT
- 実行コマンド名を除くコマンドライン引数を1個与えた場合
ファイルオープンに成功し、何かデータを読みこんだ(fgetsが成功した)場合は、match_strの45~53行目の無限ループにはまります。
この時、27行目で出力しようとした内容はバッファがフラッシュされず、出力されないかもしれません。
- 実行コマンド名を除くコマンドライン引数が1個でない場合
15行目で実行が終了します。
Re: 結果が出ません。
Posted: 2016年2月13日(土) 19:22
by みけCAT
コード:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define str 300
int match_str(char *a, char *b);
int main(int argc,char *argv[])
{
FILE *fp;
char a[str] = {'\0'};
int cnt,num; /* cntを初期化していない */
if(argc != 2) /* 条件が不自然。argc[2]を利用しているので、argc != 3の方が適するのでは? */
{
return 1;
}
fp = fopen(argv[1],"r");
if(fp == NULL)
{
printf("ファイル %s が見つかりません\n",argv[1]);
return 1;
}
while(fgets(a,str,fp)!= NULL)
{
cnt++;
printf("%d\t:",cnt); /* 初期化していない自動変数の値を使っているのでundefined behavior */
num = match_str(a,argv[2]);
if(num == 1)
{
printf("%s",a);
}
}
fclose(fp);
printf("\n");
/* 新しいCでは大丈夫だが、戻り値を明示的に書いたほうがわかりやすい */
}
int match_str(char *a, char *b)
{
int i = 0;
int j = 0;
int maxa,maxb;
int flg = 0;
while(flg == 0)
{
if(a[i] == '\0')
{
maxa = i;
flg == 1; /* 意味のない文。flg = 1;の間違いでは?そもそも素直にfor(;;)でループしてここではbreak;でいいのでは? */
}
i++;
}
i = 0;
/* ここに来るということはflgが0でなくなったということだが、flgを初期化していない */
while(flg == 0)
{
if(b[i] == '\0')
{
maxb = 0; /* 詳しい仕様を追っていないが、iではなく0でいいのか? */
flg = 1; /* 同様に素直にwhile(flg == 0)ではなくfor(;;)を使ってここではbreak;でいいのでは? */
}
i++;
}
for(i=0;i<maxa;i++)
{
if(0==strncmp(&a[i],&b[j],1)) /* 素直にa[i] == b[j]でいいのでは? */
{
/* maxbが初期化されていない場合はundefined behavior */
/* maxb=0の場合はjがオーバーフローしなければ成り立たない(符号付き整数のオーバーフローはundefined behavior)が、
* j++;は高々maxa回(<=INT_MAX回)しか実行されず、jの初期値は0なので、オーバーフローは
* (デバッガや宇宙線などによるメモリの書き換えや、処理系の不都合による誤動作が無い)通常の実行では起こらない。
* よって、この式は通常の実行では常に偽である。 */
if(maxb-1 == j)
{
return 1;
}
else
{
j++;
}
}
}
return 0;
}
Re: 結果が出ません。
Posted: 2016年2月13日(土) 19:35
by pazumon_2525
$ ./a.exe a.c printf
1 :2 :3 :4 :5 :6 :7 :8 :9 :10 :11 :12 :13 :14 :15 :16 :17 :18 :19 :20 :21 :22 :23 :24 : printf("[%d][%d]\n",y,x);
25 :26 :27 :28 :29 :30 :31 :32 :33 :34 :35 :36 :37 :38 :39 :40 :41 :42 :43 :44 :45 :46 :47 :48 :49 :50 :51 :52 :53 :54 :55 :56 :57 :58 :59 :60 :61 :62 :63 :64 ://printf("a\n");
65 :66 :67 :68 :69 :70 :71 : //printf("d\n");
72 :73 :74 :75 :76 :77 :78 :79 : //printf("b\n");
80 :81 :82 :83 :84 :85 : //printf("c\n");
86 :87 :88 :89 :90 :91 :92 :93 : //printf("c\n");
94 :95 :96 :97 :98 :99 : //printf("b\n");
100 :101 :102 :103 :104 :105 :106 :107 : //printf("d\n");
108 :109 :110 :111 :112 :113 : //printf("a\n");
114 :115 :116 :117 :118 :119 :120 :121 :
結果がこうなってしまいます。
cntも列として表示させるにはどうしたらよいですか?
Re: 結果が出ません。
Posted: 2016年2月13日(土) 20:02
by hoge
Re: 結果が出ません。
Posted: 2016年2月13日(土) 23:11
by pazumon_2525
$ ./a.exe printf a.c
24: printf("[%d][%d]\n",y,x);
64: //printf("a\n");
71: //printf("d\n");
79: //printf("b\n");
85: //printf("c\n");
93: //printf("c\n");
99: //printf("b\n");
107: //printf("d\n");
113: //printf("a\n");
列の処理と結果はうまくできましたが、上のようにズレと大きな空白ができてしまいます。
どうしたら改正しますですか?
初心的な質問ですみません。
Re: 結果が出ません。
Posted: 2016年2月13日(土) 23:14
by pazumon_2525
ソースです。
コード:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define str 300
int match_str(char *a, char *b);
int main(int argc,char *argv[])
{
FILE *fp;
char a[str] = {'\0'};
int cnt = 0,num;
if(argc != 3)
{
return 1;
}
fp = fopen(argv[2],"r");
if(fp == NULL)
{
printf("ファイル %s が見つかりません\n",argv[1]);
return 1;
}
while(fgets(a,str,fp)!= NULL)
{
cnt++;
num = match_str(a,argv[1]);
if(num == 1)
{
printf("%d:%s",cnt,a);
}
}
fclose(fp);
}
int match_str(char *a, char *b)
{
int i = 0;
int j = 0;
int maxa,maxb;
int flg = 0;
while(flg == 0)
{
if(a[i] == '\0')
{
maxa = i;
flg = 1;
}
i++;
}
i = 0;
flg = 0;
while(flg == 0)
{
if(b[i] == '\0')
{
maxb = i;
flg = 1;
}
i++;
}
for(i=0;i<maxa;i++)
{
if(a[i] == b[j])
{
if(maxb-1 == j)
{
return 1;
}
else
{
j++;
}
}
}
return 0;
}
Re: 結果が出ません。
Posted: 2016年2月13日(土) 23:35
by みけCAT
pazumon_2525 さんが書きました:列の処理と結果はうまくできましたが、上のようにズレと大きな空白ができてしまいます。
入力の通り出力されているだけではないですか?
今のコードが、このような大量の全角スペースを生成するとは考えられません。
pazumon_2525 さんが書きました:どうしたら改正しますですか?
適当な変換プログラムを書いて使うか、空白がない入力を与えたらいいと思います。
Re: 結果が出ません。
Posted: 2016年2月13日(土) 23:38
by みけCAT
pazumon_2525 さんが書きました:列の処理と結果はうまくできましたが、上のようにズレと大きな空白ができてしまいます。
どうしたら改正しますですか?
まず、入力例とそれに対する欲しい出力を教えてください。
例だけでなく、きちんと定義された変換規則を教えていただけるとさらにいいです。
Re: 結果が出ません。
Posted: 2016年2月13日(土) 23:40
by box
match_str()のかわりに、標準関数のstrstr()あたりを使う方が
簡単ではないですか?
Re: 結果が出ません。
Posted: 2016年2月13日(土) 23:56
by みけCAT
box さんが書きました:match_str()のかわりに、標準関数のstrstr()あたりを使う方が
簡単ではないですか?
このmatch_str()は第二引数が第一引数の連続とは限らない部分文字列になっているかを判定する関数であるので、
strstr()で同じ働きを再現することは難しいと思います。
例えば、
コード:
match_str("kanozyogafuraguwooraretara", "gaworare")
は1ですが、
コード:
!!strstr("kanozyogafuraguwooraretara", "gaworare")
は0となります。
むしろ、match_str()の引数の型をconst char*にし、前半を標準関数のstrlen()に置き換える方がいいでしょう。