Cで、文字列検索のコードを書いたのですが、想定外の動作をします


ABC295 のA問題を解くコードをCで書いてみました。  
それが末尾のコードなのですが、まず、他のオンラインコンパイラ(Paiza
IO)ではエラーにならないコードがAtCoderに提出するとREになっており、またテストケースの一つ(test_15)は、Paiza
IOではエラーにはならないのですが(AtCoderではREになる)、下記のデバッグ出力の実行結果のように、最初のtheのところで"Yes"を出力して終了するべきものが、次の"and"まで行っています。原因が分かりません。

[code]

    testcase_15
    100
    the and that the you you the not that that you that you you the and not not and that the you not that and you that the not the not the you you the that that you and you and you the that and and and that not and and that that and that and not the and that the that not and and the and the not the you the the and and not the the not the that the the the the that the not you and and not that the not that that not that you
    
[/code]

実行結果(19行以下のデバッグ出力をオンにしたもの)

[code]

    cnt=1 wl=3: the
    cnt=2 wl=3: and
    Yes
    
[/code]

ソースコード

[code]

    int readint(char *s);
    #include<stdio.h>
    #include<stdlib.h>
    #define N 5010
    int main(void){
        char* s=(char*)malloc(sizeof(char)*3);
        fgets(s,5,stdin);
        int n=readint(s);
        //printf("%d\n",n);
        char* s2=(char*)malloc(sizeof(char)*N);
        fgets(s2,N,stdin);
        //printf("%s\n",s2);
        const char* list[5]={"and", "not", "that", "the", "you"};
        int wsz[5]={3,3,4,3,3}; 
        int i=0,cnt=0,wl=0;
        while(cnt<n && i<N){
    //        printf("%s\n",s2+i);
            while(*(s2+i+wl)>=97 && *(s2+i+wl)<=122)wl++;
            cnt++;
    /*        printf("cnt=%d wl=%d: ",cnt,wl);
            for(int j=0;j<wl;j++){
                printf("%c",*(s2+i+j));
            }
            printf("\n");*/
            for(int k=0;k<5;k++){
                if (wl!=wsz[k])break;
                int flag=1,j=0;
                for(;j<wl;j++){
                    if(*(s2+i+j)!=list[k][j]){
                        flag=0; break;
                    }
                }
                if(j==wl){
                    printf("%s\n","Yes");
                    exit(0);
                }
            }
            i+=(wl+1); wl=0;
            }
        printf("No\n");
        return 0;
    }
    int readint(char *s){
        int i=0,ret=0;
        while(*(s+i)>=48 && *(s+i)<=57){
    //        printf("%d\n",*(s+i));
            ret*=10;
            ret+=*(s+i)-48;
            i+=1;
        }
        return ret;
    }
    
[/code]




> 下記のデバッグ出力の実行結果のように、最初のtheのところで"Yes"を出力して終了するべきものが、次の"and"まで行っています。

この理由は、変数`k`に対するforループ中の処理、文字長の判定をしているところの処理が間違っているからと思います。

[code]

            for(int k=0;k<5;k++){
                if (wl!=wsz[k])break;
                /* 以下、略 */
    
[/code]

forループで、配列`list`の全要素に対し比較を行う必要があるのであれば、`break`ではなく、`continue`として、ループを継続する必要があると思います。つまり、以下のようにすれば良いと思います。

[code]

            for(int k=0;k<5;k++){
                if (wl!=wsz[k]) continue;
                /* 以下、略 */
    
[/code]

＃質問に対する回答であり、解いておられる元の問題の解答ではないことをご了承ください。




> 下記のデバッグ出力の実行結果のように、最初のtheのところで"Yes"を出力して終了するべきものが、次の"and"まで行っています。

この理由は、変数`k`に対するforループ中の処理、文字長の判定をしているところの処理が間違っているからと思います。

[code]

            for(int k=0;k<5;k++){
                if (wl!=wsz[k])break;
                /* 以下、略 */
    
[/code]

forループで、配列`list`の全要素に対し比較を行う必要があるのであれば、`break`ではなく、`continue`として、ループを継続する必要があると思います。つまり、以下のようにすれば良いと思います。

[code]

            for(int k=0;k<5;k++){
                if (wl!=wsz[k]) continue;
                /* 以下、略 */
    
[/code]

＃質問に対する回答であり、解いておられる元の問題の解答ではないことをご了承ください。

