写了一阵子C++,再写C就不怎么顺手了,写成了“高级集成语言”,再写“低级集成语言”,发现很多东西都不顺手,就拿这次批量查询IP来说吧,对于fgets读取获得的buf,C++中似乎不用管这个指针变量char *所指地址的大小,而C语言就不同了,直接指定char *会发生core dump,必须指定char的大小,另外,我测试平台可能也有很大关系,我在windows下的cygwin平台没有错误,但是在linux下发生错误,freebsd下却因为inet的问题导致错误,很稀奇,在cygwin下代码如下:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#include <netinet/in.h>
#include <netdb.h>
#define DOMAINLENGTH 100
int main (int argc, char *argv[])
{
if (argc != 3)
{
printf("usage: %s <infile> <outfile>\n", argv[0]);
return 0;
}
struct in_addr addr;
struct hostent * domain;
uint address = 0;
char *dom;
char *ipaddress;
char *output;
FILE *fp;
FILE *op;
if ((fp = fopen(argv[1], "r")) == NULL)
{
perror("Can't read the file!");
exit(1);
}
if ((op = fopen(argv[2], "w")) == NULL)
{
perror("Can't write the file!");
exit(1);
}
int i;
while (fgets(dom, DOMAINLENGTH, fp))
{
int domLen = strlen(dom);
for (i = 0; i < domLen; i ++)
{
if (dom[i] == '\r' || dom[i] == '\n') dom[i] = '\0';
}
if (*dom == 0 || strlen(dom) < 5) continue;
if (strstr(dom, ":") || strstr(dom, "/"))
{
char *httptype = strtok(dom, ":");
char *host = strtok(NULL, " ");
if (strcmp(httptype, "http") == 0 || strcmp(httptype, "https") == 0 || strcmp(httptype, "ftp") == 0)
{
if (strstr(host, ":"))
{
if ((httptype = strtok(host, ":")) != NULL)
{
host = strtok(NULL, " ");
sprintf(host, "%s", httptype);
}
}
if (strstr(host, "//"))
{
char *slashs = strtok(host, "//");
sprintf(host, "%s", slashs);
}
if (strstr(host, "/"))
{
char *slash = strtok(host, "/");
sprintf(host, "%s", slash);
}
sprintf(dom, "%s", host);
}
else
{
if (strstr(httptype, "/"))
{
char *slash = strtok(httptype, "/");
sprintf(httptype, "%s", slash);
}
sprintf(dom, "%s", httptype);
}
}
if (isalpha(*dom))
{
domain = gethostbyname(dom);
if (domain != NULL)
{
address = ((uint*)domain->h_addr_list[0])[0];
if ( (address & 0xffff) == 0x0a0a ) address= ((uint*)domain->h_addr_list[0])[1];
}
}
else
{
address = inet_addr(dom);
}
addr.s_addr = address;
ipaddress = inet_ntoa(addr);
sprintf(output, "%s\t%s\n", dom, ipaddress);
if (fputs( output, op ) == EOF)
{
perror("Write error!");
exit(1);
}
}
fclose(fp);
fclose(op);
return 0;
}
在linux正确运行代码如下:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#include <netinet/in.h>
#include <netdb.h>
#define DOMAINLENGTH 100
int main (int argc, char *argv[])
{
if (argc != 3)
{
printf("usage: %s <infile> <outfile>\n", argv[0]);
return 0;
}
struct in_addr addr;
struct hostent * domain;
uint address = 0;
char dom[DOMAINLENGTH];
char output[DOMAINLENGTH+16];
char *ipaddress;
FILE *fp;
FILE *op;
if ((fp = fopen(argv[1], "r")) == NULL)
{
perror("Can't read the file!");
exit(1);
}
if ((op = fopen(argv[2], "w")) == NULL)
{
perror("Can't write the file!");
exit(1);
}
int i;
while (fgets(dom, DOMAINLENGTH, fp) != NULL)
{
int domLen = strlen(dom);
for (i = 0; i < domLen; i ++)
{
if (dom[i] == '\r' || dom[i] == '\n') dom[i] = '\0';
}
if (*dom == 0 || strlen(dom) < 5) continue;
if (strstr(dom, ":") || strstr(dom, "/"))
{
char *httptype = strtok(dom, ":");
char *host = strtok(NULL, " ");
if (strcmp(httptype, "http") == 0 || strcmp(httptype, "https") == 0 || strcmp(httptype, "ftp") == 0)
{
if (strstr(host, ":"))
{
if ((httptype = strtok(host, ":")) != NULL)
{
host = strtok(NULL, " ");
sprintf(host, "%s", httptype);
}
}
if (strstr(host, "//"))
{
char *slashs = strtok(host, "//");
sprintf(host, "%s", slashs);
}
if (strstr(host, "/"))
{
char *slash = strtok(host, "/");
sprintf(host, "%s", slash);
}
sprintf(dom, "%s", host);
}
else
{
if (strstr(httptype, "/"))
{
char *slash = strtok(httptype, "/");
sprintf(httptype, "%s", slash);
}
sprintf(dom, "%s", httptype);
}
}
if (isalpha(*dom))
{
domain = gethostbyname(dom);
if (domain != NULL)
{
address = ((uint*)domain->h_addr_list[0])[0];
if ( (address & 0xffff) == 0x0a0a ) address= ((uint*)domain->h_addr_list[0])[1];
}
}
else
{
address = inet_addr(dom);
}
addr.s_addr = address;
ipaddress = inet_ntoa(addr);
sprintf(output, "%s\t%s\n", dom, ipaddress);
printf("%s", output);
if (fputs( output, op ) == EOF)
{
perror("Write error!");
exit(1);
}
}
fclose(fp);
fclose(op);
return 0;
}
freebsd下正确运行与linux运行不一样就是结构申明没有那么自由,linux下可以任意处申明,而freebsd必须函数开头申明,程序如下:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <unistd.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#define DOMAINLENGTH 100
int main (int argc, char *argv[])
{
struct in_addr addr;
struct hostent * domain;
uint address = 0;
char dom[DOMAINLENGTH];
char output[DOMAINLENGTH+16];
char *ipaddress;
FILE *fp;
FILE *op;
int i = 0;
if (argc != 3)
{
printf("usage: %s <infile> <outfile>\n", argv[0]);
return 0;
}
if ((fp = fopen(argv[1], "r")) == NULL)
{
perror("Can't read the file!");
exit(1);
}
if ((op = fopen(argv[2], "w")) == NULL)
{
perror("Can't write the file!");
exit(1);
}
while (fgets(dom, DOMAINLENGTH, fp) != NULL)
{
int domLen = strlen(dom);
for (i = 0; i < domLen; i ++)
{
if (dom[i] == '\r' || dom[i] == '\n') dom[i] = '\0';
}
if (*dom == 0 || strlen(dom) < 5) continue;
if (strstr(dom, ":") || strstr(dom, "/"))
{
char *httptype = strtok(dom, ":");
char *host = strtok(NULL, " ");
if (strcmp(httptype, "http") == 0 || strcmp(httptype, "https") == 0 || strcmp(httptype, "ftp") == 0)
{
if (strstr(host, ":"))
{
if ((httptype = strtok(host, ":")) != NULL)
{
host = strtok(NULL, " ");
sprintf(host, "%s", httptype);
}
}
if (strstr(host, "//"))
{
char *slashs = strtok(host, "//");
sprintf(host, "%s", slashs);
}
if (strstr(host, "/"))
{
char *slash = strtok(host, "/");
sprintf(host, "%s", slash);
}
sprintf(dom, "%s", host);
}
else
{
if (strstr(httptype, "/"))
{
char *slash = strtok(httptype, "/");
sprintf(httptype, "%s", slash);
}
sprintf(dom, "%s", httptype);
}
}
if (isalpha(*dom))
{
domain = gethostbyname(dom);
if (domain != NULL)
{
address = ((uint*)domain->h_addr_list[0])[0];
if ( (address & 0xffff) == 0x0a0a ) address= ((uint*)domain->h_addr_list[0])[1];
}
}
else
{
address = inet_addr(dom);
}
addr.s_addr = address;
ipaddress = inet_ntoa(addr);
sprintf(output, "%s\t%s\n", dom, ipaddress);
printf("%s", output);
if (fputs( output, op ) == EOF)
{
perror("Write error!");
exit(1);
}
}
fclose(fp);
fclose(op);
return 0;
}
都是使用的标准ASCII C函数,怎么会那么大的差别,现总结经验如下,freebsd是比较好的规范程式代码的方案,他所正确运行的代码在其他平台下都能正确的运行,而cygwin环境下的最为自由,当然,以语言比较而言,刚才上述代码在C++里面都可以正确运行,说明C++容错性或者扩展性比C强。