【问题标题】:Replacing spaces with %20 in C在 C 中用 %20 替换空格
【发布时间】:2010-08-07 00:38:45
【问题描述】:

我正在用 C 为我的网站编写一个 fastcgi 应用程序。不要问为什么,留下所有部分。

请帮我解决这个问题 - 我想用 %20 替换查询字符串中的空格。 这是我正在使用的代码,但我在输出中看不到 20,只有 %.问题出在哪里?

代码:

unsigned int i = 0;

/*
 * Replace spaces with its hex %20
 * It will be converted back to space in the actual processing
 * They make the application segfault in strtok_r()
 */

char *qstr = NULL;
for(i = 0; i <= strlen(qry); i++) {
  void *_tmp;
  if(qry[i] == ' ') {
    _tmp = realloc(qstr, (i + 2) * sizeof(char));
    if(!_tmp) error("realloc() failed while allocting string memory (space)\n");
    qstr = (char *) _tmp;
    qstr[i] = '%'; qstr[i + 1] = '2'; qstr[i + 2] = '0';
  } else {
    _tmp = realloc(qstr, (i + 1) * sizeof(char));
    if(!_tmp) error("realloc() failed while allocating string memory (not space)\n");
    qstr = (char *) _tmp;
    qstr[i] = qry[i];
  }
}

在代码中,qry 是 char *,作为函数的实际参数。 我尝试在空间替换块中的 realloc() 中使用 i + 3, 4, 5,但没有成功。

【问题讨论】:

  • 要使您的代码正常工作,您必须将i += 2 添加到 if 语句的主体中。但是,下面我的答案中的代码避免了您陷入的其他一些 C 字符串处理陷阱。

标签: c http


【解决方案1】:

C 中的字符串处理可能很棘手。我建议先检查字符串,计算空格,然后分配适当大小的新字符串(原始字符串大小 +(空格数 * 2))。然后,遍历原始字符串,维护指向新字符串和原始字符串中位置的指针(或索引)。 (为什么是两个指针?因为每次遇到空格,指向新字符串的指针都会比指向旧字符串的指针提前两个字符。)

这里有一些代码应该可以解决问题:

int new_string_length = 0;
for (char *c = qry; *c != '\0'; c++) {
    if (*c == ' ') new_string_length += 2;
    new_string_length++;
}
char *qstr = malloc((new_string_length + 1) * sizeof qstr[0]);
char *c1, *c2;
for (c1 = qry, c2 = qstr; *c1 != '\0'; c1++) {
    if (*c1 == ' ') {
        c2[0] = '%';
        c2[1] = '2';
        c2[2] = '0';
        c2 += 3;
    }else{
        *c2 = *c1;
        c2++;
    }
}
*c2 = '\0';

【讨论】:

  • 如果速度优先于内存,请分配一个 3 倍于原始字符串空间的字符串,并跳过搜索空格以确定新字符串的长度。就像在康坎的答案中的链接中找到的方法一样。
  • 好方法,但你分配的字符串太短了一个字符(你不计算尾随的'\0'),所以最好以int new_string_length = 1;开头。
  • @x4u:哎呀!现在修好了。 (虽然我选择更改 malloc 调用而不是 new_string_length 的初始值,因此 new_string_length 的名称仍然适合其用途。)
  • @Daniel - 为什么分配块 3 倍于原始字符串的空间会更快? strlen() 无论如何都必须遍历字符串 - 为什么不像 David 的解决方案那样在处理时自己迭代并考虑空格? strlen() 可能比自己迭代要快一点,但我敢打赌,除非你的字符串真的非常长,否则这种差异很难衡量。
  • @Michael - 对不起,我的错误,我脑子里已经知道字符串的长度了。你是对的:)
【解决方案2】:
qstr[i] = '%'; qstr[i + 1] = '2'; qstr[i + 2] = '0'; 

该行将三个字符写入您的输出缓冲区,因此您写入的下一个字符需要写入 qstr[i+3]。但是,您只需将 i 步进 1,因此下一个字符将写入 qstr[i+1],从而覆盖 '2'。

您需要保留单独的索引以单步执行qryqstr

【讨论】:

    【解决方案3】:

    我同意大卫的观点。

    建议分两步进行:在第一个循环中,您只需计算空格:

    int spaceCounter=0;
    const int sourceLen = strlen(qry);
    for(int i = 0; i < sourceLen; ++i) 
        if ( qry[i] == ' ')
            ++spaceCounter;
    
    char* newString = (char*)malloc(sourceLen + 3*spaceCounter*sizeof(char) + 1)
    //check for null!
    for(int i = 0; i < sourceLen; ++i) 
        if ( qry[i] == ' ')
        {
            *newString++ = '%';
            *newString++ = '2';
            *newString++ = '0';
        }
        else
            *newString++ = qry[i];
    
    *newString = '\0';
    

    警告:代码未经测试。

    【讨论】:

    • 请注意,标准要求sizeof(char) 为1。
    • 另外,你在 newString 中加入了一个空格,这有点违背了这个函数的目的。它应该只添加三个字符%20
    • @James:虽然你是对的,但我认为这里可能的意图可能是让它更易于移植到 Unicode。
    • sizeof(char) 始终为 1。sizeof 以 char 形式定义。 char 可以是 8 个 9 位字节,但 sizeof(char) 仍然是 1。 Unicode 与 sizeof(char) 无关。
    • sizeof(char) 在 c/c++ 中永远不能为 2。标准要求为 1。sizeof(wchar_t) 可能为 2。
    【解决方案4】:

    您使用相同的计数器进行分配,因为字符串的长度不同,您需要 2 个计数器

    你的 else 情况分配 qstr[i] = qry[i];在你写完 %20 之后,你在结果字符串上至少偏离了 2。

    【讨论】:

      【解决方案5】:

      这称为 url 编码。你可以参考这个页面查看一些类似的实现:http://www.geekhideout.com/urlcode.shtml

      【讨论】:

      • 哦,没有人。我对 C 很陌生,我想学习而不是使用一些预定义的东西。
      【解决方案6】:
      char* toHexSpace(const char *s)
      {
        char *b=strcpy(malloc(3*strlen(s)+1),s),*p;
        while( p=strchr(b,' ') )
        {
          memmove(p+3,p+1,strlen(p));
          strncpy(p,"%20",3);
        }
        return b; 
      }
      

      在调用上下文中需要“空闲”。

      【讨论】:

        猜你喜欢
        • 2010-12-03
        • 1970-01-01
        • 2012-07-22
        • 2018-01-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多