Alter Mann's accepted answer jest wzdłuż odpowiednich linii, z tym że jeden s nie mógł po prostu kodować funkcji niestandardowej, aby zliczyć liczbę bajtów w ciągu wielobajtowym, które nie kodują widocznego znaku: Kod powinien być zlokalizowany pod numerem setlocale(LC_ALL, "")
lub podobnym, a strlen(str) - mbstowcs(NULL, str, 0)
zliczać liczbę bajtów w ciągu znaków, które nie zawierają koduj widoczny znak.
setlocale()
to standard C (C89, C99, C11), ale również zdefiniowany w POSIX.1. mbstowcs()
to standardowe C99 i C11, a także zdefiniowane w POSIX.1. Oba są również implementowane w bibliotekach Microsoft C, więc działają praktycznie wszędzie.
Rozważmy następujący przykład program, który drukuje ciągi C, podane w linii poleceń:
#include <stdlib.h>
#include <string.h>
#include <locale.h>
#include <stdio.h>
/* Counts the number of (visible) characters in a string */
static size_t ms_len(const char *const ms)
{
if (ms)
return mbstowcs(NULL, ms, 0);
else
return 0;
}
/* Number of bytes that do not generate a visible character in a string */
static size_t ms_extras(const char *const ms)
{
if (ms)
return strlen(ms) - mbstowcs(NULL, ms, 0);
else
return 0;
}
int main(int argc, char *argv[])
{
int arg;
/* Default locale */
setlocale(LC_ALL, "");
for (arg = 1; arg < argc; arg++)
printf(">%-*s< (%zu bytes; %zu chars; %zu bytes extra in wide chars)\n",
(int)(10 + ms_extras(argv[arg])), argv[arg],
strlen(argv[arg]), ms_len(argv[arg]), ms_extras(argv[arg]));
return EXIT_SUCCESS;
}
Jeśli skompilować powyżej example
i uruchomieniu
./example aaa aaä aää äää aa€ a€€ €€€ a ä €
program będzie wyjściowej
>aaa < (3 bytes; 3 chars; 0 bytes extra in wide chars)
>aaä < (4 bytes; 3 chars; 1 bytes extra in wide chars)
>aää < (5 bytes; 3 chars; 2 bytes extra in wide chars)
>äää < (6 bytes; 3 chars; 3 bytes extra in wide chars)
>aa€ < (5 bytes; 3 chars; 2 bytes extra in wide chars)
>a€€ < (7 bytes; 3 chars; 4 bytes extra in wide chars)
>€€€ < (9 bytes; 3 chars; 6 bytes extra in wide chars)
>a < (1 bytes; 1 chars; 0 bytes extra in wide chars)
>ä < (2 bytes; 1 chars; 1 bytes extra in wide chars)
>€ < (3 bytes; 1 chars; 2 bytes extra in wide chars)
> < (4 bytes; 1 chars; 3 bytes extra in wide chars)
Jeśli ostatni <
nie nie są zgodne z innymi, ponieważ używana czcionka nie jest dokładnie ustalona - szerokość: emotikona
jest szersza niż zwykłe znaki, takie jak Ä
, to wszystko. Wini czcionkę.
Ostatnią postacią jest U + 1F608 UŚMIECHNA TWARZ Z TORAMI, z Emoticons unicode block, na wypadek, gdyby system operacyjny/przeglądarka/czcionka nie mogła go wyświetlić. W Linuksie wszystkie powyższe >
i <
są poprawnie rozmieszczone we wszystkich terminalach, jakie mam, w tym w konsoli (nie graficzna konsola systemowa), chociaż czcionka konsoli nie ma glifu dla emotikonu, a zamiast tego pokazuje go jako diament.
W przeciwieństwie do Alter Mann's answer, podejście to jest przenośne i nie przyjmuje żadnych założeń dotyczących tego, jaki zestaw znaków jest faktycznie używany przez bieżącego użytkownika.
Czy używasz kodowania UTF-8? Te znaki wymagają 2 bajtów, a 'printf' może nie być znane z UTF-8. – user694733
http://stackoverflow.com/questions/15528359/printing-utf-8-strings-with-printf-wide-vs-multibyte-string-literals – 123
@ user694733 Tak, użyłem utf-8 –