cgiの動作が停止してしまいます

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
blade

cgiの動作が停止してしまいます

#1

投稿記事 by blade » 13年前

以下のプログラム(sample.c)を実行形式の.cgiにしてブラウザ上で動かしたいと考えています。
前のページで受け取った文字列の入力を受け取ってそれを処理して表示させるプログラムなのですが、1つ問題があり、
130行目のstrcat_sで引数3のaを参照すると
ブラウザ上で動く際に
sample.cgiは動作を停止しました
となってしまいます。
例えばその引数3をwordtmp2にしたときなどは動作停止しません。
また、コマンドプロンプトでsample.exeを動かした時には何の問題もなく通るのですがcgiだと動作が停止する原因がわかりません。

ちなみにこのプログラム以外の.cgiは動いているため、サーバの設定が間違っているということはないと思います(ローカルホスト使用)。

コード:

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

#define MAXLEN 3000  //文字列の長さ

// フォームから入力された日本語をデコードするプログラム
// 参考:「C言語道場」
//http://vapour.s22.xrea.com/clangdojo/index.php?assosiative_array.c
int decode(char *inBuf );


//文字列を置換する。 buf の中の mae を ato にする。成功=1 失敗=0
//参考:「C言語:文字列をいじる」
//www.geocities.jp/debu0510/personal/c_moji.html
int strrep(char *buf, char *mae, char *ato);



int main (int argc, char **argv)
{
    typedef struct{
        char* base; //単語の原型
        int id; //単語の・・
        char *pos; //単語の品詞
        char arg; //単語の引数の・・
    }_token;

    _token p;
    char buf[256];
    char input[MAXLEN];
    char input2[MAXLEN];
    char input3[MAXLEN];
    int flag = 0;         //同義語があるかどうかのフラグ
    FILE *fp_input;
    char wordtmp[512];
    char wordtmp2[512];
    unsigned int i, j;
    unsigned int size=10;
    char data[256]; //単語のデータを格納
    FILE *fp2; //fp2は入力ファイル
    errno_t error;
    char* ctx;
    char nokori[MAXLEN];  //残りの文章
    char ch;
    char q[MAXLEN];
    char *a[MAXLEN];

    /* 入力データの取得。デコードおよび切り離しも含める */
    for (i = 0; (ch = getchar()) != EOF; i++) {
        if (ch == '\r' || ch == '\n'){
            i--;
            break;
            //q[i]=ch;
        }
        else
            q[i] = ch;
        //i--;
    }
    q[i+1] = '\0';
    decode(q);
    getstring(q, "string", input3);
    //getstring(q, "st1", st1);
    getstring(q, "nokori", nokori);

    a[0]=strtok(input3, " ");
    for(i=1;a[i-1]!=NULL;i++){
        a[i] = strtok( NULL," ." );
        if(a[i]==NULL)break;
        //puts(a[i]);
    }
/************ 処理 ***************/

/************ 処理***************/

    /************ cgi出力スペース ***************/
    printf("Content-type:text/html\n\n");
    printf("<HTML><HEAD>\n");
    printf("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=Shift_JIS\">\n");
    printf("<TITLE>自然言語ツール</TITLE>\n");
    printf("</HEAD>\n<BODY>\n");
    printf("<FORM METHOD=\"POST\" ACTION=\"../../dgg/Debug/t0.cgi\">");

    printf("<input type=hidden name=string value=%s>",input3); //入力文章
    //printf("<input type=hidden name=nokori value=%s>",nokori); //残りの文章
    //printf("%s",nokori);


    for(i = 0; i < size; ++i){
        while(fgets(data, sizeof(data), fp2) != NULL){

            p.base = strstr(data, "base");
            if(p.base==NULL)break;
            p.base = strtok_s((p.base)+6, "\"", &ctx);
            strcat(p.base, " ");
            // printf("原型は%sです、", p.base);

            p.pos = strstr(data, "pos");
            p.pos = strtok_s((p.pos)+5, "\"", &ctx);
            // printf("品詞は%sだ\n", p.pos);



            //    }
            //}
            //fclose(fp2);




            for(j=0;j<MAXLEN;j++) input[j] = NULL;

          

            //指示語があれば対応する語句、語句の番号を格納する
            if((strncmp(p.pos, "PRP", 3) == 0) ){
                flag = 1;
                sprintf(wordtmp, "%s", p.base);
                sprintf(wordtmp2, " [[[%s]]] ", p.base);
                strcat(input, wordtmp);
                strcat(input2, wordtmp2);

            }
            else{
                //sprintf(wordtmp, "%s", p.pos);
                sprintf(wordtmp2, "%s", p.base);
                //strcat(input, wordtmp);
                if(a[i]!=NULL){ 
                    strcat_s(input2, sizeof(input2), a[i]);
                    strcat(input2, " ");
                };
            }

            /* }*/


        }
    }


    printf("<font size = 5>特定結果</font><br><br>\n");
    //printf("%s", input);
    printf("<hr><br>\n");

    if(flag == 1){ 
       
        printf("<textarea name=string rows=4 cols=50>%s</textarea><br><br>\n", input2);
        printf("<input type=hidden name=string value=%s>",input2); //次に使う文章
        printf("<hr><tt><font size = 5, color=red>%s</font></tt><br>\n", input);
        printf ("<hr><tt>書き換えが終わったら、下の「次へ」ボタンを押してください。</tt><br>\n");
    }

    else{
        printf("<input type=hidden name=string value=%s>",input3); //次に使う文章
        
    }

   
    printf ("<INPUT TYPE=SUBMIT VALUE=\"次へ\" >");
    printf("</FORM></BODY></HTML>\n");
    /*********************************************************/    


    fclose(fp2);

    return 0;	
}

/* フォームから入力された日本語をデコードするプログラム *
* 参考:「C言語道場」                                  */
int decode(char *inBuf ) {

    int i;
    int j;
    int n = strlen(inBuf);
    char decodeBuf[3];
    char c[MAXLEN];
    char outBuf[MAXLEN];

    j=0;

    for ( i=0; i<n; i++) {
        if (inBuf[i] == '%' ) {
            strncpy(decodeBuf, &inBuf[i+1], 2);
            decodeBuf[2] = 0x00;
            sscanf(decodeBuf, "%2x", &c);
            outBuf[ j++ ] = c[MAXLEN];
            i += 2;
        }
        else
            outBuf[j++] = inBuf[i];
    }
    outBuf[j] = 0x00;
    strcpy(inBuf, outBuf);
    return 0;

}

/* フォームからの入力を切り離すプログラム *
* 参考:「猫でも分かるプログラミング」   */
int getstring(char *src, char *element, char *dest)
{
    int len;
    char *data, *amp;
    char *temp;

    len = (int)strlen(src) + 1;
    temp = (char *)malloc(len);

    if (len >= MAXLEN) {
        free(temp);
        return -1;
    }

    strcpy(temp, src);

    data = strstr(temp, element);
    if(data == NULL) {
        strcpy(dest, "no element");
        free(temp);
        return -2;
    }

    len = (int)strlen(element) + 1;

    amp = strstr(data, "&");
    if (amp == NULL) {
        strcpy(dest, data + len);
        if (dest[0] == '\0') {
            strcpy(dest, "no data");
            free(temp);
            return 0;
        }
        free(temp);
        return 1;
    }
    data[(int)(amp-data)] = '\0';
    strcpy(dest, data + len);

    if (dest[0] == '\0') {
        strcpy(dest, "no data");
        free(temp);
        return 0;
    }

    free(temp);
    return 0;
}



//文字列を置換する。 buf の中の mae を ato にする。成功=1 失敗=0
//参考:「C言語:文字列をいじる」
int strrep(char *buf, char *mae, char *ato)
{
    char *mituke;
    size_t maelen, atolen;

    maelen = strlen(mae);
    atolen = strlen(ato);
    if (maelen == 0 || (mituke = strstr(buf, mae)) == NULL) return 0;
    memmove(mituke + atolen, mituke + maelen, strlen(buf) - (mituke + maelen - buf ) + 1);
    memcpy(mituke, ato, atolen);
    return 1;
}



アバター
h2so5
副管理人
記事: 2212
登録日時: 15年前
住所: 東京
連絡を取る:

Re: cgiの動作が停止してしまいます

#2

投稿記事 by h2so5 » 13年前

67行目

コード:

    a[0]=strtok(input3, " ");
    for(i=1;a[i-1]!=NULL;i++){
        a[i] = strtok( NULL," ." );
        if(a[i]==NULL)break;
        //puts(a[i]);
    }
この部分で5つのトークンに分割された場合、aの中身はこうなります。

a = { ポインタ, ポインタ, ポインタ, ポインタ, ポインタ, NULL, 不定, 不定, 不定, 不定 }

129行目

コード:

                if(a[i]!=NULL){ 
                    strcat_s(input2, sizeof(input2), a[i]);
                    strcat(input2, " ");
                };
この部分で「不定」の部分にアクセスしてしまう可能性があるんじゃないでしょうか。
オフトピック
C言語は標準の文字列操作が貧弱なので自然言語処理と相性が悪いです...

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: cgiの動作が停止してしまいます

#3

投稿記事 by softya(ソフト屋) » 13年前

ざっと見た感じaのiがループ条件のsize-1まで、ちゃんとポインタかNULLが入っている保証がないように見えます。
デバッグのためにprintf("%p",a);としてみればポインタ値を確認できるのでは? ※こういうデバッグの方法を常に考えましょう。

オフトピック
perlとかPHPで組めばこんな面倒は無いですね。高速性が必要なければperlで良いのでは?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

blade

Re: cgiの動作が停止してしまいます

#4

投稿記事 by blade » 13年前

回答有り難うございます。
お二方の仰る通り、不定のaにアクセスしていたからのようでした。

90行目のforループの条件を

コード:

 for(i = 0; a[i]!=NULL ; i++){
にしてこの点は解決しました。
softya(ソフト屋) さんが書きました: ざっと見た感じaのiがループ条件のsize-1まで、ちゃんとポインタかNULLが入っている保証がないように見えます。
デバッグのためにprintf("%p",a);としてみればポインタ値を確認できるのでは? ※こういうデバッグの方法を常に考えましょう。

これをやって気づけました。
今後使っていきたいと思います。

そしてすみません、また問題が発生しました。
148行目で

コード:

printf("<textarea name=string rows=4 cols=50>%s</textarea><br><br>\n", input2);
で処理した文字列を表示させる時、ブラウザ上で見るとテキストエリア内に
[[[she]]]
とだけ表示され、その後の文字列が表示されません。
(入力内容を"she loves him"とすると"[[[she ]]] loves [[[him]]]"と表示させたい)

これまた.exeをコマンドプロンプトで動かすと
<textarea name=string rows=4 cols=50>[[[she ]]] loves [[[him]]]</textarea><br><br>
とprintfされるのにどうしてこうなるのでしょうか。


オフトピック
C言語しか触れておらず、かつ私事ですが時間がなく、他の言語で新たに始められる余裕がないのですよね・・・

アバター
h2so5
副管理人
記事: 2212
登録日時: 15年前
住所: 東京
連絡を取る:

Re: cgiの動作が停止してしまいます

#5

投稿記事 by h2so5 » 13年前

input2は初期化されていないですよね。これまた内容が不定です。
122行目の時点で先頭がNULLでなければならないはずです。
オフトピック
C言語で書く時間 > 他の言語を覚える時間+他の言語で書く時間

blade

Re: cgiの動作が停止してしまいます

#6

投稿記事 by blade » 13年前

h2so5 さんが書きました:input2は初期化されていないですよね。これまた内容が不定です。
122行目の時点で先頭がNULLでなければならないはずです。
115行目に

コード:

memset(input2, '\0', sizeof(input2));
を追加しました。

しかし、これをしなくても実際コマンドプロンプトではinput2に欲しい内容が表示されていたため
なぜこれがcgiにしてブラウザ上で表示させると[[[she ]]]]だけになってしまうのかがわかりません。
オフトピック
そうなんですか∑(゚Д゚)ガーン

アバター
h2so5
副管理人
記事: 2212
登録日時: 15年前
住所: 東京
連絡を取る:

Re: cgiの動作が停止してしまいます

#7

投稿記事 by h2so5 » 13年前

コマンドプロンプトで実行したときは「偶然にも」input2の先頭がNULLだったからだと思います。
ポインタ関連のバグは時としておかしな挙動を引き起こします。
オフトピック
少なくともこのトピックのようなバグは起きません。
このような面倒が起きるのはC言語くらいです。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: cgiの動作が停止してしまいます

#8

投稿記事 by softya(ソフト屋) » 13年前

オフトピック
C言語でしっかりしたプログラムを書けるなら別ですが、文字列や配列の扱いが不安な現状だと私もPerlを覚えたほうが速いのでは? と思います。
Perlで書いたら凄く短いプログラムで書けそうです。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

blade

Re: cgiの動作が停止してしまいます

#9

投稿記事 by blade » 13年前

せっかくここまでやってきたのと、C言語の勉強のためとりあえずこのプログラムだけはこのままCでやりたいと思います。
h2so5 さんが書きました: ポインタ関連のバグは時としておかしな挙動を引き起こします。
ではこの問題は"おかしな挙動"なためどうにか解決することは不可能なのでしょうか。

blade

Re: cgiの動作が停止してしまいます

#10

投稿記事 by blade » 13年前

softya(ソフト屋) さんが書きました:
オフトピック
C言語でしっかりしたプログラムを書けるなら別ですが、文字列や配列の扱いが不安な現状だと私もPerlを覚えたほうが速いのでは? と思います。
Perlで書いたら凄く短いプログラムで書けそうです。
オフトピック
このプログラムは私がつくりたいツールの一部ですので、みなさんのおっしゃるとおり、次の機能からはperlで書いてみたいと思います。
これはさらにトピックから外れるのですが、perlでまた質問したい時はここではダメでしょうか。
C言語だとここでお世話になれるため、使っていたのも理由の一つだったため迷っています。
perlだとあまり活発な掲示板が見つからなく、わからなくなったとき困ってしまいます。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: cgiの動作が停止してしまいます

#11

投稿記事 by softya(ソフト屋) » 13年前

offtopicとも言えなくなってので。
こちらで質問しても大丈夫ですよ。

ただ、最近は私はPHPが多いのでPerlは大分忘れてますが他にもPerlが得意な人がいるので大丈夫でしょう。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

blade

Re: cgiの動作が停止してしまいます

#12

投稿記事 by blade » 13年前

ありがとうございます。perlに切り替えてからもまたお世話になります。

それから、やはりNo.6の問題は"おかしな挙動"ということで解決はできない問題なのでしょうか。
何度もすみません。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: cgiの動作が停止してしまいます

#13

投稿記事 by softya(ソフト屋) » 13年前

えーと、input2をクリアしても問題は再現するんでしょうか? 文章からそう読み取れなかったんですが。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

blade

Re: cgiの動作が停止してしまいます

#14

投稿記事 by blade » 13年前

書き方が悪かったです、すみません。
解決しませんでした。

先ほど115行目に

コード:

memset(input2, '\0', sizeof(input2));
を追加したと書きましたがそれだとforループの中なのでせっかく入れたwordtmpやaが毎回消えてしまったため
76行目に追加しました。

しかしあいも変わらずブラウザ上になると表示されないのは変わりませんでした。

アバター
h2so5
副管理人
記事: 2212
登録日時: 15年前
住所: 東京
連絡を取る:

Re: cgiの動作が停止してしまいます

#15

投稿記事 by h2so5 » 13年前

96行目で strcat にp.baseを指定する意味ってないですよね。常に最後に連結されるわけですから。
あとコマンドプロンプトの表示とブラウザのテキストエリアの表示では比較になりません。ブラウザ上で表示されるソースを比較してください。

blade

Re: cgiの動作が停止してしまいます

#16

投稿記事 by blade » 13年前

h2so5 さんが書きました:96行目で strcat にp.baseを指定する意味ってないですよね。常に最後に連結されるわけですから。
あとコマンドプロンプトの表示とブラウザのテキストエリアの表示では比較になりません。ブラウザ上で表示されるソースを比較してください。
そうでした、消しました。

比較するのは"何"と"ブラウザ上で表示されるソース"を比較するのでしょうか。この3つですか?

コマンドプロンプト
<textarea name=string rows=4 cols=50> [[]] it [[[it]]] he [[[he]]] </textarea><br><br>

テキストエリアの表示
[[]]

ブラウザ上で表示されるソース
<textarea name=string rows=4 cols=50> [[]] </textarea><br><br>

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: cgiの動作が停止してしまいます

#17

投稿記事 by softya(ソフト屋) » 13年前

最新の状況が再現できるソースコードを貼ってください。
なお、こちらのHTTPサーバーはapacheのため同じ状況が再現できるかは分かりません。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

blade

Re: cgiの動作が停止してしまいます

#18

投稿記事 by blade » 13年前

ソースコードを貼ります。
渡す入力は
string I+searches+it+which+he+seeks
です。
だいぶ汚くて申し訳ないですが、よろしくお願いします。

