Подтвердить что ты не робот

Удаление пространств из строки в C?

Что является самым простым и эффективным способом удаления пробелов из строки в C?

4b9b3361

Ответ 1

Самый простой и эффективный, как правило, не идут вместе...

Вот возможное решение:

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

Ответ 2

Здесь очень компактная, но совершенно правильная версия:

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

И здесь, только для моего развлечения, версии с кодовым полом, которые не совсем правильны, и расстраивают комментаторов.

Если вы можете рисковать каким-то образом undefined и никогда не иметь пустых строк, вы можете избавиться от тела:

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

Черт, если по пространству вы имеете в виду только пробел:

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

Не используйте это в процессе производства:)

Ответ 3

Как видно из ответов, это удивительно не тривиальная задача. Когда вы столкнулись с такой задачей, казалось бы, многие программисты предпочитают бросать здравый смысл из окна, чтобы создать самый неясный фрагмент, который они могут придумать.

Что нужно учитывать:

  • Вам нужно будет сделать копию строки с удаленными пробелами. Изменение переданной строки является плохой практикой, это может быть строковый литерал. Кроме того, иногда возникают преимущества обработки строк как неизменяемые объекты.
  • Вы не можете предположить, что исходная строка не пуста. Он может содержать только один символ нулевого завершения.
  • Буфер назначения может содержать любой неинициализированный мусор при вызове функции. Проверка на нулевое завершение не имеет никакого смысла.
  • Документация по исходному коду должна указывать на то, что буфер назначения должен быть достаточно большим, чтобы содержать обрезанную строку. Самый простой способ сделать это - сделать его таким же большим, как необработанная строка.
  • Буфер назначения должен содержать строку с нулевым завершением без пробелов, когда функция выполнена.
  • Рассмотрим, хотите ли вы удалить все пробелы или пробелы ' '.
  • 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, который является контрактом между программистом и компилятором, где программист гарантирует, что адресат и источник не совпадают с адресом (а точнее, что данные, на которые они указывают, доступны только через этот самый указатель, а не через какой-либо другой указатель). Это обеспечивает более эффективную оптимизацию, поскольку компилятор затем может копировать прямо из источника в пункт назначения без временной памяти между ними.

Ответ 4

В 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);

Вы можете понять, почему люди изобретали другие языки;)

Ответ 5

#include <ctype>

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

Примечание;

  • Это не обрабатывает Юникод.

Ответ 6

если вы все еще заинтересованы, эта функция удаляет пробелы с начала строки, и я просто использовал ее в своем коде:

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

Ответ 7

Самый простой и эффективный способ удаления пробелов из строки - просто удалить пробелы из строкового литерала. Например, используйте ваш редактор, чтобы "найти и заменить" "hello world" с помощью "helloworld" и presto!

Хорошо, я знаю, что не то, что вы имели в виду. Не все строки взяты из строковых литералов, не так ли? Предположим, что эта строка, в которой вы хотите удалить пробелы, не получается из строкового литерала, нам нужно рассмотреть источник и назначение вашей строки... Нам нужно рассмотреть весь ваш алгоритм, какую фактическую проблему вы пытаетесь решить, в чтобы предложить самые простые и оптимальные методы.

Возможно, ваша строка поступает из файла (например, stdin) и должна быть записана в другой файл (например, stdout). Если это произойдет, я бы поставил под вопрос, почему это когда-либо должно стать струной в первую очередь. Просто относитесь к нему так, как будто это поток персонажей, отбрасывая пробелы, когда вы сталкиваетесь с ними...

#include <stdio.h>

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

Исключая необходимость хранения строки, не только вся программа становится намного, намного короче, но теоретически также намного более эффективной.

Ответ 8

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

Ответ 9

Я предполагаю, что строка C находится в фиксированной памяти, поэтому, если вы заменяете пробелы, вы должны переместить все символы.

Самое простое - создать новую строку и перебрать ее по исходному и скопировать только не пробельные символы.

Ответ 10

Что самое легкое, о котором я мог думать (TESTED), и он работает!!

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

Ответ 11

void spaces_be_gone(char *str)
{
    char *p = --str;
    do while (*++p == ' ');
    while (*++str = *p);
}

Ответ 12

Код, взятый из библиотеки 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

У вас есть llok в коде zString, вы можете найти его полезным https://github.com/fnoyanisi/zString

Ответ 13

Я столкнулся с вариацией этого вопроса, когда вам нужно уменьшить количество пробелов в одном пространстве, "представить" пробелы.

Это мое решение:

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

Надеюсь, что это поможет: -)