programing

C에서 유니코드 문자열의 문자를 카운트하는 방법

itsource 2022. 8. 17. 21:41
반응형

C에서 유니코드 문자열의 문자를 카운트하는 방법

문자열이 있다고 칩시다.

char theString[] = "你们好āa";

인코딩이 utf-8인 경우 이 문자열은 12바이트입니다(3개의 한자는 각각 3바이트, 마크롱이 있는 라틴 문자는 2바이트, 'a'는 1바이트).

strlen(theString) == 12

글자 수는 어떻게 셀 수 있나요?서브스크립션과 동등한 기능을 사용하여 다음을 실현하려면 어떻게 해야 합니까?

theString[3] == "好"

어떻게 하면 이런 끈을 잘라낼 수 있을까?

사이즈는 다음과 같습니다.

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

// returns the number of utf8 code points in the buffer at s
size_t utf8len(char *s)
{
    size_t len = 0;
    for (; *s; ++s) if ((*s & 0xC0) != 0x80) ++len;
    return len;
}

// returns a pointer to the beginning of the pos'th utf8 codepoint
// in the buffer at s
char *utf8index(char *s, size_t pos)
{    
    ++pos;
    for (; *s; ++s) {
        if ((*s & 0xC0) != 0x80) --pos;
        if (pos == 0) return s;
    }
    return NULL;
}

// converts codepoint indexes start and end to byte offsets in the buffer at s
void utf8slice(char *s, ssize_t *start, ssize_t *end)
{
    char *p = utf8index(s, *start);
    *start = p ? p - s : -1;
    p = utf8index(s, *end);
    *end = p ? p - s : -1;
}

// appends the utf8 string at src to dest
char *utf8cat(char *dest, char *src)
{
    return strcat(dest, src);
}

// test program
int main(int argc, char **argv)
{
    // slurp all of stdin to p, with length len
    char *p = malloc(0);
    size_t len = 0;
    while (true) {
        p = realloc(p, len + 0x10000);
        ssize_t cnt = read(STDIN_FILENO, p + len, 0x10000);
        if (cnt == -1) {
            perror("read");
            abort();
        } else if (cnt == 0) {
            break;
        } else {
            len += cnt;
        }
    }

    // do some demo operations
    printf("utf8len=%zu\n", utf8len(p));
    ssize_t start = 2, end = 3;
    utf8slice(p, &start, &end);
    printf("utf8slice[2:3]=%.*s\n", end - start, p + start);
    start = 3; end = 4;
    utf8slice(p, &start, &end);
    printf("utf8slice[3:4]=%.*s\n", end - start, p + start);
    return 0;
}

샘플 실행:

matt@stanley:~/Desktop$ echo -n 你们好āa | ./utf8ops 
utf8len=5
utf8slice[2:3]=好
utf8slice[3:4]=ā

이 예에서는, 1 에러로 오프가 되어 있는 것에 주의해 주세요.theString[2] == "好"

.2비트로 않습니다.10 그 것)0x80 "" 큰"0xbf를 참조해 주세요.

는 상위 ""로 되어 있기 입니다.10UTF-8을 사용하다

인코딩 및 방법에 대한 설명은 여기를 참조하십시오.strlen【UTF-8】【UTF-8】【UTF-8】【UTF-8】【UTF-8】★★★★★★★★★★★★★★★★★★★★★★★」

UTF-8 스트링을 슬라이스 및 다이싱할 경우 기본적으로 동일한 규칙을 따라야 합니다.0 또는 11포인트의 이며, 그 의 모든 입니다.sequence ut UTF - 8 、 UTF - 8 、 UTF - 8 、 、 sequence sequence sequence sequence sequence sequence 。

서드파티제의 라이브러리를 사용하지 않는 경우는, 다음의 기능을 간단하게 제공하는 것이 최선입니다.

