Перевернуть строку, содержащую символы ASCII и символы не-ASCII
У меня возникла проблема о том, как отменить строку, содержащую этот 'abcd汉字efg'.
str_to_reverse = "abcd汉字efg"; /* those non-ASCII chars are Chinese characters, each of them takes 2 bytes */
после реверсии должно быть:
str_toreverse = "gfe字汉dcba";
Я подумал: чтобы перевернуть строку, я должен идентифицировать эти не-ASCII-символы, потому что я думаю, что простое изменение каждого байта не даст правильного ответа.
Как мне это сделать?
PS: я написал эту программу под Ubuntu, 32-битной. Затем я напечатал каждый байт:
for(i = 0; i < strlen(s); i++)
printf("%c", s[i]);
Я получил немного бессмысленного текста вместо "汉字".
2 ответа
Решение
Чистый ответ C89:
#include <stdlib.h>
#include <stdio.h>
#include <locale.h>
#include <string.h>
int main()
{
char const* str;
size_t slen;
char* rev;
setlocale(LC_ALL, "");
str = "abcd汉字efg";
printf("%s\n", str);
slen = strlen(str);
rev = malloc(slen+1)+slen;
*--rev = '\0';
while (*str != '\0') {
int clen, i;
clen = mblen(str, slen);
if (clen == -1) {
fprintf(stderr, "Bad encoding\n");
return EXIT_FAILURE;
}
for (i = 0; i < clen; ++i) {
*--rev = str[clen-1-i];
}
str += clen;
}
printf("%s\n", rev);
return 0;
}
Если строка закодирована как utf8, это довольно просто. Вы можете получить длину правильно сформированных последовательностей utf8, проверяя только первый байт.
На первом проходе вы изменяете только "подпоследовательности" utf8 (с длиной> 1). На втором проходе вы полностью изменяете всю строку. Вуаля.