コード:

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

#define MAXLEN 3000  //文字列の長さ

// フォームから入力された日本語をデコードするプログラム
// 参考:「C言語道場」
//http://vapour.s22.xrea.com/clangdojo/index.php?assosiative_array.c
int decode(char *inBuf );


//文字列を置換する。 buf の中の mae を ato にする。成功=1 失敗=0
//参考:「C言語:文字列をいじる」
//www.geocities.jp/debu0510/personal/c_moji.html
int strrep(char *buf, char *mae, char *ato);


//フォームからの入力を切り離すプログラム
//参考:「猫でも分かるプログラミング」
//http://homepage2.nifty.com/c_lang/intro/no_82.htm
int getstring(char *src, char *element, char *dest);

int main (int argc, char **argv)
{
    typedef struct{
        char* base; //単語の原型
        int id; //単語の・・
        char *pos; //単語の品詞
        char arg; //単語の引数の・・
    }_token;

    _token p;
    char buf[256];
    char input0[MAXLEN];
    char input[MAXLEN];
    char input2[MAXLEN];
    char input3[MAXLEN];
    int flag = 0;         //同義語があるかどうかのフラグ
    FILE *fp_input;
    char wordtmp[512];
    char wordtmp2[512];
    unsigned int i, j;
    unsigned int size=10;
    char data[256]; //単語のデータを格納
    FILE *fp2; //fp2は入力ファイル
    errno_t error;
    char* ctx;
    char nokori[MAXLEN];  //残りの文章
    char ch;
    char q[MAXLEN];
    char *a[MAXLEN];

    memset(input0, '\0', sizeof(input0));
    memset(input3, '\0', sizeof(input3));
    /* 入力データの取得。デコードおよび切り離しも含める */
    for (i = 0; (ch = getchar()) != EOF; i++) {
        if (ch == '\r' || ch == '\n'){
            i--;
            break;
            //q[i]=ch;
        }
        else
            q[i] = ch;
        //i--;
    }
    q[i+1] = '\0';
    decode(q);
    getstring(q, "string", input3);
    //getstring(q, "st1", st1);
    getstring(q, "nokori", nokori);

    strcpy(input0, input3);
    while( strrep(input0, "フ", "+"));

    a[0]=strtok(input3, "+");
    for(i=1;a[i-1]!=NULL;i++){
        a[i] = strtok( NULL,"+" );
        if(a[i]==NULL)break;
        //puts(a[i]);
    }
   


    /********** ここから解析開始 ****************/

    if ((error = fopen_s(&fp2, "ccc.txt", "r")) !=0) {
        printf("file open error!!\n");
        exit(EXIT_FAILURE);	/* エラーの場合は通常、異常終了する */
    }

    memset(input, '\0', sizeof(input));
    memset(input2, '\0', sizeof(input2));
    /************ cgi出力スペース ***************/
    printf("Content-type:text/html\n\n");
    printf("<HTML><HEAD>\n");
    printf("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=Shift_JIS\">\n");
    printf("<TITLE>自然言語文ツール</TITLE>\n");
    printf("</HEAD>\n<BODY>\n");
    printf("<FORM METHOD=\"POST\" ACTION=\"../../dgg/Debug/t0.cgi\">");

    printf("<input type=hidden name=string value=%s>",input0); //入力文章
    //printf("<input type=hidden name=nokori value=%s>",nokori); //残りの文章
    //printf("%s",nokori);


    for(i = 0; a[i]!=NULL ; i++){
        while(fgets(data, sizeof(data), fp2) != NULL){

            p.base = strstr(data, "base");
            if(p.base==NULL)break;
            p.base = strtok_s((p.base)+6, "\"", &ctx);
            //strcat(p.base, " ");
            // printf("原型は%sです、", p.base);

            p.pos = strstr(data, "pos");
            p.pos = strtok_s((p.pos)+5, "\"", &ctx);
            // printf("品詞は%sだ\n", p.pos);



            //    }
            //}
            //fclose(fp2);




            //for(j=0;j<MAXLEN;j++) input[j] = NULL


            //指示語があれば対応する語句、語句の番号を格納する
            if((strncmp(p.pos, "PRP", 3) == 0) ){
                flag = 1;
                sprintf(wordtmp, "%s", p.base);
                sprintf(wordtmp2, " [[[%s]]] ", p.base);
                strcat(input, wordtmp);
                strcat(input2, wordtmp2);
                strcat(input2, " ");

            }
            else{
                //sprintf(wordtmp, "%s", p.pos);
                sprintf(wordtmp2, "%s", p.base);
                //strcat(input, wordtmp);

                strcat(input2, a[i]);
                strcat(input2, " ");

            }

            /* }*/


        }
    }

    //for(i=0;a[i]!=NULL;i++)printf("%sだ\n", a[i]);

    //ここからhtml出力内容
    printf("<font size = 5>指示語の特定結果</font><br><br>\n");
    //printf("%s", input);
    printf("<hr><br>\n");

    if(flag == 1){ //指示語があれば
        printf("<tt>指示語を[[[ ]]]で囲みました。指示語の指し示す内容に書き換えてください。<br></tt>\n");
        printf("<textarea name=string rows=4 cols=50>%s</textarea><br><br>\n", input2);
        printf("<input type=hidden name=string value=%s>",input2); //次に使う文章
        printf("<hr><tt><font size = 5, color=red>%s</font></tt><br>\n", input);
        printf ("<hr><tt>書き換えが終わったら、下の「次へ」ボタンを押してください。</tt><br>\n");
    }

    else{
        printf("<input type=hidden name=string value=%s>",input0); //次に使う文章
        printf ("<hr><tt>この文章中に指示語は無いので、次へを押してください。</tt><br>\n");
    }

    printf ("<br><br><a href=\"../../sizigohint.html\" target=\"_blank\">この画面のヒント</a></li><br><br>");
    printf ("<INPUT TYPE=SUBMIT VALUE=\"次へ\" >");
    printf("</FORM></BODY></HTML>\n");
    /*********************************************************/    


    fclose(fp2);

    return 0;	
}