utf8left (char *destbuff, char *srcbuff, size_t sz);
utf8mid  (char *destbuff, char *srcbuff, size_t pos, size_t sz);
utf8rest (char *destbuff, char *srcbuff, size_t pos;

취득 방법:

  • szUTF-8
  • sz, "UTF-8", "로 하는 문자열pos.
  • 의 나머지 UTF-8'부터 )pos.

이것은 당신의 목적에 맞게 충분히 문자열을 조작할 수 있는 적절한 구성 요소가 될 것입니다.

당신의 "성격"에 대한 개념에 따라 이 질문은 다소 복잡해질 수 있습니다.

먼저 바이트 문자열을 Unicode 코드 포인트 문자열로 변환해야 합니다., 하다, 하다, 하다, 이렇게 할 수 요.iconv()경우, 밖에 할 수 없는 ,iconv()포식스

Unicode "null-terminated"와 .uint32_t[]C1x' 가 있는 char32_t이 어레이의 크기(바이트 단위의 크기가 아닌 요소의 수)는 코드 포인트 수(터미네이터도 포함)로, 매우 좋은 시작을 제공합니다.

그러나 "인쇄 가능한 문자"라는 개념은 상당히 복잡하며 코드 포인트보다는 알파벳 를 세는 것을 선호할 수 있습니다. 예를 들어,a^의 Unicode 코드 Unicode 코드 의 수 .â 둘하며, 에서는 둘 다 동등하게 - 그러다문자열을 일정한 버전으로 바꾸는 '정규화'라는 과정이 있지만, 하나의 코드 포인트로 표현할 수 없는 글자가 많고, 일반적으로 이를 이해하고 글자를 세는 적절한 라이브러리에는 방법이 없습니다.

즉, 스크립트의 복잡성과 처리의 철저성은 사용자에게 달려 있습니다.유니코드 코드 포인트로 변환하는 것은 필수이며, 그 이외의 모든 것은 사용자의 재량에 달려 있습니다.

될 경우 하지 말고 ICU에 해 주십시오 ICU에 대해 .하지만, 매우 심플한 ICU에 대해 자유롭게 살펴보십시오.iconv() 번째

저도 몇 년 전에 비슷한 구현을 했습니다.하지만 난 암호를 가지고 있지 않다.

각 유니코드 문자에 대해 첫 번째 바이트는 유니코드 문자를 구성하기 위해 이어지는 바이트 수를 나타냅니다.첫 번째 바이트를 기준으로 각 유니코드 문자의 길이를 결정할 수 있습니다.

좋은 UTF8 도서관인 것 같아요.링크 설명을 여기에 입력하십시오.

일반적으로 유니코드 문자에는 다른 데이터 유형을 사용해야 합니다.

예를 들어 와이드 문자 데이터 유형을 사용할 수 있습니다.

wchar_t theString[] = L"你们好āa";

문자열이 와이드 문자로 구성되어 있음을 나타내는L 수식자에 주의해 주세요.

는 이 을 사용하여 계산할 수 .wcslen이라고 하는 동작하는 것처럼 합니다.strlen.

가장 쉬운 방법은 ICU와 같은 라이브러리를 이용하는 것이다.

세계에서는, ★★★★★★★★★★★★★★★★★★★★★★★★.theString[3]=foo;의미 있는 작업이 아닙니다.문자열의 특정 위치에 있는 문자를 다른 문자로 대체하려는 이유는 무엇입니까?이 작업에 의미가 있는 자연어 텍스트 처리 태스크는 없습니다.

문자를 세는 것도 의미가 없을 것 같다."a"에는 몇 글자가 있습니까?"""는 어때?자, 그럼 '오빠'는요?텍스트 편집 기능을 구현하기 위해 이 정보가 필요한 경우 이러한 어려운 질문에 대처하거나 기존 라이브러리/gui 툴킷을 사용해야 합니다.당신이 세계 대본과 언어에 대한 전문가이고 당신이 더 잘할 수 있다고 생각하지 않는다면 후자를 추천할 것이다.

외 목적을 위해strlen는 문자열에 필요한 스토리지 공간 크기 등 실제로 유용한 정보를 정확하게 보여줍니다.이것이 현의 조합과 분리에 필요한 것입니다.,snprintf (오류)strcat와 ......)의 기능strstr필요한 건 이것뿐이에요

대문자화, 줄 바꿈 등의 고급 자연어 텍스트 조작이나 다중화, 시제 변경 등의 고급 조작을 실행하려면 ICU와 같은 라이브러리 또는 보다 높은 수준의 언어 기능(및 사용하고 있는 언어에 특유한 것)이 필요합니다..

다시 말하지만, 대부분의 프로그램은 이런 종류의 것에 전혀 쓸모가 없으며, 자연어를 고려하지 않고 텍스트를 조합하고 구문 분석하기만 하면 됩니다.

while (s[i]) {
    if ((s[i] & 0xC0) != 0x80)
        j++;
    i++;
}
return (j);

UTF-8 문자열의 문자를 카운트합니다.(이 기사에 기재되어 있습니다.UTF-8 문자증가)

하지만 난 아직 썰고 연결하는 데 어려움을 겪고 있어!

위의 답변에서 명확하지 않은 한가지는 그것이 왜 간단하지 않은가이다.각 문자는 예를 들어 UTF-8일 필요는 없으며, 각 문자는 여러 개의 인코딩을 가질 수 있으며, 엑센트 조합 등을 처리하는 다양한 방법이 있습니다.규칙은 매우 복잡하고 부호화에 따라 다릅니다(예를 들어 utf-8과 utf-16).

이 질문에는 보안에 대한 우려가 매우 크기 때문에 올바르게 실행하는 것이 중요합니다.OS 제공 라이브러리 또는 잘 알려진 서드파티 라이브러리를 사용하여 유니코드 문자열을 조작합니다.자신의 문자열을 롤하지 마십시오.

코드 포인트의 시퀀스는 다른 많은 서유럽 언어(예: 모든 인도 언어)에서 단일 음절/문자/문자를 구성합니다.

따라서 길이를 세거나 서브스트링을 찾을 때(예를 들어 행맨 게임을 할 때) 코드 포인트가 아닌 음절 단위로 진행해야 합니다.

따라서 문자/음절의 정의와 문자열을 실제로 "음절의 청크"로 나누는 위치는 다루는 언어의 특성에 따라 달라집니다.예를 들어 많은 인도 언어(힌디어, 텔루구어, 칸나다어, 말라얄람어, 네팔어, 타밀어, 펀자비어 등)의 음절 패턴은 다음 중 하나일 수 있습니다.

V  (Vowel in their primary form appearing at the beginning of the word)
C (consonant)
C + V (consonant + vowel in their secondary form)
C + C + V
C + C + C + V

문자열을 해석하고 위의 패턴을 찾아 문자열을 끊고 하위 문자열을 찾아야 합니다.

하나의 언어에 적용되는 패턴이 다른 문자에는 적용되지 않을 수 있기 때문에 유니코드 문자열(또는 코드 포인트의 시퀀스)에 대해 위의 방법으로 마술을 부릴 수 있는 범용적인 방법은 있을 수 없다고 생각합니다.

유니코드 문자열을 이러한 음절 청크로 분할하기 위한 입력으로 정의/설정 파라미터를 사용할 수 있는 메서드/라이브러리가 있을 수 있습니다.잘 모르겠어요!시판 또는 오픈 소스 방법을 사용하여 이 문제를 해결한 방법을 알려주시면 감사하겠습니다.

언급URL : https://stackoverflow.com/questions/7298059/how-to-count-characters-in-a-unicode-string-in-c

반응형