remove spaces from char* array in C

浪子不回头ぞ 提交于 2021-01-27 17:51:20

问题


I am working on a plugin in C for a game emulator, where I would like to remove all spaces from chat message before checking if the input messages contain any website urls.

So, I have this function like this to deblank (remove spaces from input message):

char* deblank(char* input) {
    int i, j;
    char *output = input;
    for (i = 0, j = 0; i < strlen(input); i++, j++) {
        if (input[i] != ' ')
            output[j] = input[i];
        else
            j--;
    }
    output[j] = 0;
    return output;
}

I use it in my plugin hook like this:

bool my_pc_process_chat_message(bool retVal___, struct map_session_data *sd, const char *message) {
    if (retVal___ == true) {
        char* check_message = deblank(message);
        bool url_detected = (stristr(check_message, "://") || stristr(check_message, "www.") || stristr(check_message, "vvvvvv.") || stristr(check_message, "wvvw."));
        if (!url_detected) {
            int len = sizeof(tld_list) / sizeof(tld_list[0]);
            int i;
            for (i = 0; i < len; ++i) {
                if (stristr(check_message, tld_list[i])) {
                    url_detected = true;
                    break;
                }
            }
        }
        if (url_detected) {
            clif->messagecolor_self(sd->fd, COLOR_RED, "Possible GM Impersonation Detected - you cannot type website URLs in chat.");
            return false;
        }
    }
    return retVal___;
}

The above works, but there's a side-effect. What seems to be happening is that the input message is getting modified and all spaces from the message being removed, when it doesn't contain any website urls.

For example, if I typed:

Go to www.some-domain.com

The above get's blocked, So does this (when players try to be clever and use spaces):

w w w . s o m e - d o m a i n . c o m

However, when you type a normal message that doesn't contain any website urls like this:

Hello, how are you?

It's getting turned into the following:

Hello,howareyou?

This is because of this line: char* check_message = deblank(message); The deblank function appears to be modifying the original message. I thought the function would return a new copy of the orignal message, without spaces.

Is there a way I can make a temporary copy of the original input message, remove spaces from that, before doing my check?

Also, how do you clear allocated memory to the temp copy of the orignal input? I don't want this to linger around. Or does C automatically clears that temp char array once the code finishes it's execution in the scope?


回答1:


No, you can't actually do that.

There are two solutions: - Loop the string a first time to count how many non-space characters there are, so you know how much you need to allocate.

int count_not_empty(const char *str)
{
  int n = 0;

  for (; *str; ++str) {
    if (*str != ' ') n++;
  }
  return n + 1; // the +1 is for the nulbyte at the end
}
  • Allocate a string as big as the one you want to trim, and pad with nulbytes at the end.

i.e.

char *copy_not_empty(const char *str)
{
  size_t i;
  size_t j;
  char *new = malloc(strlen(str) + 1);

  for (i = j = 0; i < strlen(str); ++i)
  {
    if (str[i] != ' ')
      new[j++] = str[i];
  }
  for (; j <= i; j++)
    new[j] = 0; // pad with nulbytes
  return new;
}




回答2:


Code broke the contract.

const char *message points to data that should be not modified. deblank(message) attempted to modified. it --> undefined behavior.

bool my_pc_process_chat_message(..., const char *message) {
  if (retVal___ == true) {
    char* check_message = deblank(message);

A properly warning enabled compiler would warn about this - saves you time.

For more detail and ideas, post the calling code to my_pc_process_chat_message().



来源:https://stackoverflow.com/questions/38543918/remove-spaces-from-char-array-in-c

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!