IT이야기

C의 모든 공백에서 문자열 분할

cyworld 2021. 9. 15. 21:17
반응형

C의 모든 공백에서 문자열 분할


전체 문장(입력으로 사용)의 각 단어를 별도의 줄에 표시하는 프로그램을 C로 작성하고 싶습니다. 이것이 내가 지금까지 한 일입니다.


void manipulate(char *buffer);
int get_words(char *buffer);

int main(){
    char buff[100];

    printf("sizeof %d\nstrlen %d\n", sizeof(buff), strlen(buff));   // Debugging reasons

    bzero(buff, sizeof(buff));

    printf("Give me the text:\n");
    fgets(buff, sizeof(buff), stdin);

    manipulate(buff);
    return 0;
}

int get_words(char *buffer){                                        // Function that gets the word count, by counting the spaces.
    int count;
    int wordcount = 0;
    char ch;

    for (count = 0; count < strlen(buffer); count ++){
        ch = buffer[count];
        if((isblank(ch)) || (buffer[count] == '\0')){                   // if the character is blank, or null byte add 1 to the wordcounter
            wordcount += 1;
        }
    }
    printf("%d\n\n", wordcount);
    return wordcount;
}

void manipulate(char *buffer){
    int words = get_words(buffer);
    char *newbuff[words];
    char *ptr;
    int count = 0;
    int count2 = 0;
    char ch = '\n';

    ptr = buffer;
    bzero(newbuff, sizeof(newbuff));

    for (count = 0; count < 100; count ++){
        ch = buffer[count];
        if (isblank(ch) || buffer[count] == '\0'){
            buffer[count] = '\0';
            if((newbuff[count2] = (char *)malloc(strlen(buffer))) == NULL) {
                printf("MALLOC ERROR!\n");
                exit(-1);
            }
            strcpy(newbuff[count2], ptr);
            printf("\n%s\n",newbuff[count2]);
            ptr = &buffer[count + 1];
            count2 ++;
        }
    }
}

출력이 내가 원하는 것이지만 표시된 마지막 단어 뒤에 정말 많은 공백이 있고 malloc()이 NULL을 반환하므로 MALLOC ERROR! 마지막에 표시됩니다. 내 malloc() 구현에 실수가 있다는 것을 이해할 수 있지만 그것이 무엇인지 모르겠습니다.

더 우아하고 일반적으로 더 나은 방법이 있습니까?

미리 감사드립니다.


http://www.cplusplus.com/reference/clibrary/cstring/strtok/

이것을 살펴보고 공백 문자를 구분 기호로 사용하십시오. 힌트가 더 필요하면 알려주십시오.

웹사이트에서:

char * strtok ( char * str, const char * delimiters );

첫 번째 호출에서 함수는 첫 번째 문자가 토큰 스캔을 위한 시작 위치로 사용되는 str에 대한 인수로 C 문자열을 예상합니다. 후속 호출에서 함수는 널 포인터를 예상하고 마지막 토큰 끝 바로 뒤의 위치를 ​​스캔을 위한 새 시작 위치로 사용합니다.

strtok에 대한 호출에서 str의 종료 널 문자가 발견되면 이 함수에 대한 모든 후속 호출(첫 번째 인수로 널 포인터 사용)은 널 포인터를 리턴합니다.

매개변수

  • str
    • 자를 C 문자열입니다.
    • 이 문자열은 더 작은 문자열(토큰)로 나누어 수정됩니다. 또는 [원문 그대로], 널 포인터가 지정될 수 있으며, 이 경우 함수는 이전에 성공한 함수 호출이 종료된 위치를 계속 검색합니다.
  • 구분 기호
    • 구분 문자가 포함된 C 문자열입니다.
    • 이는 호출마다 다를 수 있습니다.

반환 값

string에서 찾은 마지막 토큰에 대한 포인터입니다. 검색할 토큰이 남아 있지 않으면 null 포인터가 반환됩니다.

예시

/* strtok example */
#include <stdio.h>
#include <string.h>

