私が使っているマシンはWin98なのですが、ここにWindows付属のPersonalWebSaverをインストールし、
イントラネットを構築するようにしました。
そこで見れるページをVC++4(中身はまったくCです)を使いCGIを
作成することにしました。
そこでCGIを作るにあたり、送信されたきたURLにあるパラメータ(&aaa=xxx)などを解析する処理を
入れたいのですが、どのような処理させればよろしいのでしょうか?
サンプルなどご紹介していただけると大変嬉しいです。
では宜しくお願い致します。

このQ&Aに関連する最新のQ&A

A 回答 (3件)

POSTとGETによりパラメータの取得方法が異なります。


環境変数「REQUEST_METHOD」によりPOSTかGETかを判断します。POSTの場合は標準入力からGETの場合は環境変数「QUERY_STRING」からパラメータを取得します。取得したパラメータはエンコーディングされているので、処理可能な文字列に変換する必要があります。

パラメータの取得方法のサンプル
/* REQUEST_METHOD環境変数の取得 */
MethodPtr=getenv("REQUEST_METHOD");
/* METHOD==POST */
if(0==memcmp(MethodPtr,"POST",4))
{
/* CONTENT_LENGTH環境変数の取得 */
ContentLengthPtr=getenv("CONTENT_LENGTH");
/* 標準入力より読込み */
ReadSize=read((int)0,QueryStr,ContentLength);
}
/* METHOD==GET */
else if(0==memcmp(MethodPtr,"GET",3))
{
/* QUERY_STRING環境変数の取得 */
WkQueryStr=getenv("QUERY_STRING");
QueryStr = malloc( strlen(WkQueryStr)+1 ) ;
strcpy( QueryStr , WkQueryStr ) ;
}

こんな感じです。

パラメータの取得サンプル

WorkPtr = (char *)strstr( QueryStr , "code=" ) ;
WorkPtr+=5; /* "code="の文字数分インクリメント */
do{
  if(NULL==*WorkPtr || '&'==*WorkPtr)
{
break;
}
wk_code[strlen(wk_code)]=*WorkPtr;
WorkPtr++;
}while(1);

こんな感じです。

パラメータのエンコーディングの解凍方法については参考URLを参照すれば理解出来ると思います。

参考URL:http://www.iroiro.org/cgi/index.html

この回答への補足

早速のご回答ありがとうございます。
ひとつ気になるところがあるのですが、上記コーディングで...

QueryStrはchar型のポインタ変数だと思いますが、METHODの形式が"POST"であった場合
QueryStrの領域は確保する必要性はあるのでしょうか?
上記コーディングを見たところ"POST"であった場合、malloc()での領域確保処理が
内容なので気になってはいるのですが...

教えていただた身で大変恐縮ではありますが、確認のために補足として
記述させていただきました。宜しくお願い致します。

補足日時:2001/03/28 14:56
    • good
    • 0

METHODの形式が"POST"の場合も当然メモリの確保をする必要があります。


下の人は恐らく書き忘れたのでしょう。

PWSを使用といことなのでこのページはかなり参考になるのではないでしょうか?

  http://www.argus.ne.jp/hsp/setup/pwscgi.html


パラメーターの解析としてはパラメーターを取得後エンコードされた文字を
デコードする必要があります。

サンプルソース

/*************** 日本語にデコードする  ****************/

void decode(char *url)
{
int i, j;
for(i = 0, j = 0; url[j]; ++i, ++j){

if((url[i] = url[j]) == '%'){
url[i] = tochar( &url[j + 1]);
j += 2;
}
else if (url[i] == '+')
url[i] = ' ';
}
url[i] = '\0';
}

char tochar(char *x)
{
register char c;

c = (x[0] >= 'A' ? ((x[0] & 0xdf) - 'A') + 10 : (x[0] - '0'));
c *= 16;
c += (x[1] >= 'A' ? ((x[1] & 0xdf) - 'A') + 10 : (x[1] - '0'));

return c;
}

