我正在尝试编写一个程序来计算土耳其语字符串中的所有字符。我不明白为什么这不起作用。我添加了库,setlocale(LC_ALL,“土耳其语”),但仍然无效。谢谢。这是我的代码: 我的文件字符编码: utf_8
int main(){
setlocale(LC_ALL,"turkish");
char string[9000];
int c = 0, count[30] = {0};
int bahar = 0;
...
if ( string[c] >= 'a' && string[c] <= 'z' ){
count[string[c]-'a']++;
bahar++;
}
我的输出:
0.085217 b 0.015272 c 0.022602 d 0.035736 e 0.110263 f 0.029933 g 0.015272 h 0.053146 我0.071167 k 0.010996 l 0.047954 m 0.025046 n 0.095907 o 0.069334 p 0.013745 q 0.002443 r 0.053451 s 0.073916 t 0.095296 你0.036958 v 0.004582 w 0.019243 x 0.001527 是0.010996
这是英文字母,但我也需要这个字符计算:“ğ,ü,ç,ı,ö”
答案 0 :(得分:2)
setlocale(LC_ALL,"turkish");
首先:"turkish"
不是区域设置。
区域设置的正确名称通常类似于xx_YY.CHARSET
,其中xx
是该语言的ISO 639-1代码,YY
是ISO 3166-1 Alpha-2 code国家/地区CHARSET
是可选的字符集名称(通常为ISO8859-1
,ISO8859-15
或UTF-8
)。请注意,并非所有组合都有效;计算机必须具有为语言代码,国家/地区代码和字符集的特定组合生成的区域设置文件。
您可能需要的是setlocale(LC_ALL, "tr_TR.UTF-8")
。
if ( string[c] >= 'a' && string[c] <= 'z' ){
第二:>=
和<=
等比较运算符不区分区域设置。此比较将始终对字节执行,并且不包括ASCII a
- z
范围之外的字符。
要执行区分区域敏感的比较,您必须使用strcoll()
之类的函数。但是,请注意,有些字母(包括您在此处尝试包含的字母!)由UTF-8中的多字节序列组成,因此循环字节也不会起作用。您需要使用mblen()
或mbtowc()
等函数来分隔这些序列。
答案 1 :(得分:2)
由于您显然使用的是UTF-8文件,答案取决于您的执行平台:
如果您使用的是Linux,那么setlocale(LC_CTYPE, "en_US.UTF-8")
或类似内容应该可以正常运行,但最重要的部分是UTF-8
!语言无关紧要。您可以使用
if (setlocale(LC_CTYPE, "en_US.UTF-8") == NULL) {
abort();
}
这将阻止程序执行。该代码之后的任何内容都意味着语言环境设置正确。
如果您使用的是Windows,则可以使用fopen("myfile.txt", "rt, ccs=UTF-8")
打开该文件。但是,这并非完全可移植到其他平台。然而,它比替代品更清洁,在这种特殊情况下可能更为重要。
如果您正在使用FreeBSD或其他不允许您使用这两种方法的系统(例如,没有UTF-8
语言环境),您需要手动解析字节或使用库为你转换它们。如果您的实现具有iconv()
函数,则可以使用它将UTF-8转换为ISO-8859-9,以将特殊字符用作单个字节。
准备好阅读文件后,您可以将fgetws
与wchar_t
数组一起使用。
另一个问题是检查是否检测到您的某个非ASCII字符。你可以这样做:
// lower = "abcdefghijklmnopqrstuvwxyzçöüğı"
// upper = "ABCDEFGHİJKLMNOPQRSTUVWXYZÇÖÜĞI"
const wchar_t lower[] = L"abcdefghijklmnopqrstuvwxyz\u00E7\u00F6\u00FC\u011F\u0131";
const wchar_t upper[] = L"ABCDEFGH\u0130JKLMNOPQRSTUVWXYZ\u00C7\u00D6\u00DC\u011EI";
const wchar_t *lchptr = wcschr(lower, string[c]);
const wchar_t *uchptr = wcschr(upper, string[c]);
if (lchptr) {
count[(size_t)(lchptr-lower)]++;
bahar++;
} else if (uchptr) {
count[(size_t)(uchptr-upper)]++;
bahar++;
}
该代码假定您在不考虑大小写的情况下对字符进行计数(不区分大小写)。也就是说,ı
(\u0131
)和I
被视为相同的字符(count[8]++
),就像İ
(\u0130
)和{ {1}}被视为相同(i
)。我不会声称对土耳其语有太多了解,但是当我创建大写和小写字符串时,我使用了我对土耳其套管规则的了解。
修改强>
正如@JonathanLeffler在问题评论中提到的,更好的解决方案是在count[29]++
中的每个字符上使用isalpha
(或者在这种情况下,iswalpha
)而不是我使用的string
和lower
个有效字符串。但是,这只会让您知道该字符是一个字母字符;它不会告诉你要使用的upper
数组的索引,事实是没有通用的答案,因为有些语言只使用带变音符号的几个字符而不是整个组可以做count
。换句话说,即使您已经读取了数据,您仍然需要将其转换为适合您的解决方案,并且需要了解您正在使用的内容来创建从字符到整数值的映射,我的代码通过使用字符串中的有效字符串和每个字符的索引作为string[c] >= L'à' && string[c] <= L'ç'
数组的索引(即count
将表示lower[29]
将被执行,count[29]++
将表示{执行{1}}。
答案 2 :(得分:0)
解决方案取决于文件的字符编码。
如果文件是ISO 8859-9(latin-5),那么每个特殊字符仍然只能在一个字节中编码,您可以轻松修改代码:您已经在大写和小写之间存在分歧。只需为特殊字符添加更多分支。
如果文件是UTF-8或其他一些unicode编码,则需要一个支持多字节的字符串库。