programing

C 문자열에서 공백 제거

bestcode 2022. 8. 14. 12:02
반응형

C 문자열에서 공백 제거

C 문자열에서 공백을 제거하는 가장 쉽고 효율적인 방법은 무엇입니까?

가장 쉽고 효율이 뛰어난 제품은 일반적으로 함께 사용할 수 없습니다.

다음은 인플레이스 제거에 사용할 수 있는 솔루션입니다.

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

게시된 답변에서 알 수 있듯이, 이것은 의외로 간단한 작업이 아닙니다.이런 작업에 직면했을 때, 많은 프로그래머들은 그들이 생각해낼 수 있는 가장 모호한 조각을 만들기 위해 상식을 버리기를 선택하는 것 같습니다.

고려해야 할 사항:

  • 공백이 제거된 상태로 문자열 복사본을 만듭니다.전달된 문자열을 수정하는 것은 잘못된 관행입니다. 문자열 리터럴일 수 있습니다.또한 때로는 문자열을 불변의 객체로 취급하는 이점도 있습니다.
  • 소스 문자열이 비어 있지 않다고 가정할 수 없습니다.단일 Null 끝 문자만 포함할 수 있습니다.
  • 함수가 호출될 때 대상 버퍼에는 초기화되지 않은 가비지가 포함될 수 있습니다.null 종료를 확인하는 것은 의미가 없습니다.
  • 소스 코드 문서에는 대상 버퍼가 잘린 문자열을 포함할 수 있을 정도로 커야 한다고 기술되어 있어야 합니다.가장 쉬운 방법은 프레임되지 않은 문자열만큼 크게 만드는 것입니다.
  • 함수 실행 시 수신처 버퍼는 공백 없이 종료된 늘 문자열을 유지해야 합니다.
  • 인지 공백만 할 것인지를 합니다.' '.
  • C 프로그래밍은 가능한 한 많은 연산자를 한 줄에 끼워 넣을 수 있는 경쟁은 아닙니다.오히려 그 반대입니다.좋은 C 프로그램은 프로그램 효율을 희생하지 않고 판독 가능한 코드(항상 가장 중요한 단일 품질)를 포함합니다.
  • 따라서 복사 코드의 일부로서 행선지 문자열의 늘 끝 삽입을 숨김으로써 보너스 포인트를 얻을 수 없습니다.대신 Null 종단 삽입을 명시하여 실수로 제대로 된 삽입이 아님을 나타냅니다.

내가 하고 싶은 일:

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_untrimed"는 변경되지 않은 상태로 유지되며 적절한 const correctness를 사용함으로써 보증됩니다.소스 문자열에 null 끝만 포함되어 있는 경우 크래시는 발생하지 않습니다.행선지 문자열은 항상 null로 끝납니다.

메모리 할당은 발신자에게 맡겨집니다.알고리즘은 의도된 작업에만 초점을 맞춰야 합니다.모든 공백을 제거합니다.

코드에는 미묘한 트릭이 없습니다.한 줄에 가능한 한 많은 연산자를 삽입하려고 하지 않습니다.그것은 IOCC에 매우 좋지 않은 후보가 될 것이다.그러나 더 불분명한 원라이너 버전과 거의 동일한 기계 코드를 생성할 수 있습니다.

는 두 를 모두 '복사하다'로할 수 .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);

당신은 왜 사람들이 다른 언어를 발명했는지 알 수 있다;)

다음은 매우 콤팩트하지만 완전히 올바른 버전입니다.

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

그리고 여기 재미삼아 코드 골프 버전이 있습니다. 완전히 정확하지 않습니다. 논객들을 화나게 합니다.

정의되지 않은 동작을 감수하고 빈 문자열이 없는 경우 본문을 삭제할 수 있습니다.

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

헉, 만약 공간이 단지 공백 문자를 의미한다면:

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

그것을 실가동에서는 사용하지 말아 주세요:)

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 코드를 확인하세요.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);

도움이 되었으면 좋겠다:-)

문자열에서 공백을 제거하는 가장 쉽고 효율적인 방법은 문자열 리터럴에서 공백을 제거하는 것입니다.예를 들어, 에디터를 사용하여 '검색 및 치환'을 수행합니다."hello world""helloworld" , presto! , presto!

좋아, 그런 뜻이 아니란 거 알아.모든 현이 현 리터럴에서 나오는 건 아니죠?공백이 제거되는 문자열이 문자열 리터럴이 아닌 경우 문자열의 원본과 대상을 고려해야 합니다.가장 심플하고 최적의 방법을 제안하기 위해서는 알고리즘 전체를 고려해야 합니다.실제로 해결하려는 문제가 무엇인지도 고려해야 합니다.

문자열은 파일(예:stdin다른 파일(예:stdout그렇다면 왜 굳이 문자열이 되어야 하는지 의문입니다.마치 캐릭터의 흐름인 것처럼 대하고, 마주치면 그 공간을 버리고...

#include <stdio.h>

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

문자열을 저장할 필요가 없으므로 프로그램 전체가 훨씬 짧아질 뿐만 아니라 이론적으로도 훨씬 더 효율적입니다.

C 문자열은 고정 메모리에 있다고 생각하기 때문에 공백 치환 시 모든 문자를 옮겨야 합니다.

가장 쉬운 방법은 새 문자열을 만들고 원래 문자열을 반복하고 공백이 아닌 문자만 복사하는 것입니다.

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

내가 생각한 것 중 가장 쉬웠고 (테스트 완료) 효과가 있어!!

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

다른 답변만큼 간결하지는 않지만 Calcix 소스 코드를 사용하여 C를 처음 접하는 사람에게는 이해하기 쉽습니다.

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

언급URL : https://stackoverflow.com/questions/1726302/remove-spaces-from-a-string-in-c

반응형