tocharで行っている処理をsscanfを使って処理するともっとすっきり
かけます。
こんな感じでいかがでしょ?
    • good
    • 0

UNIXでの経験しかないのでWindowsでは違うかもしれませんが。


パラメータにはGETとPOSTがありますが、たぶん質問されているのは
GETの場合だと思われます。
GETのパラメータは環境変数"QUERY_STRING"に格納されます。
それをgetenv()関数で取得します。
取得した文字列より目的のパラメータの値を取り出せばOKです。
POSTの場合は、標準入力(stdin)できますので、その中身を
readすれば中身を取得できます。
Windowsは違っていたらゴメンナサイ。
    • good
    • 0
この回答へのお礼

早速のアドバイスありがとうございます。
こちらでWindowsで試したところうまく動作してくようでした。
自分でもUNIXしかダメなのかなとあきらめつつやってみたところ、
WinもUNIXも同様のようでした。
OSは違うとも考え方は一緒なんですね。

お礼日時:2001/03/28 14:45

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

QC言語のソースコードの書き方

C言語のソースコードの書き方に関する質問です。
0を5個と1を4個の、合わせて9個の数字を並べて出来上がる数列のパターン(126通り)を全て羅列させるプログラムを作りたいと考えていますが、そのためにどういった方針を立ててソースコードを書けばよいかが分かりません。
どういった構造かだけでも構いませんので、教えて頂けると幸いです。
よろしくお願いします。

Aベストアンサー

という方針で書くとこんな感じね。
#include <stdio.h>

void
print_pattern(char pattern[], int size)
{
for (int i = 0; i < size; i++) {
printf("%c", pattern[i]);
}
printf("\n");
}

void
iter(char pattern[], int end, int n, int m)
{
if (n == 0 && m == 0) {
print_pattern(pattern, end);
return;
}

if (n == 0) {
pattern[end] = 'b';
iter(pattern, end + 1, n, m - 1);
return;
}
if (m == 0) {
pattern[end] = 'a';
iter(pattern, end + 1, n - 1, m);
return;
}

pattern[end] = 'b';
iter(pattern, end + 1, n, m - 1);
pattern[end] = 'a';
iter(pattern, end + 1, n - 1, m);
}

int
main(void)
{
int m = 5, n = 4;
char pattern[m + n];
iter(pattern, 0, m, n);
return 0;
}

という方針で書くとこんな感じね。
#include <stdio.h>

void
print_pattern(char pattern[], int size)
{
for (int i = 0; i < size; i++) {
printf("%c", pattern[i]);
}
printf("\n");
}