int main ()
{
  char str[] ="- This, a sample string.";
  char * pch;
  printf ("Splitting string \"%s\" into tokens:\n",str);
  pch = strtok (str," ,.-");
  while (pch != NULL)
  {
    printf ("%s\n",pch);
    pch = strtok (NULL, " ,.-");
  }
  return 0;
}

재미를 위해 다음은 콜백 접근 방식을 기반으로 한 구현입니다.

const char* find(const char* s,
                 const char* e,
                 int (*pred)(char))
{
    while( s != e && !pred(*s) ) ++s;
    return s;
}

void split_on_ws(const char* s,
                 const char* e,
                 void (*callback)(const char*, const char*))
{
    const char* p = s;
    while( s != e ) {
        s = find(s, e, isspace);
        callback(p, s);
        p = s = find(s, e, isnotspace);
    }
}

void handle_word(const char* s, const char* e)
{
    // handle the word that starts at s and ends at e
}

int main()
{
    split_on_ws(some_str, some_str + strlen(some_str), handle_word);
}

malloc(0)NULL구현에 따라 (선택적으로) 반환할 수 있습니다 . 왜 전화를 했는지 malloc(0)아십니까? 또는 더 정확하게는 배열의 크기 이상으로 읽고 쓰는 위치가 보이나요?


strtok_r다른 사람들이 제안한 대로 , 또는 다음과 같은 것을 사용하는 것을 고려하십시오 .

void printWords(const char *string) {
    // Make a local copy of the string that we can manipulate.
    char * const copy = strdup(string);
    char *space = copy;
    // Find the next space in the string, and replace it with a newline.
    while (space = strchr(space,' ')) *space = '\n';
    // There are no more spaces in the string; print out our modified copy.
    printf("%s\n", copy);
    // Free our local copy
    free(copy);
}

문제가 발생하면 get_words()항상 실제 단어 수보다 하나 적은 값을 반환하므로 결국 다음을 시도합니다.

char *newbuff[words]; /* Words is one less than the actual number,
so this is declared to be too small. */

newbuff[count2] = (char *)malloc(strlen(buffer))

count2, 결국 은 항상 에 대해 선언한 요소 수보다 하나 더 많습니다 newbuff[]. malloc()유효한 ptr을 반환하지 않는지 모르겠습니다.


strlen(buf)이 아니라 strlen(ptr)을 malloc해야 합니다. 또한 count2는 단어 수로 제한되어야 합니다. 문자열의 끝에 도달하면 버퍼의 0을 계속 살펴보고 배열에 크기가 0인 문자열을 추가합니다.


C에서 다른 스타일의 문자열 조작에 대한 아이디어처럼 소스 문자열을 수정하지 않고 malloc. 공백을 찾으려면 libc 함수를 사용합니다 strpbrk.

int print_words(const char *string, FILE *f)
{
   static const char space_characters[] = " \t";
   const char *next_space;

   // Find the next space in the string
   //
   while ((next_space = strpbrk(string, space_characters)))
   {
      const char *p;

      // If there are non-space characters between what we found
      // and what we started from, print them.
      //
      if (next_space != string)
      {
         for (p=string; p<next_space; p++)
         {
            if(fputc(*p, f) == EOF)
            {
               return -1;
            }
         }

         // Print a newline
         //
         if (fputc('\n', f) == EOF)
         {
            return -1;
         }
      }

      // Advance next_space until we hit a non-space character
      //
      while (*next_space && strchr(space_characters, *next_space))
      {
         next_space++;
      }

      // Advance the string
      //
      string = next_space;
   }

   // Handle the case where there are no spaces left in the string
   //
   if (*string)
   {
      if (fprintf(f, "%s\n", string) < 0)
      {
         return -1;
      }
   }

   return 0;
}

char arr[50];
gets(arr);
int c=0,i,l;
l=strlen(arr);

    for(i=0;i<l;i++){
        if(arr[i]==32){
            printf("\n");
        }
        else
        printf("%c",arr[i]);
    }

ReferenceURL : https://stackoverflow.com/questions/4513316/split-string-in-c-every-white-space

반응형