ページ 11

C言語の問題に関しての質問です

Posted: 2013年8月06日(火) 10:28
by リテン
あなたは N 個の指輪を持っている.どの指輪にも,アルファベットの大文字 10 文字からなる文字列が刻印されている.指輪には文字列の最初と最後がつながった形で文字が刻印されている.指輪に刻印された文字列を逆順に読む心配はない.
探したい文字列が与えられたとき,その文字列を含む指輪が何個あるかを求めるプログラムを作成せよ.

という問題なのですが、1行目に文字列、二行目に指輪の個数、三行目以降に刻印が入力されます
文字列のプログラムは初めて書くので、どこが間違っているか教えて下さいm(_ _)m

コード:

#include <stdio.h>
#include <stdlib.h>
  
int main(){
char moji[11]={'\0'},moji2[21]={'\0'},moji3[11]={'\0'};
int n,i,j,k,kai=0;
  
gets(moji);
scanf("%d",&n);
for(i=0;i<n;i++){
gets(moji2);
for(j=0;j<10;j++){
moji3[j]=moji2[j];
}
moji3[10]='\0';
for(k=0;moji3[k]!='\0';k++){
moji2[k+10]=moji3[k];
}
moji2[20]='\0';
for(j=0;j<10;j++){
for(k=0;moji[k]==moji2[k+j];k++){
if(moji[k+1]=='\0'){
kai++;
break;
}
}
if(moji[k+1]=='\0')break;
}
}
printf("%d\n",kai);
  
return 0;
}

Re: C言語の問題に関しての質問です

Posted: 2013年8月06日(火) 10:31
by みけCAT
インデントをしていただくと、コードが見やすくなります。

コード:

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

int main(){
	char moji[11]={'\0'},moji2[21]={'\0'},moji3[11]={'\0'};
	int n,i,j,k,kai=0;

	gets(moji);
	scanf("%d",&n);
	for(i=0;i<n;i++){
		gets(moji2);
		for(j=0;j<10;j++){
			moji3[j]=moji2[j];
		}
		moji3[10]='\0';
		for(k=0;moji3[k]!='\0';k++){
			moji2[k+10]=moji3[k];
		}
		moji2[20]='\0';
		for(j=0;j<10;j++){
			for(k=0;moji[k]==moji2[k+j];k++){
				if(moji[k+1]=='\0'){
					kai++;
					break;
				}
			}
			if(moji[k+1]=='\0')break;
		}
	}
	printf("%d\n",kai);

	return 0;
}
この問題ですか?
http://judge.u-aizu.ac.jp/onlinejudge/d ... sp?id=0555

Re: C言語の問題に関しての質問です

Posted: 2013年8月06日(火) 10:38
by みけCAT
scanfで改行を読み取っておらず、次のgetsでその改行のみを読み込んでいるため、
最後の指輪の文字列を処理していないようです。
無理に危険とされるgetsを使用せず、素直にscanfで文字列を読み込めば大丈夫だと思います。

Re: C言語の問題に関しての質問です

Posted: 2013年8月06日(火) 11:23
by リテン
ご指摘ありがとうございます
はい、その問題です。
直してみましたが……それでもまだダメみたいです

コード:

#include <stdio.h>

int main(){
   char moji[11]={'\0'},moji2[21]={'\0'},moji3[11]={'\0'};
   int n,i=0,j,k,kai=0,t;

   while(1){
     scanf("%c", &moji[i]);
     if(moji[i]=='\n')break;
     i++;
   }
   moji[i]='\0';
   scanf("%d",&n);
   for(i=0;i<n;i++){
     scanf("%c", &moji2[0]);
     scanf("%c", &moji2[1]);
     scanf("%c", &moji2[2]);
     scanf("%c", &moji2[3]);
     scanf("%c", &moji2[4]);
     scanf("%c", &moji2[5]);
     scanf("%c", &moji2[6]);
     scanf("%c", &moji2[7]);
     scanf("%c", &moji2[8]);
     scanf("%c", &moji2[9]);
     moji2[10]='\0';
     for(j=0;moji2[j]!='\0';j++){
         moji3[j]=moji2[j];
     }
     moji3[j]='\0';
     for(k=0;moji3[k]!='\0';k++,j++){
       moji2[j]=moji3[k];
     }
     moji2[j]='\0';
     for(j=0;j<10;j++){
       for(k=0;moji[k]==moji2[k+j];k++){
         if(moji[k+1]=='\0'){
         kai++;
         break;
         }
       }
     if(moji[k+1]=='\0')break;
     }
    }
printf("%d\n",kai);

return 0;
}