void
iter(char pattern[], int end, int n, int m)
{
if (n == 0 && m == 0) {
print_pattern(pattern, end);
return;
}

if (n == 0) {
pattern[end] = 'b';
iter(pattern, end + 1,...続きを読む

QVC++2005ExpressEditionでサンプルプログラムが動かない

 Visual C++ 2005 Express Editionを使用しています.コンパイル時にエラーが出て困っています.どなたか解決法をご教授ください.

 「猫でもわかるネットワークプログラミング」という本に載っているサンプルプログラムをコンパイルしようとすると,エラーが出ます(下のアドレス(*1)の『PDFで試し読み』に該当プログラムがあります).

 とりあえず少しずつ実行しようと,サンプルプログラムの冒頭の16行目まで書いてコンパイル・実行すると,完全に意図した動きをしました.しかし,21行目まで書いてコンパイルすると,次のエラーが出ます(ファイル名は net.cpp ).

vvvvvvvvvvvv
1>c:\***\net.cpp(16) : warning C4996: 'gets' が古い形式として宣言されました。
1> c:\program files\microsoft visual studio 8\vc\include\stdio.h(270) : 'gets' の宣言を確認してください。
1> メッセージ: 'This function or variable may be unsafe. Consider using gets_s instead. To disable deprecation, use _CRT_SECURE_NO_DEPRECATE. See online help for details.'
1>リンクしています...
1>net.obj : error LNK2001: 外部シンボル "__imp__InternetOpenW@20" は未解決です。
1>C:\***\Debug\net.exe : fatal error LNK1120: 外部参照 1 が未解決です。
1>ビルドログは "file://c:\***\BuildLog.htm" に保存されました。
1>net - エラー 2、警告 1
^^^^^^^^^^^^

 一文を加えた途端にエラーとなったので困惑しています.何かVC++の設定が悪いのでしょうか.「新規作成->プロジェクト->Win32->Win32コンソールアプリケーション」とし,次に出てくる「Win32アプリケーション ウィザード」で「空のプロジェクト」にチェックを入れています.

(*1) http://shop.sbcr.jp/bm_detail.asp?sku=4797323604

 Visual C++ 2005 Express Editionを使用しています.コンパイル時にエラーが出て困っています.どなたか解決法をご教授ください.

 「猫でもわかるネットワークプログラミング」という本に載っているサンプルプログラムをコンパイルしようとすると,エラーが出ます(下のアドレス(*1)の『PDFで試し読み』に該当プログラムがあります).

 とりあえず少しずつ実行しようと,サンプルプログラムの冒頭の16行目まで書いてコンパイル・実行すると,完全に意図した動きをしました.しかし,21行目まで書いてコ...続きを読む

Aベストアンサー

gets に関するメッセージはwarning (警告)ですので、直接関係はないです。
失敗しているのはリンクで失敗しています。
「PDFで試し読み」の本の中でのページ番号14に
Wininet.lib をプロジェクトに参加させる
というのをやっていないのではないですか?
あるいは、実際に呼び出されるWininet.dllがないのかもしれません。

その本を持っていないし、実際に試してもいないので、見当違いなコメントだったらすみません。

QC言語のソースコードについて教えてください。

以下のソースコードを学習用C言語開発環境で行ったのですが、
『ファイル「C:/Users/ユーザー名/AppData/Local/EasyIDEC/project/タイトル/main.c」の
「41行目」で記述エラーを発見しました。
「,」を付け忘れています。』

という、コンパイルエラーが表示されました。
何度も見直したのですが、よくわかりません。

#include <stdio.h>

int main(int argc, char *argv[])
{
char answer ;
answer = 'n' ;

while(answer =='n')
{
int input ;
input = 0 ;
int add ;
add = 1 ;
int sum ;
sum = 0 ;

printf("数値を入力して下さい。:") ;
scanf("%d", &input ) ;

int i ;
i = 0 ;

while(i < input)
{
sum =sum + add ;
printf("\n%d",sum) ;
i++ ;
add++ ;
}

printf("\n1から%dまでの総和は、%dです。" , input , sum) ;

while(1)
{

printf("\n終了しますか? y/n:") ;
scanf(" %c , &answer) ;

if( (answer != 'y') && (answer != 'n') )
{
printf( "y or nを入れてください。") ;
}
else
{
break ;
}
}
}
return 0 ;
}

以下のソースコードを学習用C言語開発環境で行ったのですが、
『ファイル「C:/Users/ユーザー名/AppData/Local/EasyIDEC/project/タイトル/main.c」の
「41行目」で記述エラーを発見しました。
「,」を付け忘れています。』

という、コンパイルエラーが表示されました。
何度も見直したのですが、よくわかりません。

#include <stdio.h>

int main(int argc, char *argv[])
{
char answer ;
answer = 'n' ;

while(answer =='n')
{
int input ;
input = 0 ;
int add ;
add = 1 ;
int sum ;
sum = 0 ;

printf("...続きを読む

Aベストアンサー

>>おかげで、エラー表記されずに、プログラムが実行されました。

これはコンパイルがうまく完了したってことでしょうか?できあがったプログラムが実行できたってことではないですよね?そうなら

>>’タイトル’は内部コマンドまたは外部コマンド、操作可能なプログラムまたはバッチ ファイルとして認識されていません。」

なんて問題は起きないはすですからね。

できあがったファイルは、XXXX.EXEのように拡張子のEXEがついていますか?もしXXXX.OBJであれば、リンクができていませんから、実行できません。

学習用C言語開発環境の使い方を確認してみてください。

P.S.
昔は、コンパイラを使うのは大変でしたが、今は楽ですね。CではなくPascal系コンパイラーですが、カセットテープに入っていて、コンパイラの読込にテープレコーダで15分かかったりとか、まあ大変だけど面白い時代でした。

QCQ出版Interface誌12月号のVC++でのTCP/IPサンプルプログラムを動作できない

Interface誌の12月号にMicrosoft Vistal C++ 2008 Express EdtionでのTCP/IPサーバ、クライアントのサンプルプログラムが下記のURLからダウンロードできるようになっており、


http://www.cqpub.co.jp/interface/download/contents.htm
”第1章 C言語で書くシンプルなWebサーバの製作”の項目


このサイトからダウンロードして、自分のPCでサーバとクライアントを両方CTRL + F5で起動させようとしたところ、サーバプログラムはちゃんと起動するのですが、クライアントを起動することができませんでした。雑誌の中ではちゃんと動くようなのですが、なぜ自分のPCでは動かないのか原因がわかりません。ご存じの方いらっしゃいましたら是非ご教授よろしくお願いいたします。

そのときの症状を映像で取りましたのでyoutubeにアップしておきます。

http://www.youtube.com/watch?v=Lhsmqw0xepM

Aベストアンサー

手元のはMicrosoft Visual Studio 2005なので、ソリューションは開けませんでしたが…
クライアント側のソースコードのドコにも
「7番ポートで接続待機中」と表示するコードがありません。
にも関わらず、動画内のクライアント側を実行した。
というところで
「7番ポートで接続待機中」
が表示されるのはおかしいと思いませんか?

Microsoft Visual Studio 2005の場合ですが、ソリューションエンスプローラから該当のプロジェクトを選択し、
右クリックで表示されるメニューから[デバッグ][新しいインスタンスを開始]で、起動できました。
# もっとも、Ctrl+F5のデバッグなしで起動とは違いますが…
# F5/Ctrl+F5で起動できるのはスタートアッププロジェクトに設定されている場合…でしょうか。
# ソリューションを選択して右クリック、[スタートアップ プロジェクトの設定]で、「現在の選択」にしておくと、自動で切り替わるようですが。(それでもデバッグ起動できるのは1つだけ)

QC言語ソースコードに関する質問です。

以下の数列について,初項から第15項までを求めるプログラムと実行結果を示せ。
0 1 1 2 3 5 8 13 21(ただし,初項=0,第1項=1とする。)

ソースコードを書くと、エラーがでた。
#include <stdio.h>
int fib(int n)
{
if(n==1 || n==2)
return 1;
else
return fib(n-1)+fib(n-2);
}
int main(void)
{
int n;
for(n=0;n<17;n++)
printf("%d,",fib(n));
}

正しソースコードを教えてください!

よろしくお願いします。

Aベストアンサー

#include <stdio.h>

void fib(int i, int j, int n)
{
if (n == 1)
{
printf("%d\n", i);
}
else
{
printf("%d\n", i);
return fib(j, i + j, n - 1);
}
}

int main(void)
{
fib(0, 1, 15);

return 0;
}

QVC++2010 エンターキーが押されたときの処理

VC++2010 エンターキーが押されたときの処理なんですが、
キーボードのエンターキーが押されたとき,ある処理(なんかの関数をさせたりなど・・・)をさせたいんですが調べた結果わかりませんでした。
どのようにしたらよろしいでしょうか?
よろしくお願いします.

Aベストアンサー

状況が全く書かれていませんが。

C++/CLIなのか、MFCなのかAPIのみ使用なのか。
何かダイアログなどのウィンドウを表示している状態なのか、フォーカスはどこにあるのか。

こういったことが書かれていないと、「どのようにしたら」と言われても「状況によって適切な位置にコードを書きましょう」としか言いようがありません。

Qc言語のソースコードを教えて下さい

キーボードから10個の正整数値を読み込み,合計値を表示するプログラムを作りなさい。
ただし,キーボードから読み込んだ値はint型変数xにしまわれるものとし,変数はこのxと回数を数えるint型変数countと合計値をしまうint型変数sumのみを用いることとする。

このプログラムのソースコードを教えて下さい。
解説もよろしくお願いします。

Aベストアンサー

一例です。
添付のURLを参照して下さい。
因みに、平均値も算出しているが気にせずに、後はご自身で変数、コードを要調整して下さい。

参考URL:http://www.geocities.jp/kenji_y0328/crenshu/renshu/r021.gif

Q関数名、パラメータは同じで、戻り値によって異なる処理?

戻り値というより、受け側によって関数の振る舞いを変えたいのですが、
C++では、同名、同パラメータはC2556のコンパイルエラーになります。

Perlでいうリスト値を返すかスカラー値を返すかは呼び出し側によるようなことをしたいのですが、C++では無理でしょうか?

下の例では、//...部分は戻り値によって異なるのでC++のテンプレート?では無理そうですが、そんなことはC++でできるのでしょうか?
似たようなテクニックでも構いませんので、知識の豊富な方、教えてください。

#include <iostream>
#include <string>

using namespace std;

class A {
public:
A(){}
~A(){}
int test(int x, int y){
          //...
return 0;
}
string test(int x, int y){
// ...
return "";
}
};


void main(void){
A a;
int ret1 = a.test(1,2);
string ret2 = a.test(1,2);

cout << endl << "End..." << endl;

}

戻り値というより、受け側によって関数の振る舞いを変えたいのですが、
C++では、同名、同パラメータはC2556のコンパイルエラーになります。

Perlでいうリスト値を返すかスカラー値を返すかは呼び出し側によるようなことをしたいのですが、C++では無理でしょうか?

下の例では、//...部分は戻り値によって異なるのでC++のテンプレート?では無理そうですが、そんなことはC++でできるのでしょうか?
似たようなテクニックでも構いませんので、知識の豊富な方、教えてください。

#include <iostream>
#i...続きを読む

Aベストアンサー

決してお勧めはしませんが...

class A
{
public:
 class B
 {
  A* a_;
  int x_, y_;
 public:
  explicit B(A* a, int x, int y) : a_(a), x_(x), y_(y) {}
  template <class T>
   operator T() const;
 };
 B test(int x, int y)
 {
  return B(this, x, y);
 }
};

template<> A::B::operator int() const { return 0; }
template<> A::B::operator std::string() const { return ""; }

int main()
{
 A a;
 int i = a.test(1, 2);
 std::string s = a.test(1, 2);
}

とすれば解決できそうです。GCCではコンパイルできました。
(移植性があるかどうかは未確認)

決してお勧めはしませんが...

class A
{
public:
 class B
 {
  A* a_;
  int x_, y_;
 public:
  explicit B(A* a, int x, int y) : a_(a), x_(x), y_(y) {}
  template <class T>
   operator T() const;
 };
 B test(int x, int y)
 {
  return B(this, x, y);
 }
};

template<> A::B::operator int() const { return 0; }
template<> A::B::operator std::string() const { return ""; }

int main()
{
 A a;
 int i = a.test(1, 2);
 std::string s = a...続きを読む

Qソースコードの間違い (C言語)

変数に、文字列を入れた配列の文字列の最後の要素数を入れたいのですが(つまり'\0')、うまくいきません。いつも2個多い値になってしまいます。

#include <stdio.h>

void main() {
char moji[100]={0};
int c=0;

fgets(moji,sizeof moji,stdin);

while( moji[c] != '\0' ) ++c;

printf("\n%d\n",c); //
}

例えば5文字の1ビット文字を入れると、最後の文字はmoji[4]にあるのでprintfで4と表示されるはずじゃないですか。でも6になるんです。いつも+2の値になるんですよ。どうやらfgetsを使っているからそうなるらしく、scanfを使うと結果は1多い値に、普通に配列に直接文字列を代入すると正常な結果になります。別にcに-2してもいいのですが、それはなんだか癪といいますか・・・。なぜこういうことがおきるのでしょうか?回答よろしくお願いします。

Aベストアンサー

>なぜこういうことがおきるのでしょうか
そのmoji[]の余計な部分にはどんなコードが入っているかは確認していますか?
リターンキーも「キー入力」の一つですよ。

QVC++フォームアプリケーション でのビットマップ処理

私は今Visual Studio 2005(C++)のフォームアプリケーションでプログラムを組んでいるのですが、ビットマップ処理ができません。以下のプログラムにどのような変更を加えればできるようになるのでしょうか?
ご存知の方がいたら教えてください。

#pragma once

~フォームのデザイン部分のプログラム(自動)なので省略いたします~

#pragma endregion
private: Bitmap^ bmp;

private: System::Void Form1_Load(System::Object^ sender, System::EventArgs^ e) {
}

private: System::Void 開くOToolStripMenuItem_Click(System::Object^ sender, System::EventArgs^ e) {
OpenFileDialog^ myDLG = gcnew OpenFileDialog();
myDLG->AddExtension = true;
myDLG->DefaultExt = "bmp";
myDLG->FileName = "*.bmp";
myDLG->ShowReadOnly = false;
myDLG->Filter = "ビットマップ(*.bmp) | *.bmp | jpeg(*.jpg;*.jpeg) | *.jpg;*.jpeg";
if(myDLG->ShowDialog() == System::Windows::Forms::DialogResult::OK){
this->Text = myDLG->FileName;
pictureBox1->Image = gcnew Bitmap(myDLG->FileName);
Invalidate();
}
}

private: System::Void 保存SToolStripMenuItem_Click(System::Object^ sender, System::EventArgs^ e) {
SaveFileDialog^ myDLG = gcnew SaveFileDialog();
myDLG->AddExtension = true;
myDLG->DefaultExt = "bmp";
myDLG->FileName = "*.bmp";
myDLG->Filter = "ビットマップ(*.bmp) | *.bmp | jpeg(*.jpg;*.jpeg) | *.jpg;*.jpeg | すべてのファイル(*.*) | *.*";
if(myDLG->ShowDialog() != System::Windows::Forms::DialogResult::OK){
return;
}
pictureBox1->Image->Save(myDLG->FileName);

Invalidate();
}

private: System::Void 閉じるCToolStripMenuItem_Click(System::Object^ sender, System::EventArgs^ e) {
if(MessageBox::Show("アプリケーションを終了しますか?","画像描画",MessageBoxButtons::OKCancel,MessageBoxIcon::Question)
== System::Windows::Forms::DialogResult::OK){
this->Close();
}
}

private: System::Void 編集ToolStripMenuItem_Click(System::Object^ sender, System::EventArgs^ e) {
}

private: System::Void 回転180ToolStripMenuItem_Click(System::Object^ sender, System::EventArgs^ e) {
}


}

よろしくお願いします。

私は今Visual Studio 2005(C++)のフォームアプリケーションでプログラムを組んでいるのですが、ビットマップ処理ができません。以下のプログラムにどのような変更を加えればできるようになるのでしょうか?
ご存知の方がいたら教えてください。

#pragma once

~フォームのデザイン部分のプログラム(自動)なので省略いたします~

#pragma endregion
private: Bitmap^ bmp;

private: System::Void Form1_Load(System::Object^ sender, System::EventArgs^ e) {
}

private: System::Void 開くOTo...続きを読む

Aベストアンサー

 こんばんは。
 ピクチャーボックス内のビットマップを180度回転させたいのでしょうか?
 であるのでしたら、これで回転出来る筈です。以下参考に。

private: System::Void 回転180StripMenuItem_Click(System::Object^ sender, System::EventArgs^ e)
{
pictureBox1->Image->RotateFlip(System::Drawing::RotateFlipType::Rotate180FlipX);
pictureBox1->Invalidate();
}


人気Q&Aランキング

おすすめ情報