Ответ 1
Самый простой и эффективный, как правило, не идут вместе...
Вот возможное решение:
void remove_spaces(char* s) {
const char* d = s;
do {
while (*d == ' ') {
++d;
}
} while (*s++ = *d++);
}
Что является самым простым и эффективным способом удаления пробелов из строки в C?
Самый простой и эффективный, как правило, не идут вместе...
Вот возможное решение:
void remove_spaces(char* s) {
const char* d = s;
do {
while (*d == ' ') {
++d;
}
} while (*s++ = *d++);
}
Здесь очень компактная, но совершенно правильная версия:
do while(isspace(*s)) s++; while(*d++ = *s++);
И здесь, только для моего развлечения, версии с кодовым полом, которые не совсем правильны, и расстраивают комментаторов.
Если вы можете рисковать каким-то образом undefined и никогда не иметь пустых строк, вы можете избавиться от тела:
while(*(d+=!isspace(*s++)) = *s);
Черт, если по пространству вы имеете в виду только пробел:
while(*(d+=*s++!=' ')=*s);
Не используйте это в процессе производства:)
Как видно из ответов, это удивительно не тривиальная задача. Когда вы столкнулись с такой задачей, казалось бы, многие программисты предпочитают бросать здравый смысл из окна, чтобы создать самый неясный фрагмент, который они могут придумать.
Что нужно учитывать:
' '
.Что я буду делать:
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);
Вы можете понять, почему люди изобретали другие языки;)
#include <ctype>
char * remove_spaces(char * source, char * target)
{
while(*source++ && *target)
{
if (!isspace(*source))
*target++ = *source;
}
return target;
}
Примечание;
если вы все еще заинтересованы, эта функция удаляет пробелы с начала строки, и я просто использовал ее в своем коде:
void removeSpaces(char *str1)
{
char *str2;
str2=str1;
while (*str2==' ') str2++;
if (str2!=str1) memmove(str1,str2,strlen(str2)+1);
}
Самый простой и эффективный способ удаления пробелов из строки - просто удалить пробелы из строкового литерала. Например, используйте ваш редактор, чтобы "найти и заменить" "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);
}
}
Исключая необходимость хранения строки, не только вся программа становится намного, намного короче, но теоретически также намного более эффективной.
#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));
}
Я предполагаю, что строка C находится в фиксированной памяти, поэтому, если вы заменяете пробелы, вы должны переместить все символы.
Самое простое - создать новую строку и перебрать ее по исходному и скопировать только не пробельные символы.
Что самое легкое, о котором я мог думать (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';
void spaces_be_gone(char *str)
{
char *p = --str;
do while (*++p == ' ');
while (*++str = *p);
}
Код, взятый из библиотеки 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
Я столкнулся с вариацией этого вопроса, когда вам нужно уменьшить количество пробелов в одном пространстве, "представить" пробелы.
Это мое решение:
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);
Надеюсь, что это поможет: -)