我刚刚阅读本页http://www.cs.tut.fi/~jkorpela/forms/cgic.html关于在C中开始使用CGI。我对未编码部分的代码有疑问。
#include <stdio.h>
#include <stdlib.h>
#define MAXLEN 80
#define EXTRA 5
/* 4 for field name "data", 1 for "=" */
#define MAXINPUT MAXLEN+EXTRA+2
/* 1 for added line break, 1 for trailing NUL */
#define DATAFILE "../data/data.txt"
void unencode(char *src, char *last, char *dest)
{
for(; src != last; src++, dest++)
if(*src == '+')
*dest = ' ';
else if(*src == '%') {
int code;
if(sscanf(src+1, "%2x", &code) != 1) code = '?';
*dest = code;
src +=2; }
else
*dest = *src;
*dest = '\n';
*++dest = '\0';
}
int main(void)
{
char *lenstr;
char input[MAXINPUT], data[MAXINPUT];
long len;
printf("%s%c%c\n",
"Content-Type:text/html;charset=iso-8859-1",13,10);
printf("<TITLE>Response</TITLE>\n");
lenstr = getenv("CONTENT_LENGTH");
if(lenstr == NULL || sscanf(lenstr,"%ld",&len)!=1 || len > MAXLEN)
printf("<P>Error in invocation - wrong FORM probably.");
else {
FILE *f;
fgets(input, len+1, stdin);
unencode(input+EXTRA, input+len, data);
f = fopen(DATAFILE, "a");
if(f == NULL)
printf("<P>Sorry, cannot store your data.");
else
fputs(data, f);
fclose(f);
printf("<P>Thank you! Your contribution has been stored.");
}
return 0;
}
我想知道这些线是怎么回事:
else if(*src == '%') {
int code;
if(sscanf(src+1, "%2x", &code) != 1) code = '?';
*dest = code;
src +=2; }
将%21之类的内容转换回感叹号?
谢谢!
答案 0 :(得分:1)
else if(*src == '%') { int code; if(sscanf(src+1, "%2x", &code) != 1) code = '?'; *dest = code; src +=2; }
如果字符串以%
字符开头,sscanf()
用于解析以下十六进制字符。 "%x"
格式将十六进制字符转换为整数值(在本例中为字符代码),2
指定最大字段宽度,以便最多消耗 2个字符。
sscanf()
的返回值表示成功转换的次数,因此如果它不返回1
,则找不到有效的十六进制数。
然后将字符代码分配给*dest
,并将src
指针提前指向%xx
序列之后的下一个字符。
这里实际上有三个错误:
"%x"
格式说明符需要unsigned int *
类型的参数。传递了signed int *
,我相信,它会调用未定义的行为。变量函数(例如sscanf()
)具有传递参数的不同方式,并且要求格式说明符与参数的类型匹配。
然而,这两种类型足够相似,在实践中可能会很好。
它还接受签名的十六进制数字(带有+
或-
字符),这可能不是作者想要的。
例如,"%-ffText"
会产生code == -15
。
src
指针前进2个字节,但scanf()
不一定消耗2个字符。
"%fText"
将导致code == 15
,并且只消耗一个字符(%
字符除外)。上面的示例将消耗3个字符。
答案 1 :(得分:0)
sscanf函数将2个十六进制字符转换为单个int值。该值等于ASCII值,因此放入&#39; dest&#39;。由于已经解码了2个字符,因此src必须增加两个位置。 所以&#39;%21&#39; - &GT; 0x21 - &gt; char&#39;!&#39;