/* フォームから入力された日本語をデコードするプログラム *
* 参考:「C言語道場」                                  */
int decode(char *inBuf ) {

    int i;
    int j;
    int n = strlen(inBuf);
    char decodeBuf[3];
    char c[MAXLEN];
    char outBuf[MAXLEN];

    j=0;

    for ( i=0; i<n; i++) {
        if (inBuf[i] == '%' ) {
            strncpy(decodeBuf, &inBuf[i+1], 2);
            decodeBuf[2] = 0x00;
            sscanf(decodeBuf, "%2x", &c);
            outBuf[ j++ ] = c[MAXLEN];
            i += 2;
        }
        else
            outBuf[j++] = inBuf[i];
    }
    outBuf[j] = 0x00;
    strcpy(inBuf, outBuf);
    return 0;

}

/* フォームからの入力を切り離すプログラム *
* 参考:「猫でも分かるプログラミング」   */
int getstring(char *src, char *element, char *dest)
{
    int len;
    char *data, *amp;
    char *temp;

    len = (int)strlen(src) + 1;
    temp = (char *)malloc(len);

    if (len >= MAXLEN) {
        free(temp);
        return -1;
    }

    strcpy(temp, src);

    data = strstr(temp, element);
    if(data == NULL) {
        strcpy(dest, "no element");
        free(temp);
        return -2;
    }

    len = (int)strlen(element) + 1;

    amp = strstr(data, "&");
    if (amp == NULL) {
        strcpy(dest, data + len);
        if (dest[0] == '\0') {
            strcpy(dest, "no data");
            free(temp);
            return 0;
        }
        free(temp);
        return 1;
    }
    data[(int)(amp-data)] = '\0';
    strcpy(dest, data + len);

    if (dest[0] == '\0') {
        strcpy(dest, "no data");
        free(temp);
        return 0;
    }

    free(temp);
    return 0;
}



//文字列を置換する。 buf の中の mae を ato にする。成功=1 失敗=0
//参考:「C言語:文字列をいじる」
int strrep(char *buf, char *mae, char *ato)
{
    char *mituke;
    size_t maelen, atolen;

    maelen = strlen(mae);
    atolen = strlen(ato);
    if (maelen == 0 || (mituke = strstr(buf, mae)) == NULL) return 0;
    memmove(mituke + atolen, mituke + maelen, strlen(buf) - (mituke + maelen - buf ) + 1);
    memcpy(mituke, ato, atolen);
    return 1;
}


ccc.txt

コード:

0	1	tok id="t0" cat="N" pos="PRP" base="i" lexentry="[<NP.no3sg.nom>]" pred="noun_arg0"

2	8	tok id="t1" cat="V" pos="VBP" base="search" lexentry="[NP.nom<V.bse>NP.accNP.acc]-no_singular3rd_verb_rule" pred="verb_arg123" tense="present" aspect="none" type="none" voice="active" aux="minus" arg1="c1" arg2="c5" arg3="c8"

9	11	tok id="t2" cat="N" pos="PRP" base="it" lexentry="[<NP.3sg>]" pred="noun_arg0"

12	17	tok id="t3" cat="N" pos="WDT" base="which" lexentry="[<NP.3sg^[NP]>]" pred="noun_arg0"

18	20	tok id="t4" cat="N" pos="PRP" base="he" lexentry="[<NP.3sg.nom>]" pred="noun_arg0"

21	26	tok id="t5" cat="V" pos="VBZ" base="seek" lexentry="[NP.nom<V.bse>NP.acc]-movement_rule-singular3rd_verb_rule" pred="verb_arg12" tense="present" aspect="none" type="none" voice="active" aux="minus" arg1="c10" arg2="c8"




アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: cgiの動作が停止してしまいます

#19

投稿記事 by softya(ソフト屋) » 13年前

渡す入力ってなんですか?
http://localhost/xx.cgi?string=I+search ... h+he+seeks
じゃなくてでしょうか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

blade

Re: cgiの動作が停止してしまいます

#20

投稿記事 by blade » 13年前

すみません、あまり理解していないのですが、前のページの入力フォームで入力した文字列が、名前がstring、その内容がI+search+it+which+he+seeks
という意味です。

<input type=hidden name=string value=I+search+it+which+he+seeks<hr><tt>

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: cgiの動作が停止してしまいます

#21

投稿記事 by softya(ソフト屋) » 13年前

前にも書きましたが工夫して状況を把握するようにしないと、どんなプログラムでもデバッグできません。
デバッグの情報を出してみたので、自分で直してみてください(post先は変えたのでまずかったら直してください)

コード:

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

#define MAXLEN 3000  //文字列の長さ

// フォームから入力された日本語をデコードするプログラム
// 参考:「C言語道場」
//http://vapour.s22.xrea.com/clangdojo/index.php?assosiative_array.c
int decode( char *inBuf );


//文字列を置換する。 buf の中の mae を ato にする。成功=1 失敗=0
//参考:「C言語:文字列をいじる」
//www.geocities.jp/debu0510/personal/c_moji.html
int strrep( char *buf, char *mae, char *ato );


//フォームからの入力を切り離すプログラム
//参考:「猫でも分かるプログラミング」
//http://homepage2.nifty.com/c_lang/intro/no_82.htm
int getstring( char *src, char *element, char *dest );

