char site[];
scanf("%s", site);
send(sock,"GET / HTTP/1.1\r\nHost: " + site + "\r\nConnection: close\r\n\r\n", strlen("GET / HTTP/1.1\r\nHost: " + site + "\r\nConnection: close\r\n\r\n"),0);
これにより、エラーが発生します。式には整数型または列挙型が必要です。
どうすればこれを修正できますか?
他の回答で述べたように、投稿したコードはストレートCです。C++では、通常、Cスタイルのchar配列よりもstd :: stringを、Cスタイルのscanf()よりもstd::cinを優先します。より多くのC++の方法は次のようになります
std::string input;
std::cin >> input;
std::string out = "GET / HTTP/1.1\r\nHost: " + input + "\r\nConnection: close\r\n\r\n";
send(sock, out.c_str(), out.size(), 0);
別のGET
実装。
char *get_http= new char[256];
memset(get_http,' ', sizeof(get_http) );
strcpy(get_http,"GET / HTTP/1.1\r\nHost: ");
strcat(get_http,url);
strcat(get_http,"\r\nConnection: close\r\n\r\n");
.
.
send(Socket,get_http, strlen(get_http),0 );
WinsockコンソールのHTMLブラウザコードのサンプル:
#include <winsock2.h>
#include <windows.h>
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <cctype>
#include <locale>
#pragma comment(lib,"ws2_32.lib")
using namespace std;
string website_HTML;
locale local;
//***************************
void get_Website(char *url );
//***************************
int main ()
{
get_Website("www.msn.com" );
for (size_t i=0; i<website_HTML.length(); ++i) website_HTML[i]= tolower(website_HTML[i],local);
cout <<website_HTML;
cout<<"\n\n";
return 0;
}
//***************************
void get_Website(char *url )
{
WSADATA wsaData;
SOCKET Socket;
SOCKADDR_IN SockAddr;
int lineCount=0;
int rowCount=0;
struct hostent *host;
char *get_http= new char[256];
memset(get_http,' ', sizeof(get_http) );
strcpy(get_http,"GET / HTTP/1.1\r\nHost: ");
strcat(get_http,url);
strcat(get_http,"\r\nConnection: close\r\n\r\n");
if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0)
{
cout << "WSAStartup failed.\n";
system("pause");
//return 1;
}
Socket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
host = gethostbyname(url);
SockAddr.sin_port=htons(80);
SockAddr.sin_family=AF_INET;
SockAddr.sin_addr.s_addr = *((unsigned long*)host->h_addr);
cout << "Connecting to "<< url<<" ...\n";
if(connect(Socket,(SOCKADDR*)(&SockAddr),sizeof(SockAddr)) != 0)
{
cout << "Could not connect";
system("pause");
//return 1;
}
cout << "Connected.\n";
send(Socket,get_http, strlen(get_http),0 );
char buffer[10000];
int nDataLength;
while ((nDataLength = recv(Socket,buffer,10000,0)) > 0)
{
int i = 0;
while (buffer[i] >= 32 || buffer[i] == '\n' || buffer[i] == '\r')
{
website_HTML+=buffer[i];
i += 1;
}
}
closesocket(Socket);
WSACleanup();
delete[] get_http;
}
char site[];
このコードは合法ではありません。コンパイラは次のようなエラーを生成する必要があります。
main.cpp:5:10: error: definition of variable with array type needs an explicit size or an initializer
char site[];
^
C++ では、組み込み配列の型の一部である固定サイズがあるためです。サイズ変更可能な配列が必要std::vector
な場合は、一般的なケースとstd::string
文字列に使用する必要があります。
scanf("%s", site);
が機能している場合char site[]
、コンパイラはおそらくサイズ 0 の配列を作成するため、配列に何かを読み込むとバッファ オーバーフローが発生します。
send(sock,"GET / HTTP/1.1\r\nHost: " + site + "\r\nConnection: close\r\n\r\n", strlen("GET / HTTP/1.1\r\nHost: " + site + "\r\nConnection: close\r\n\r\n"),0);
これにより、次の行に沿って別のエラーが発生するはずです。
main.cpp:10:42: error: invalid operands to binary expression ('const char *' and 'char *')
send(sock,"GET / HTTP/1.1\r\nHost: " + site + "\r\nConnection: close\r\n\r\n", strlen("GET / HTTP/1.1\r\nHost: " + site + "\r\nConnection: close\r\n\r\n"),0);
~~~~~~~~~~~~~~~~~~~~~~~~~~ ^ ~~~~
C++ では、配列を単純に追加することはできません。繰り返しますが、C++ の配列は固定サイズのオブジェクトです。ただし、std::strings
一緒に追加することも、 astd::string
で aを追加することもできますconst char *
(std::string はoperator+
それ自体と の間で定義されるためconst char *
)。
std::string site;
site = getURL(); // you'll have to implement this, including both getting the string from the user and validating that the user isn't entering in something tricky that will cause security problems
std::string query = "GET / HTTP/1.1\r\nHost: " + site + "\r\nConnection: close\r\n\r\n";
send(sock, query.c_str(), query.size());
これは C++ とタグ付けされていますが、コードはストレート C です。2 つの問題があります。まず、site
不完全な型です。サイズを指定する必要があります。第二に、C では文字列を '+' で詰め込むことはできません。使用する必要がありますstrcat
:
char site[128];
char cmd[128];
scanf("%s", site);
strcpy(cmd, "GET / HTTP/1.1\r\nHost: ");
strcat(cmd, site);
strcat(cmd, "\r\nConnection: close\r\n\r\n");
これはスタイル (または \r\n のもの) を推奨するものではなく、オリジナルがしなかったことを行う単純なコード ブロックにすぎません。
これを変える:
"GET / HTTP/1.1\r\nHost: " + site + "\r\nConnection: close\r\n\r\n", strlen("GET / HTTP/1.1\r\nHost: " + site + "\r\nConnection: close\r\n\r\n"
これに:
(std::string() +"GET / HTTP/1.1\r\nHost: " + site + "\r\nConnection: close\r\n\r\n", strlen("GET / HTTP/1.1\r\nHost: " + site + "\r\nConnection: close\r\n\r\n").c_str()
そのコード行をコンパイルして、おそらくあなたが望むことをするための絶対に最小限の変更のために。
生の C 文字列に対する operator+ は、やりたいことを何もしません。std::string() で開始することにより、生の C 文字列を追加すると、新しい std::string が作成されます。次に、最後に .c_str() を呼び出して、少なくとも呼び出している関数が終了するまで続く生の C 文字列に戻ります。その後、すべてがクリーンアップされます。
さて、あなたのコードには他の問題があります。 コンパイラは配列char site[]; scanf("%s", site);
の大きさを認識できないため、未定義の動作を引き起こします。のようにサイズを指定したとしてもsite
、これは発生するのを待っているバッファ オーバーフローになります。そのように使用することはお勧めしません。site
char site[100];
scanf
文字列を読み取るときは、読み取る量を読み取り先のバッファーに制限する関数、または読み取り対象に合わせて必要に応じてバッファーのサイズを変更する関数が必要です。
注: タグ付けされているように、コードは実際には C++ であると想定しています。