簡體   English   中英

從 C 中的字符串中刪除空格

[英]Remove spaces from a string in C

從 C 中的字符串中刪除空格的最簡單和最有效的方法是什么?

最簡單和最有效的方法通常不會同時存在……

這是就地移除的可能解決方案:

void remove_spaces(char* s) {
    char* d = s;
    do {
        while (*d == ' ') {
            ++d;
        }
    } while (*s++ = *d++);
}

這是一個非常緊湊但完全正確的版本:

do while(isspace(*s)) s++; while(*d++ = *s++);

在這里,只是為了我的娛樂,代碼高爾夫版本不完全正確,讓評論者感到不安。

如果你可以冒險一些未定義的行為,並且永遠不會有空字符串,你可以擺脫身體:

while(*(d+=!isspace(*s++)) = *s);

哎呀,如果你說的空格只是空格字符:

while(*(d+=*s++!=' ')=*s);

不要在生產中使用它:)

正如我們從發布的答案中看到的那樣,這令人驚訝地不是一項微不足道的任務。 當面對這樣的任務時,似乎許多程序員選擇將常識拋諸腦后,以產生他們可能想出的最晦澀的片段。

需要考慮的事項:

  • 您需要復制該字符串,並刪除空格。 修改傳遞的字符串是不好的做法,它可能是字符串文字。 此外,將字符串視為不可變對象有時也有好處。
  • 您不能假設源字符串不為空。 它可能只包含一個空終止字符。
  • 調用函數時,目標緩沖區可以包含任何未初始化的垃圾。 檢查它是否為空終止沒有任何意義。
  • 源代碼文檔應說明目標緩沖區需要足夠大以包含修剪后的字符串。 最簡單的方法是使它與未修剪的字符串一樣大。
  • 當函數完成時,目標緩沖區需要保存一個沒有空格的空終止字符串。
  • 考慮是否要刪除所有空白字符或僅刪除空格' '
  • C 編程不是關於誰能在一行中擠入盡可能多的運算符的競爭。 恰恰相反,一個好的 C 程序包含可讀的代碼(始終是最重要的質量),而不會犧牲程序效率(有些重要)。
  • 出於這個原因,通過讓目標字符串成為復制代碼的一部分來隱藏目標字符串的空終止插入,您不會獲得任何獎勵積分。 相反,讓空終止插入顯式,以表明您不是偶然地設法做到了正確。

我會怎么做:

void remove_spaces (char* restrict str_trimmed, const char* restrict str_untrimmed)
{
  while (*str_untrimmed != '\0')
  {
    if(!isspace(*str_untrimmed))
    {
      *str_trimmed = *str_untrimmed;
      str_trimmed++;
    }
    str_untrimmed++;
  }
  *str_trimmed = '\0';
}

在此代碼中,源字符串“str_untrimmed”保持不變,這是通過使用適當的常量正確性來保證的。 如果源字符串只包含一個空終止符,它不會崩潰。 它始終為 null 終止目標字符串。

內存分配留給調用者。 該算法應該只專注於完成其預期的工作。 它刪除所有空格。

代碼中沒有任何微妙的技巧。 它不會試圖在一行中擠入盡可能多的運算符。 它將成為IOCCC 的一個非常糟糕的候選人。 然而,它將產生與更晦澀的單行版本幾乎相同的機器代碼。

但是,在復制某些內容時,您可以通過將兩個指針聲明為restrict來優化一點,這是程序員和編譯器之間的契約,程序員保證目標和源地址不同。 這允許更有效的優化,因為編譯器可以直接從源復制到目標,中間沒有臨時內存。

在 C 中,您可以就地替換一些字符串,例如 strdup() 返回的字符串:

char *str = strdup(" a b c ");

char *write = str, *read = str;
do {
   if (*read != ' ')
       *write++ = *read;
} while (*read++);

printf("%s\n", str);

其他字符串是只讀的,例如那些在代碼中聲明的字符串。 您必須將它們復制到新分配的內存區域並通過跳過空格來填充副本:

char *oldstr = " a b c ";

char *newstr = malloc(strlen(oldstr)+1);
char *np = newstr, *op = oldstr;
do {
   if (*op != ' ')
       *np++ = *op;
} while (*op++);

printf("%s\n", newstr);

你可以明白為什么人們發明了其他語言;)

如果您仍然感興趣,這個函數會從字符串的開頭刪除空格,我只是讓它在我的代碼中工作:

void removeSpaces(char *str1)  
{
    char *str2; 
    str2=str1;  
    while (*str2==' ') str2++;  
    if (str2!=str1) memmove(str1,str2,strlen(str2)+1);  
}
#include <ctype>

char * remove_spaces(char * source, char * target)
{
     while(*source++ && *target)
     {
        if (!isspace(*source)) 
             *target++ = *source;
     }
     return target;
}

筆記;

  • 這不處理 Unicode。

從字符串中刪除空格的最簡單最有效的方法是簡單地從字符串文字中刪除空格。 例如,使用您的編輯器將"hello world" “查找並替換"hello world""helloworld" ,然后就可以了!

好吧,我知道你不是這個意思。 並非所有字符串都來自字符串文字,對嗎? 假設您想要從中刪除空格的這個字符串不是來自字符串文字,我們需要考慮您的字符串的來源和目的地......我們需要考慮您的整個算法,您試圖解決的實際問題,在為了建議最簡單和最優化的方法。

也許您的字符串來自一個文件(例如stdin )並且必然會被寫入另一個文件(例如stdout )。 如果是這樣的話,我會質疑為什么它首先需要成為一個字符串。 只要把它當作一個字符流,當你遇到它們時丟棄空格......

#include <stdio.h>