int main ( int argc, char **argv ) {
	typedef struct {
		char* base; //単語の原型
		int id; //単語の・・
		char *pos; //単語の品詞
		char arg; //単語の引数の・・
	} _token;

	_token p;
	char buf[256];
	char input0[MAXLEN];
	char input[MAXLEN];
	char input2[MAXLEN];
	char input3[MAXLEN];
	int flag = 0;         //同義語があるかどうかのフラグ
	FILE *fp_input;
	char wordtmp[512];
	char wordtmp2[512];
	unsigned int i, j;
	unsigned int size = 10;
	char data[256]; //単語のデータを格納
	FILE *fp2; //fp2は入力ファイル
	errno_t error;
	char* ctx;
	char nokori[MAXLEN];  //残りの文章
	char ch;
	char q[MAXLEN];
	char *a[MAXLEN];

	printf( "Content-type:text/html\n\n" );
	printf( "<HTML><HEAD>\n" );
	printf( "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=Shift_JIS\">\n" );
	printf( "<TITLE>自然言語文ツール</TITLE>\n" );
	printf( "</HEAD>\n<BODY>\n" );
	
	memset( input0, '\0', sizeof( input0 ) );
	memset( input3, '\0', sizeof( input3 ) );
	/* 入力データの取得。デコードおよび切り離しも含める */
	for ( i = 0; ( ch = getchar() ) != EOF; i++ ) {
		if ( ch == '\r' || ch == '\n' ) {
			i--;
			break;
			//q[i]=ch;
		} else
			q[i] = ch;
			printf("%c",ch );
		//i--;
	}
	q[i + 1] = '\0';
	
	decode( q );
	getstring( q, "string", input3 );
	//getstring(q, "st1", st1);
	getstring( q, "nokori", nokori );

	strcpy( input0, input3 );
	while( strrep( input0, "フ", "+" ) );

	a[0] = strtok( input3, "+" );
	for( i = 1; a[i - 1] != NULL; i++ ) {
		a[i] = strtok( NULL, "+" );
		if( a[i] == NULL )break;
		//puts(a[i]);
	}



	/********** ここから解析開始 ****************/

	if ( ( error = fopen_s( &fp2, "ccc.txt", "r" ) ) != 0 ) {
		printf( "file open error!!\n" );
		exit( EXIT_FAILURE ); /* エラーの場合は通常、異常終了する */
	}

	memset( input, '\0', sizeof( input ) );
	memset( input2, '\0', sizeof( input2 ) );
	/************ cgi出力スペース ***************/
	printf( "<FORM METHOD=\"POST\" ACTION=\"./t0.cgi\">" );

	printf( "<input type=hidden name=string value=%s>", input0 ); //入力文章
	//printf("<input type=hidden name=nokori value=%s>",nokori); //残りの文章
	//printf("%s",nokori);

	printf("input0=%s<br>\n",input0);
	printf("input3=%s<br>\n",input3);

	for( i = 0; a[i] != NULL ; i++ ) {
		while( fgets( data, sizeof( data ), fp2 ) != NULL ) {

			p.base = strstr( data, "base" );
			if( p.base == NULL )break;
			p.base = strtok_s( ( p.base ) + 6, "\"", &ctx );
			//strcat(p.base, " ");
			// printf("原型は%sです、", p.base);

			p.pos = strstr( data, "pos" );
			p.pos = strtok_s( ( p.pos ) + 5, "\"", &ctx );
			// printf("品詞は%sだ\n", p.pos);



			//    }
			//}
			//fclose(fp2);




			//for(j=0;j<MAXLEN;j++) input[j] = NULL


			//指示語があれば対応する語句、語句の番号を格納する
			if( ( strncmp( p.pos, "PRP", 3 ) == 0 ) ) {
				flag = 1;
				sprintf( wordtmp, "%s", p.base );
				sprintf( wordtmp2, " [[[%s]]] ", p.base );
				strcat( input, wordtmp );
				strcat( input2, wordtmp2 );
				strcat( input2, " " );

			} else {
				//sprintf(wordtmp, "%s", p.pos);
				sprintf( wordtmp2, "%s", p.base );
				//strcat(input, wordtmp);

				strcat( input2, a[i] );
				strcat( input2, " " );

			}
			printf("input2=%s<br>\n",input2);

			/* }*/


		}
	}

	//for(i=0;a[i]!=NULL;i++)printf("%sだ\n", a[i]);

	//ここからhtml出力内容
	printf( "<font size = 5>指示語の特定結果</font><br><br>\n" );
	//printf("%s", input);
	printf( "<hr><br>\n" );

	if( flag == 1 ) { //指示語があれば
		printf( "<tt>指示語を[[[ ]]]で囲みました。指示語の指し示す内容に書き換えてください。<br></tt>\n" );
		printf( "<textarea name=string rows=4 cols=50>%s</textarea><br><br>\n", input2 );
		printf( "<input type=hidden name=string value=%s>", input2 ); //次に使う文章
		printf( "<hr><tt><font size = 5, color=red>%s</font></tt><br>\n", input );
		printf ( "<hr><tt>書き換えが終わったら、下の「次へ」ボタンを押してください。</tt><br>\n" );
	}

	else {
		printf( "<input type=hidden name=string value=%s>", input0 ); //次に使う文章
		printf ( "<hr><tt>この文章中に指示語は無いので、次へを押してください。</tt><br>\n" );
	}

	printf ( "<br><br><a href=\"../../sizigohint.html\" target=\"_blank\">この画面のヒント</a></li><br><br>" );
	printf ( "<INPUT TYPE=SUBMIT VALUE=\"次へ\" >" );
	printf( "</FORM></BODY></HTML>\n" );
	/*********************************************************/


	fclose( fp2 );

	return 0;
}

/* フォームから入力された日本語をデコードするプログラム *
* 参考:「C言語道場」                                  */
int decode( char *inBuf ) {

	int i;
	int j;
	int n = strlen( inBuf );
	char decodeBuf[3];
	char c[MAXLEN];
	char outBuf[MAXLEN];

	j = 0;

	for ( i = 0; i < n; i++ ) {
		if ( inBuf[i] == '%' ) {
			strncpy( decodeBuf, &inBuf[i + 1], 2 );
			decodeBuf[2] = 0x00;
			sscanf( decodeBuf, "%2x", &c );
			outBuf[ j++ ] = c[MAXLEN];
			i += 2;
		} else
			outBuf[j++] = inBuf[i];
	}
	outBuf[j] = 0x00;
	strcpy( inBuf, outBuf );
	return 0;

}

/* フォームからの入力を切り離すプログラム *
* 参考:「猫でも分かるプログラミング」   */
int getstring( char *src, char *element, char *dest ) {
	int len;
	char *data, *amp;
	char *temp;

	len = ( int )strlen( src ) + 1;
	temp = ( char * )malloc( len );

	if ( len >= MAXLEN ) {
		free( temp );
		return -1;
	}

	strcpy( temp, src );

	data = strstr( temp, element );
	if( data == NULL ) {
		strcpy( dest, "no element" );
		free( temp );
		return -2;
	}

	len = ( int )strlen( element ) + 1;

	amp = strstr( data, "&" );
	if ( amp == NULL ) {
		strcpy( dest, data + len );
		if ( dest[0] == '\0' ) {
			strcpy( dest, "no data" );
			free( temp );
			return 0;
		}
		free( temp );
		return 1;
	}
	data[( int )( amp - data )] = '\0';
	strcpy( dest, data + len );

	if ( dest[0] == '\0' ) {
		strcpy( dest, "no data" );
		free( temp );
		return 0;
	}

	free( temp );
	return 0;
}



//文字列を置換する。 buf の中の mae を ato にする。成功=1 失敗=0
//参考:「C言語:文字列をいじる」
int strrep( char *buf, char *mae, char *ato ) {
	char *mituke;
	size_t maelen, atolen;

	maelen = strlen( mae );
	atolen = strlen( ato );
	if ( maelen == 0 || ( mituke = strstr( buf, mae ) ) == NULL ) return 0;
	memmove( mituke + atolen, mituke + maelen, strlen( buf ) - ( mituke + maelen - buf ) + 1 );
	memcpy( mituke, ato, atolen );
	return 1;
}
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

blade

Re: cgiの動作が停止してしまいます

#22

投稿記事 by blade » 13年前

デバックの仕方について、癖になるようにしたいと思います。
要所要所でどうなってるかわかったのでやっとできました。
長くなりましたのにありがとうございました。

コード:

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

#define MAXLEN 3000  //文字列の長さ

// フォームから入力された日本語をデコードするプログラム
// 参考:「C言語道場」
//http://vapour.s22.xrea.com/clangdojo/index.php?assosiative_array.c
int decode( char *inBuf );


//文字列を置換する。 buf の中の mae を ato にする。成功=1 失敗=0
//参考:「C言語:文字列をいじる」
//www.geocities.jp/debu0510/personal/c_moji.html
int strrep( char *buf, char *mae, char *ato );


//フォームからの入力を切り離すプログラム
//参考:「猫でも分かるプログラミング」
//http://homepage2.nifty.com/c_lang/intro/no_82.htm
int getstring( char *src, char *element, char *dest );