Re: C言語の問題に関しての質問です

Posted: 2013年8月06日(火) 11:25
by みけCAT
%cではだめです。%sを使ってください。

Re: C言語の問題に関しての質問です

Posted: 2013年8月06日(火) 11:42
by リテン
それだと配列の各要素にデータを入力できないのではないでしょうか

Re: C言語の問題に関しての質問です

Posted: 2013年8月06日(火) 11:46
by みけCAT
では、実験しましょう。

コード:

#include <stdio.h>

int main(void) {
    char test[100];
    int i;
    scanf("%s",test);
    for(i=0;test[i];i++)printf("test[%d]=%c\n",i,test[i]);
    return 0;
}
このコードを実行し、標準入力に何か文字列を入力してみてください。

この問題の場合、文字列が空白を含まないので大丈夫なはずです。

Re: C言語の問題に関しての質問です

Posted: 2013年8月06日(火) 11:58
by リテン
家にプログラムを実行できる環境が無いので…
しかしこれでも正解になりません

コード:

#include <stdio.h>
 
int main(){
char moji[11]={'\0'},moji2[21]={'\0'},moji3[11]={'\0'};
int n,i=0,j,k,kai=0,t;
 
scanf("%s",moji);
scanf("%d",&n);
for(i=0;i<n;i++){
scanf("%s",moji2);
for(j=0;moji2[j]!='\0';j++){
moji3[j]=moji2[j];
}
moji3[j]='\0';
for(k=0;moji3[k]!='\0';k++,j++){
moji2[j]=moji3[k];
}
moji2[j]='\0';
for(j=0;j<10;j++){
for(k=0;moji[k]==moji2[k+j];k++){
if(moji[k+1]=='\0'){
kai++;
break;
}
}
if(moji[k+1]=='\0')break;
}
}
printf("%d\n",kai);
 
return 0;
}


Re: C言語の問題に関しての質問です

Posted: 2013年8月06日(火) 12:02
by みけCAT
インデントをしない理由はありますか?

元のコードで

コード:

moji2[k+10]=moji3[k];
となっていた部分が

コード:

moji2[j]=moji3[k];
に変わっていて、そのせいで間違いになっていると思います。
リテン さんが書きました:家にプログラムを実行できる環境が無いので…
Ideoneというサイトで、C言語などのコードを標準入力を指定して実行することができます。
http://ideone.com/

Re: C言語の問題に関しての質問です

Posted: 2013年8月06日(火) 12:12
by リテン
メモ帳で作っているので一々インデントすると修正に時間がかかるんです
これでもできませんでした

コード:

#include <stdio.h>

int main(){
   char moji[11]={'\0'},moji2[21]={'\0'},moji3[11]={'\0'};
   int n,i=0,j,k,kai=0,t;

   scanf("%s",moji);
   scanf("%d",&n);
   for(i=0;i<n;i++){
      scanf("%s",moji2);
      for(j=0;j<10;j++){
         moji3[j]=moji2[j];
      }
      moji3[10]='\0';
      for(k=0;moji3[k]!='\0';k++){
         moji2[k+10]=moji3[k];
      }
      moji2[20]='\0';
      for(j=0;j<10;j++){
          for(k=0;moji[k]==moji2[k+j];k++){
          if(moji[k+1]=='\0'){
             kai++;
             break;
            }
         }
        if(moji[k+1]=='\0')break;
        }
      }
   printf("%d\n",kai);

return 0;
}

Re: C言語の問題に関しての質問です

Posted: 2013年8月06日(火) 12:19
by みけCAT
探したい文字と今注目している部分の最後の1文字が一致しなかった場合、その先に一致する部分があっても、
kai++;する前にif(moji[k+1]=='\0')break;によってjのループを抜けてしまうようです。
単純にkの位置だけでなく、見つかったかどうかのフラグで管理するといいでしょう。
もしくは、見つかったkai++;の部分でj=10;とする、という方法もあります。

撃墜ケース

コード:

AA
1
ABBBBAABBB

Re: C言語の問題に関しての質問です

Posted: 2013年8月06日(火) 12:50
by リテン
これでもダメみたいです・・・

コード:

#include <stdio.h>
 
int main(){
   char moji[11]={'\0'},moji2[21]={'\0'},moji3[11]={'\0'};
   int n,i=0,j,k,kai=0,t;
 
   scanf("%s",moji);
   scanf("%d",&n);
   for(i=0;i<n;i++){
      scanf("%s",moji2);
      for(j=0;j<10;j++){
         moji3[j]=moji2[j];
      }
      moji3[10]='\0';
      for(k=0;moji3[k]!='\0';k++){
         moji2[k+10]=moji3[k];
      }
      moji2[20]='\0';
      for(j=0;j<10;j++){
          for(k=0;moji[k]==moji2[k+j];k++){
        if(moji[k+1]=='\0'){
             kai++;
             j=10;
        }
      }
      }
      }
   printf("%d\n",kai);
 
return 0;
}

Re: C言語の問題に関しての質問です

Posted: 2013年8月06日(火) 13:31
by みけCAT
すいません、これはかなり厄介そうです。
出力される答えがあっているのに、WAと判定されているように見えます。
自分のソースコードはACになったので、ジャッジエラーではないようです。
どうしましょう…?

Re: C言語の問題に関しての質問です

Posted: 2013年8月06日(火) 13:50
by non
ジャッジの詳細で、ジャッジデータテストケースを確認することはできないのですか?
私、やったことがないので、わかりませんが。ヘルプを見ると確認できるようなので。

Re: C言語の問題に関しての質問です

Posted: 2013年8月06日(火) 13:55
by みけCAT
non さんが書きました:ジャッジの詳細で、ジャッジデータテストケースを確認することはできないのですか?
問題にもよりますが、この問題ではできるようですね。

Re: C言語の問題に関しての質問です

Posted: 2013年8月06日(火) 14:12
by みけCAT
AOJの環境であるgcc4.6.3でコンパイルするとおかしくなることがわかりました。
さらに、同じgcc4.6.3でも-O2オプションの有無で結果が変わります。
Ideoneでは問題ないのに、なぜでしょうか…?
とりあえず、文字列を入れる配列を大きめに取ってみてください。

【追記】
配列を大きめにしても、-O2ありとなしの結果は一致しましたが、間違った答えが出ました。

【さらに追記】
配列を大きめにした結果、なぜかIdeoneでもおかしくなってしまいました。
そんなはずはないと思いましたが、なんででしょうか?

Re: C言語の問題に関しての質問です

Posted: 2013年8月06日(火) 14:34
by みけCAT
わかりました。
j=10;の直後にbreak;をいれてください。
break;が無いとj=10になっているので、探したい文字列の長さが10の時は
NIL文字とNIL文字を比較してしまってどんどんkaiの値が増えていくようです。
Ideoneで答えが合っていたのは、たまたまNIL文字の次が不定の値で一致しなかったからでしょう。

Re: C言語の問題に関しての質問です

Posted: 2013年8月06日(火) 16:35
by リテン
!!
j=10;の直後にbreak文を入れるとACになりました!
ありがとうございます!!