int main(void) {
    for (;;) {
        int c = getchar();
        if (c == EOF) { break;    }
        if (c == ' ') { continue; }
        putchar(c);
    }
}

通過消除存儲字符串的需要,整個程序不僅變得短,而且理論上也更高效。

#include<stdio.h>
#include<string.h>
main()
{
  int i=0,n;
  int j=0;
  char str[]="        Nar ayan singh              ";
  char *ptr,*ptr1;
  printf("sizeof str:%ld\n",strlen(str));
  while(str[i]==' ')
   {
     memcpy (str,str+1,strlen(str)+1);
   }
  printf("sizeof str:%ld\n",strlen(str));
  n=strlen(str);
  while(str[n]==' ' || str[n]=='\0')
    n--;
  str[n+1]='\0';
  printf("str:%s ",str);
  printf("sizeof str:%ld\n",strlen(str));
}

代碼取自 zString 庫

/* search for character 's' */
int zstring_search_chr(char *token,char s){
        if (!token || s=='\0')
        return 0;

    for (;*token; token++)
        if (*token == s)
            return 1;

    return 0;
}

char *zstring_remove_chr(char *str,const char *bad) {
    char *src = str , *dst = str;

    /* validate input */
    if (!(str && bad))
        return NULL;

    while(*src)
        if(zstring_search_chr(bad,*src))
            src++;
        else
            *dst++ = *src++;  /* assign first, then incement */

    *dst='\0';
    return str;
}

代碼示例

  Exmaple Usage
      char s[]="this is a trial string to test the function.";
      char *d=" .";
      printf("%s\n",zstring_remove_chr(s,d));

  Example Output
      thisisatrialstringtotestthefunction

對 zString 代碼有一個 llok,你可能會發現它很有用https://github.com/fnoyanisi/zString

這是我能想到的最簡單的(已測試)並且它有效!!

char message[50];
fgets(message, 50, stdin);
for( i = 0, j = 0; i < strlen(message); i++){
        message[i-j] = message[i];
        if(message[i] == ' ')
            j++;
}
message[i] = '\0';

這是我能想到的最簡單的事情。 請注意,該程序使用第二個命令行參數(argv[1])作為刪除空格的行。

#include <string.h>
#include <stdio.h>
#include <stdlib.h>

/*The function itself with debug printing to help you trace through it.*/

char* trim(const char* str)
{
    char* res = malloc(sizeof(str) + 1);
    char* copy = malloc(sizeof(str) + 1);
    copy = strncpy(copy, str, strlen(str) + 1);
    int index = 0;

    for (int i = 0; i < strlen(copy) + 1; i++) {
        if (copy[i] != ' ')
        {
            res[index] = copy[i];
            index++;
        }
        printf("End of iteration %d\n", i);
        printf("Here is the initial line: %s\n", copy);
        printf("Here is the resulting line: %s\n", res);
        printf("\n");
    }
    return res;
}

int main(int argc, char* argv[])
{
    //trim function test

    const char* line = argv[1];
    printf("Here is the line: %s\n", line);

    char* res = malloc(sizeof(line) + 1);
    res = trim(line);

    printf("\nAnd here is the formatted line: %s\n", res);

    return 0;
}
/* Function to remove all spaces from a given string.
   https://www.geeksforgeeks.org/remove-spaces-from-a-given-string/
*/
void remove_spaces(char *str)
{
    int count = 0;
    for (int i = 0; str[i]; i++)
        if (str[i] != ' ')
            str[count++] = str[i];
    str[count] = '\0';
}

這是在微控制器中實現的,它可以工作,它應該避免所有問題,這不是一個聰明的方法,但它會工作:)

void REMOVE_SYMBOL(char* string, uint8_t symbol)
{
  uint32_t size = LENGHT(string); // simple string length function, made my own, since original does not work with string of size 1
  uint32_t i = 0;
  uint32_t k = 0;
  uint32_t loop_protection = size*size; // never goes into loop that is unbrakable
  while(i<size)
  {
    if(string[i]==symbol)
    {
      k = i;
      while(k<size)
      {
        string[k]=string[k+1];
        k++;
      }
    }
    if(string[i]!=symbol)
    {
      i++;
    }
    loop_protection--;
    if(loop_protection==0)
    {
      i = size;
      break;
    }
  }
}

雖然這不像其他答案那么簡潔,但對於 C 的新手來說,理解它是非常簡單的,改編自 Calculix 源代碼。

char* remove_spaces(char * buff, int len)
{
    int i=-1,k=0;
    while(1){
        i++;
        if((buff[i]=='\0')||(buff[i]=='\n')||(buff[i]=='\r')||(i==len)) break;
        if((buff[i]==' ')||(buff[i]=='\t')) continue;
        buff[k]=buff[i];
        k++;
    }
    buff[k]='\0';
    return buff;
}

我假設 C 字符串在固定內存中,因此如果替換空格,則必須移動所有字符。

最簡單的似乎是創建新字符串並迭代原始字符串並僅復制非空格字符。

我遇到了這個問題的一個變體,您需要將多個空格減少為一個“代表”空格的空格。

這是我的解決方案:

char str[] = "Put Your string Here.....";

int copyFrom = 0, copyTo = 0;

printf("Start String %s\n", str);

while (str[copyTo] != 0) {
    if (str[copyFrom] == ' ') {
        str[copyTo] = str[copyFrom];
        copyFrom++;
        copyTo++;

        while ((str[copyFrom] == ' ') && (str[copyFrom] !='\0')) {
            copyFrom++;
        }
    }

    str[copyTo] = str[copyFrom];

    if (str[copyTo] != '\0') {
        copyFrom++;
        copyTo++;
    }
}

printf("Final String %s\n", str);

希望能幫助到你 :-)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM