- ベストアンサー
環境変数の切り離し
CGIを最近やり始めたのですが、どうしても分からないのが環境変数の切り離しです。 POSTメソッドによるCGIへのデータの引渡しで、引き渡されたデータを for (i = 0; (c = getchar()) != EOF; i++) { buffer[i] = c; } buffer[i] = '\0'; として、char buffer[]へ文字列を入力しました。 ※ここで、「a=1&b=2&c=3」 という文字列が入力されたとする。 そこで「a=1&b=2&c=3」を「a」「1」「b」「2」「c」「3」と、それぞれ切り離した変数を作りたくて、外部関数の仮引数char buff[]に実引数bufferを入れ、 i = x = y = 0; while (buff[i] != '\0') { if (buff[i] == '=' || buff[i] == '&') { str[x][y] = '\0'; x++; y = 0; } else { str[x][y] = buff[i]; y++; } i++; } このようにして str[偶数][y]にname値、 str[奇数][y]にvalue値を入れようとしているのですが、スクリプトエラーとなります。 エラー部分は、 if (buff[i] == '=' || buff[i] == '&') { str[x][y] = '\0'; x++; y = 0; } else { str[x][y] = buff[i]; y++; } のようなのですが、なぜエラーになるのか分かりません。 もしエラーになる原因が分かる方いらっしゃいましたら教えてください。
- みんなの回答 (6)
- 専門家の回答
質問者が選んだベストアンサー
がるです。 ちぃと気になったのですが。 > 外部関数 int hoge(char buff[]) を呼び出しています これは、 int hoge(char *buf) ではなくて int hoge(char buf[]) とかかれてますか? だとしたら、まず何はさておき、その部分を int hoge(char *buf) に直してください。 このあたりは、変数宣言の意味とかメモリがどのタイミングで確保されているかとかそーゆー話になってきます。
その他の回答 (5)
- galluda
- ベストアンサー率35% (440/1242)
がるです。 んっと。変数の宣言と呼び出しを簡単に要約して。 main側では unsigned char buf[]; unsigned char str[][]; と宣言することで、データ実態を作ることができます(実際は、中に数値を入れるか、もっと理想的にはポインタ型で宣言してからmallocとかするんですが)。 で、関数hogeをcallするときは、main側は hoge(buf, str); とcallします。 一方。関数hogeはあらかじめ int hoge(char *buf, char **str); のように宣言し、実際に関数を書くときも int hoge(char *buf, char **str) { } と書きます。 実際に使う部分を適当に記述すると、例えば int hoge(char *buf, char **str) { int i= 0; if (buff[i] == '=' || buff[i] == '&'){ str[x][y] = '\0'; x++; y = 0; }else{ str[x][y] = buff[i]; y++; } // 以下続く } という風に記述できます。
お礼
丁寧な解説ありがとうございました。無事思い通りの処理ができました。 また、エラーが頻出する原因はコンパイルの仕方にも問題がありました。 お手数をおかけいたしました。感謝です。
- galluda
- ベストアンサー率35% (440/1242)
がるです。んっと、まずは状況の整理をきちんとしたいと思います。 > 外部関数の中に > printf("<p>外部値「%c」</p>\n", *(buff+1)); > などの記述で、main関数のbufferに入っている2文字目の文字などを確認はできましたが、これからどのようにして外部関数の文字配列 (例:hoge[n]) に main関数のbuffer[n]の値を入れれば良いのでしょうか。 この部分を基準に。 まずお話の限りですと ・外部関数とmain関数がある ことがわかります。また、とりあえず ・bufという名前で「標準入力から取得したデータ」を格納する変数 ・strという名前で「カッティングしたデータ」を格納する変数 の二つがあることも判明しています。 ここまではOKでしょうか? 次に、各変数の「実態」がどこで作成されているかを考慮します。 とりあえず ・双方ともmainで作成している と仮定しましょう。 main関数で unsigned char buf[]; unsigned char str[][]; と宣言します。 次に、外部関数で処理をするのであれば、上述の二つを引数として渡してあげる必要が出てきます。 int hoge(*buf, **str); これで、引数が二つとも渡ります。 あとは if (buff[i] == '=' || buff[i] == '&'){ str[x][y] = '\0'; x++; y = 0; } else { str[x][y] = buff[i]; y++; } str[x][y] = '\0'; の処理をそのままhoge関数に書けばよろしいかと思いますがいかがでしょうか? ただ、一番初めにも書いたとおり、特にstrのもち方など、あまりよろしいものではないと思われます。 構造体というものを、もしご存じなければ、まずは調べて、使われることを強くお勧めいたします。 あとは、恐らくポインタとかメモリ周りの部分がまだ苦手であるような印象を受けますので、できれば実際に対面で見てもらえる方に、絵を書いてもらうなどしてきちんと説明を受けたほうがわかりやすいと思います。
お礼
丁寧な解説ありがとうございます。 ご指摘どおり、確かに自分でもstr[][]への値の入れ方はよくないというのは理解できます。いずれ構造体などを使用したより良いものを作ろうと思います。 またポインタの仕組みは理解しているつもりですし苦手意識もありません、「記述の仕方」が分からないんですよね。 ただ、一つ疑問点があるのですが、 int hoge(*buf, **str);というのは、セミコロンがあるところからmain関数の中で外部関数を呼び出すものと推測して、この引数をどうやって外部関数で受け取れば、その外部関数で「 buff[i] 」として扱えるようになるのでしょうか。最後にこれについて教えていただけると幸いです…。
- galluda
- ベストアンサー率35% (440/1242)
がるです。なるほど状況は把握できました。 で。 その場合、エラーの原因がもう一つ不明ですね。つまり、おっしゃってるロジックの部分にあるのか「実は別の場所にある」のか。 まず、プログラムの先頭(変数宣言の直後)に、以下の一文を入れてください。 printf("Content-type: text/plain\n\n"); で、まずはその直後でreturn。 何も表示されませんが、正常に終了するはずです(ここで正常に終了しなければHTTPサーバの設定の問題でしょう)。 次に、先ほどのreturnをコメントアウトしてから、今回問題になったデータの切り分けロジックの直下でreturn。 必要に応じて、各変数をprintf文つかって打ち出してみてください。 デバッグは、こうやって「どこに問題があるのか」を探り出していく事からはじめます。 また進展があったら書いていただければ、回答できるかと思います。
補足
回答ありがとうございます。 それはすでにしました。(というより、最初に提示したソースはHTML出力するプログラムの一部でもありますので) それによりエラーは、 if (buff[i] == '=' || buff[i] == '&') { str[x][y] = '\0'; x++; y = 0; } else { str[x][y] = buff[i]; y++; } の部分を削除するとエラーはなくなりました。 そこで、buffにうまく文字列が入っていないのかもしれないと気づきました。 実のところ…引数に文字列を使うことは初めてでして、 main関数の中で、point = hoge(buffer); と記述することにより 外部関数 int hoge(char buff[]) を呼び出しています ※bufferは、char buffer[1024];という文字列です。 これで外部関数のbuff[]は、main関数のbuffer[0]~[n]のそれぞれ文字が、buff[0]~[n]に入っているという解釈をしているのですが、正しいでしょうか。 エラーが出る部分を削除した場所で、printf文によりbuff[0]などを出力しても同様にエラーが出るので、これが原因かもしれないと気づきました。 もしその方法や解釈が正しくないのであれば、外部関数のbuff[0]~[n]のそれぞれに、main関数のbuffer[0]~[n]を渡す方法を(直接渡すことができないのであれば、その間接的に渡す方法でも)もし分かりましたらお手数ですが教えてくださるととても嬉しいです。 また、正しいのであれば、では何故buff[0]が出力できないか分からないので知りたいです。
- php504
- ベストアンサー率42% (926/2160)
エラーの原因かどうかわかりませんがwhileループを抜けた後に str[x][y] = '\0'; がもう1回必要ですね。 cgi用のライブラリ探して使った方が楽ですよ
お礼
回答ありがとうございます。 >str[x][y] = '\0';がもう1回必要ですね。 おっしゃる通りでした。 とりあえずstr[x][y] = '\0';追加しましたが、スクリプトエラーとなるのは変わりませんでした。 >cgi用のライブラリ探して使った方が楽ですよ そうですよね、でもそれは解決しなかった時の最終手段とします…。
- galluda
- ベストアンサー率35% (440/1242)
がると申します。 …っと。「readつかってstdinの情報を読み取る」ではなにかまずいんでしょうか? とかいう突っ込みはさておくとして。 拝見している限りではC言語(ないしC++)をお使いのようなのですが、「スクリプトエラー」という発言からはPerlとかそのあたりのスクリプト系言語が類推されます。 あと、いずれにしても「データと値を奇数/偶数で切り分ける」のはあまりよいとは言えず、基本的には構造体ないしそれに近しいもの(言語仕様により異なる)を用いられるべきかと思います。 また、C言語であると仮定して。とりあえず「コンパイルは通る」かと思うのですが(実行結果については…意図しているものがもう一つ見えにくいのですが、恐らくは意図している通りのデータなのではないかと)。 なにをもって「スクリプトエラーとなります。」とされているのかの理由の部分を書いていただけると、もう少し何か回答も可能かと思うのですが。
補足
回答ありがとうございます。 えーと、何をおっしゃっているのか私の知識と読解力では理解できかねる部分が多いのですが、以下の点を補足いたします。 ・プログラムはC言語で記述しております。 ・スクリプトエラーは、CGIを実行して表示されたエラー出力「Script Error」が表示されるので、「スクリプトエラーとなります。」としております。
補足
重ね重ね回答ありがとうございます。 おっしゃる通りに、int hoge(char *buff) に直しましたが、エラーのままです。 外部関数の中に printf("<p>外部値「%c」</p>\n", *(buff+1)); などの記述で、main関数のbufferに入っている2文字目の文字などを確認はできましたが、これからどのようにして外部関数の文字配列 (例:hoge[n]) に main関数のbuffer[n]の値を入れれば良いのでしょうか。 自分で調べてもいるのですが、次にどういう処理をするかが分からないため調べても目的のヒントすら知ることができません。 もしよろしければお手数ですが続きを教えてください。