int main ( int argc, char **argv ) {
    typedef struct {
        char* base; //単語の原型
        int id; //単語の・・
        char *pos; //単語の品詞
        char arg; //単語の引数の・・
    } _token;

    _token p;
    char buf[256];
    char input0[MAXLEN];
    char input[MAXLEN];
    char input2[MAXLEN];
    char input3[MAXLEN];
    int flag = 0;         //同義語があるかどうかのフラグ
    FILE *fp_input;
    char wordtmp[512];
    char wordtmp2[512];
    unsigned int i, j;
    unsigned int size = 10;
    char data[256]; //単語のデータを格納
    FILE *fp2; //fp2は入力ファイル
    errno_t error;
    char* ctx;
    char nokori[MAXLEN];  //残りの文章
    char ch;
    char q[MAXLEN];
    char *a[MAXLEN];

    printf( "Content-type:text/html\n\n" );
    printf( "<HTML><HEAD>\n" );
    printf( "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=Shift_JIS\">\n" );
    printf( "<TITLE>自然言語文ツール</TITLE>\n" );
    printf( "</HEAD>\n<BODY>\n" );

    memset( input0, '\0', sizeof( input0 ) );
    memset( input3, '\0', sizeof( input3 ) );
    /* 入力データの取得。デコードおよび切り離しも含める */
    for ( i = 0; ( ch = getchar() ) != EOF; i++ ) {
        if ( ch == '\r' || ch == '\n' ) {
            i--;
            break;
            //q[i]=ch;
        } else
            q[i] = ch;

        //i--;
    }
    q[i + 1] = '\0';

    decode( q );
    getstring( q, "string", input3 );
    //getstring(q, "st1", st1);
    getstring( q, "nokori", nokori );

    strcpy( input0, input3 );
    while( strrep( input0, "フ", "+" ) );

    a[0] = strtok( input3, "フ" );
    for( i = 1; a[i - 1] != NULL; i++ ) {
        a[i] = strtok( NULL, "フ" );
        if( a[i] == NULL )break;  
    }



    /********** ここから解析開始 ****************/

    if ( ( error = fopen_s( &fp2, "ccc.txt", "r" ) ) != 0 ) {
        printf( "file open error!!\n" );
        exit( EXIT_FAILURE ); /* エラーの場合は通常、異常終了する */
    }

    memset( input, '\0', sizeof( input ) );
    memset( input2, '\0', sizeof( input2 ) );
    /************ cgi出力スペース ***************/
    printf( "<FORM METHOD=\"POST\" ACTION=\"./t0.cgi\">" );

    printf( "<input type=hidden name=string value=%s>", input0 ); //入力文章
    //printf("<input type=hidden name=nokori value=%s>",nokori); //残りの文章
    //printf("%s",nokori);

    /* printf("input0=%s<br>\n",input0);
    printf("input3=%s<br>\n",input3);
    */
    for( i = 0; a[i] != NULL ; i++ ) {
        while( fgets( data, sizeof( data ), fp2 ) != NULL ) {
            p.base = strstr( data, "base" );
            if( p.base == NULL )break;
            p.base = strtok_s( ( p.base ) + 6, "\"", &ctx );
            //strcat(p.base, " ");
            // printf("原型は%sです、", p.base);

            p.pos = strstr( data, "pos" );
            p.pos = strtok_s( ( p.pos ) + 5, "\"", &ctx );
            // printf("品詞は%sだ\n", p.pos);

            //指示語があれば対応する語句、語句の番号を格納する
            if( ( strncmp( p.pos, "PRP", 3 ) == 0 ) ) {
                flag = 1;
                sprintf( wordtmp, "%s, ", p.base );
                sprintf( wordtmp2, " [[[%s]]] ", p.base );
                strcat( input, wordtmp );
                strcat( input2, wordtmp2 );
                strcat( input2, " " );
            } 
            else {
                //sprintf(wordtmp, "%s", p.pos);
                sprintf( wordtmp2, "%s", p.base );
                //strcat(input, wordtmp);

                strcat( input2, a[i] );
                strcat( input2, " " );

            }

            i++;
            /* }*/


        }
    }

    //for(i=0;a[i]!=NULL;i++)printf("%sだ\n", a[i]);

    //ここからhtml出力内容
    printf( "<font size = 5>指示語の特定結果</font><br><br>\n" );
    //printf("%s", input);
    printf( "<hr><br>\n" );

    if( flag == 1 ) { //指示語があれば
        printf( "<tt>指示語を[[[ ]]]で囲みました。指示語の指し示す内容に書き換えてください。<br></tt>\n" );
        printf( "<textarea name=string rows=4 cols=50>%s</textarea><br><br>\n", input2 );
        printf( "<input type=hidden name=string value=%s>", input2 ); //次に使う文章
        printf( "<hr><tt><font size = 5, color=red>%s</font></tt><br>\n", input );
        printf ( "<hr><tt>書き換えが終わったら、下の「次へ」ボタンを押してください。</tt><br>\n" );
    }

    else {
        printf( "<input type=hidden name=string value=%s>", input0 ); //次に使う文章
        printf ( "<hr><tt>この文章中に指示語は無いので、次へを押してください。</tt><br>\n" );
    }

    printf ( "<br><br><a href=\"../../sizigohint.html\" target=\"_blank\">この画面のヒント</a></li><br><br>" );
    printf ( "<INPUT TYPE=SUBMIT VALUE=\"次へ\" >" );
    printf( "</FORM></BODY></HTML>\n" );
    /*********************************************************/


    fclose( fp2 );

    return 0;
}

/* フォームから入力された日本語をデコードするプログラム *
* 参考:「C言語道場」                                  */
int decode( char *inBuf ) {

    int i;
    int j;
    int n = strlen( inBuf );
    char decodeBuf[3];
    char c[MAXLEN];
    char outBuf[MAXLEN];

    j = 0;

    for ( i = 0; i < n; i++ ) {
        if ( inBuf[i] == '%' ) {
            strncpy( decodeBuf, &inBuf[i + 1], 2 );
            decodeBuf[2] = 0x00;
            sscanf( decodeBuf, "%2x", &c );
            outBuf[ j++ ] = c[MAXLEN];
            i += 2;
        } else
            outBuf[j++] = inBuf[i];
    }
    outBuf[j] = 0x00;
    strcpy( inBuf, outBuf );
    return 0;

}

/* フォームからの入力を切り離すプログラム *
* 参考:「猫でも分かるプログラミング」   */
int getstring( char *src, char *element, char *dest ) {
    int len;
    char *data, *amp;
    char *temp;

    len = ( int )strlen( src ) + 1;
    temp = ( char * )malloc( len );

    if ( len >= MAXLEN ) {
        free( temp );
        return -1;
    }

    strcpy( temp, src );

    data = strstr( temp, element );
    if( data == NULL ) {
        strcpy( dest, "no element" );
        free( temp );
        return -2;
    }

    len = ( int )strlen( element ) + 1;

    amp = strstr( data, "&" );
    if ( amp == NULL ) {
        strcpy( dest, data + len );
        if ( dest[0] == '\0' ) {
            strcpy( dest, "no data" );
            free( temp );
            return 0;
        }
        free( temp );
        return 1;
    }
    data[( int )( amp - data )] = '\0';
    strcpy( dest, data + len );

    if ( dest[0] == '\0' ) {
        strcpy( dest, "no data" );
        free( temp );
        return 0;
    }

    free( temp );
    return 0;
}



//文字列を置換する。 buf の中の mae を ato にする。成功=1 失敗=0
//参考:「C言語:文字列をいじる」
int strrep( char *buf, char *mae, char *ato ) {
    char *mituke;
    size_t maelen, atolen;

    maelen = strlen( mae );
    atolen = strlen( ato );
    if ( maelen == 0 || ( mituke = strstr( buf, mae ) ) == NULL ) return 0;
    memmove( mituke + atolen, mituke + maelen, strlen( buf ) - ( mituke + maelen - buf ) + 1 );
    memcpy( mituke, ato, atolen );
    return 1;
}
オフトピック
続きのプログラムは前おっしゃったようにperlでやってみたいと思います。

閉鎖

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