简体   繁体   中英

Replacing spaces with %20 in C

I am writing a fastcgi application for my site in C. Don't ask why, leave all that part.

Just help me with this problem- I want to replace spaces in the query string with %20. Here's the code I'm using, but I don't see 20 in the output, only %. Where's the problem?

Code:

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];
  }
}

In the code, qry is char *, comes as a actual parameter to the function. I tried with i + 3, 4, 5 in realloc() in the space replacer block, no success.

String-handling in C can be tricky. I'd suggest going through the string first, counting the spaces, and then allocating a new string of the appropriate size (original string size + (number of spaces * 2)). Then, loop through the original string, maintaining a pointer (or index) to the position in both the new string and the original one. (Why two pointers? Because every time you encounter a space, the pointer into the new string will get two characters ahead of the pointer into the old one.)

Here's some code that should do the trick:

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';
qstr[i] = '%'; qstr[i + 1] = '2'; qstr[i + 2] = '0'; 

That line writes three characters to your output buffer, so the next character you write needs to be written at qstr[i+3]. However, you only step i by 1, so the next character is written to qstr[i+1], overwriting the '2'.

You will need to keep separate indexes for stepping through qry & qstr .

I agree with David.

It is advisable to do it in two-steps: in the first loop you just count the spaces:

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';

Warning: code not tested.

You are assigning using the same counter I you will need to have 2 counters since the strings have different lengths

your else case assigns qstr[i] = qry[i]; after you have written the %20 you are at least off by 2 on the result string.

This is known as url encode. You can refer to this page to see some similar implementation: http://www.geekhideout.com/urlcode.shtml

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; 
}

needs "free" in calling context.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM