C语言如何计算字符串中某个字符出现的频率
How to calculate the frequency of a character in a string in C
我找到了计算字符串中字符出现频率的代码,但是,它们都使用同一行代码并且没有解释它的含义。有没有人可以赐教一下?
这是一个例子:
int c = 0, count[26] = {0}, x;
while (string[c] != '[=10=]') {
/** Considering characters from 'a' to 'z' only and ignoring others. */
if (string[c] >= 'a' && string[c] <= 'z') {
x = string[c] - 'a';
count[x]++;
}
我知道循环将遍历字符串直到到达末尾。
我还得到了 if 语句,因为它只将它限制在 a 和 z 之间。
但是,我不知道x = string[c] -'a'
在做什么,为什么要减去'a'
?
我也不明白count[26]
的目的是什么
这里是我从哪里得到这个程序:
https://www.programmingsimplified.com/c-program-find-characters-frequency
如有帮助将不胜感激。
在ASCII数据库中,'a'到'z'有0x61到0x7A的连续数字编码。比照。 man ascii。
因此,如果你减去 'a' 的值,你会得到从 0 到 25 的数字。这个数字是 count[] table.[=11 中的一个索引=]
TL;DR 是利用了ASCII table.
代码只接受从a
到z
的字符:
if (string[c] >= 'a' && string[c] <= 'z')
因此它创建了一个包含 26 个位置的数组(即 count[26]
)来存储这些相同字符的频率。以下
x = string[c] - 'a';
将string[c]
转换为int
;可用于利用 ASCII table.
的事实
根据 ASCII table,字母 'a' 到 'z' 由 97
到 112
的 int
值表示,分别。因此,因为 C 中的数组以 0
开头,我们需要将 97
个元素从 return 的值向左移动 string[c]
,即:
x = string[c] - 97;
可以表示为
x = string[c] - 'a';
使用这个 技巧 如果 string[c]
是 'a' 那么 :
x = 'a' - 'a';
转换为x = 97 - 97
,然后是x = 0
;因此,
count[x]++;
是 count[0]++;
将数组 count
的位置 0 加 1,这是“保留”给字母 'a'。同样的逻辑适用于从 'a' 到 'z'.
的所有其他字母
但是请记住,并引用 Eric Postpischil:
The character codes used in C implementations do not necessarily have
all the letters consecutively. ASCII does and is very common, but not
required by the standard.
因此,如果您的编码是 ASCII,此解决方案将有效。
count[26]
是频率table。 count[0]
是 a
出现的次数。 count[1]
是b
出现的次数,等等...
将 count
数组初始化为全零值
count[26] = {0}
虽然不在字符串的末尾。请记住,C 字符串始终以空字符 ([=21=]
).
结尾
while (string[c] != '[=11=]') {
判断字符串[c]中的字符是否在a和z之间
if (string[c] >= 'a' && string[c] <= 'z') {
将此字符的 ascii 值(介于 97 和 122 之间)标准化为 0 到 25 之间的值。a
在数学表达式中计算时为 97。
x = string[c] - 'a';
使用上面计算的 x
值,将其用作 count
table 的索引
将 count[x]
中的任何值增加 1。
count[x]++;
此代码示例中缺少 c
递增 1 的地方,这样 string[c]
引用字符串中的下一个字符。
count[26]
是一个包含26个整数的数组,每个整数代表string
中从'a'
到'z'
的小写字母的个数
count[0]
是 'a'
的计数器,count[1]
是 'b'
等的计数器...
x = string[c] - 'a'
计算并分配给 x
在 string[c]
处找到的字符的索引 0-25。
Simplifyng:记住 'a'
是整数 ascii 值 97 十进制。 'a'
的减法是将'a'
到'z'
的所有索引减到count[]
数组需要的0到25的值。
首先,该代码取决于字符 'a'
到 'z'
的连续表示,这很常见但不能保证。
第二,
int c = 0, count[26] = {0}, x;
while (string[c] != '[=10=]') {
/** Considering characters from 'a' to 'z' only and ignoring others. */
if (string[c] >= 'a' && string[c] <= 'z') {
x = string[c] - 'a';
count[x]++;
}
有几个问题,我想说的更清楚,因为
#include <ctype.h>
// multiple variables on one line is ***very*** bug prone
// so don't do it
int c = 0;
int count[26] = {0};
// set the input - unsigned is important
unsigned char *string = ...;
// loop until the character pointed at by string is '[=11=]'
while ( *string )
{
// islower() returns non-zero only if the unsigned char value
// passed is a lower-case letter.
//
// If the input int value can't be represented as an unsigned
// char the results are undefined behavior (because tolower()
// actually takes an int argument.)
//
// signed char will be sign-extended when passed as an int argument
if ( islower( *string ) )
{
// get the "index" of the lower-case letter
// a -> 0, b -> 1, z -> 25
// depends on a-z being consecutive - not necessarily true
int x = *string - 'a';
// increment the number of times this lower-case character
// is in this string
count[x]++;
}
// go to the next character in the string
string++;
}
请注意,我为减少使用的行数所做的努力为零。将代码塞进更少的行中没有任何好处,但会使代码更难阅读,因此更容易出错。
计算字符串中字符数的更好方法:
#include <limits.h>
void countChars( unsigned char *string )
{
int counts[ UCHAR_MAX ] = { 0 };
while ( *string )
{
counts[ *string ]++;
string++;
}
}
如果要计算小写字符:
#include <limits.h>
void countLowerCaseChars( unsigned char *string )
{
int counts[ UCHAR_MAX ] = { 0 };
while ( *string )
{
counts[ tolower( *string ) ]++;
string++;
}
}
我找到了计算字符串中字符出现频率的代码,但是,它们都使用同一行代码并且没有解释它的含义。有没有人可以赐教一下?
这是一个例子:
int c = 0, count[26] = {0}, x;
while (string[c] != '[=10=]') {
/** Considering characters from 'a' to 'z' only and ignoring others. */
if (string[c] >= 'a' && string[c] <= 'z') {
x = string[c] - 'a';
count[x]++;
}
我知道循环将遍历字符串直到到达末尾。
我还得到了 if 语句,因为它只将它限制在 a 和 z 之间。
但是,我不知道x = string[c] -'a'
在做什么,为什么要减去'a'
?
我也不明白count[26]
的目的是什么
这里是我从哪里得到这个程序:
https://www.programmingsimplified.com/c-program-find-characters-frequency
如有帮助将不胜感激。
在ASCII数据库中,'a'到'z'有0x61到0x7A的连续数字编码。比照。 man ascii。 因此,如果你减去 'a' 的值,你会得到从 0 到 25 的数字。这个数字是 count[] table.[=11 中的一个索引=]
TL;DR 是利用了ASCII table.
代码只接受从a
到z
的字符:
if (string[c] >= 'a' && string[c] <= 'z')
因此它创建了一个包含 26 个位置的数组(即 count[26]
)来存储这些相同字符的频率。以下
x = string[c] - 'a';
将string[c]
转换为int
;可用于利用 ASCII table.
根据 ASCII table,字母 'a' 到 'z' 由 97
到 112
的 int
值表示,分别。因此,因为 C 中的数组以 0
开头,我们需要将 97
个元素从 return 的值向左移动 string[c]
,即:
x = string[c] - 97;
可以表示为
x = string[c] - 'a';
使用这个 技巧 如果 string[c]
是 'a' 那么 :
x = 'a' - 'a';
转换为x = 97 - 97
,然后是x = 0
;因此,
count[x]++;
是 count[0]++;
将数组 count
的位置 0 加 1,这是“保留”给字母 'a'。同样的逻辑适用于从 'a' 到 'z'.
但是请记住,并引用 Eric Postpischil:
The character codes used in C implementations do not necessarily have all the letters consecutively. ASCII does and is very common, but not required by the standard.
因此,如果您的编码是 ASCII,此解决方案将有效。
count[26]
是频率table。 count[0]
是 a
出现的次数。 count[1]
是b
出现的次数,等等...
将 count
数组初始化为全零值
count[26] = {0}
虽然不在字符串的末尾。请记住,C 字符串始终以空字符 ([=21=]
).
while (string[c] != '[=11=]') {
判断字符串[c]中的字符是否在a和z之间
if (string[c] >= 'a' && string[c] <= 'z') {
将此字符的 ascii 值(介于 97 和 122 之间)标准化为 0 到 25 之间的值。a
在数学表达式中计算时为 97。
x = string[c] - 'a';
使用上面计算的 x
值,将其用作 count
table 的索引
将 count[x]
中的任何值增加 1。
count[x]++;
此代码示例中缺少 c
递增 1 的地方,这样 string[c]
引用字符串中的下一个字符。
count[26]
是一个包含26个整数的数组,每个整数代表string
'a'
到'z'
的小写字母的个数
count[0]
是 'a'
的计数器,count[1]
是 'b'
等的计数器...
x = string[c] - 'a'
计算并分配给 x
在 string[c]
处找到的字符的索引 0-25。
Simplifyng:记住 'a'
是整数 ascii 值 97 十进制。 'a'
的减法是将'a'
到'z'
的所有索引减到count[]
数组需要的0到25的值。
首先,该代码取决于字符 'a'
到 'z'
的连续表示,这很常见但不能保证。
第二,
int c = 0, count[26] = {0}, x;
while (string[c] != '[=10=]') {
/** Considering characters from 'a' to 'z' only and ignoring others. */
if (string[c] >= 'a' && string[c] <= 'z') {
x = string[c] - 'a';
count[x]++;
}
有几个问题,我想说的更清楚,因为
#include <ctype.h>
// multiple variables on one line is ***very*** bug prone
// so don't do it
int c = 0;
int count[26] = {0};
// set the input - unsigned is important
unsigned char *string = ...;
// loop until the character pointed at by string is '[=11=]'
while ( *string )
{
// islower() returns non-zero only if the unsigned char value
// passed is a lower-case letter.
//
// If the input int value can't be represented as an unsigned
// char the results are undefined behavior (because tolower()
// actually takes an int argument.)
//
// signed char will be sign-extended when passed as an int argument
if ( islower( *string ) )
{
// get the "index" of the lower-case letter
// a -> 0, b -> 1, z -> 25
// depends on a-z being consecutive - not necessarily true
int x = *string - 'a';
// increment the number of times this lower-case character
// is in this string
count[x]++;
}
// go to the next character in the string
string++;
}
请注意,我为减少使用的行数所做的努力为零。将代码塞进更少的行中没有任何好处,但会使代码更难阅读,因此更容易出错。
计算字符串中字符数的更好方法:
#include <limits.h>
void countChars( unsigned char *string )
{
int counts[ UCHAR_MAX ] = { 0 };
while ( *string )
{
counts[ *string ]++;
string++;
}
}
如果要计算小写字符:
#include <limits.h>
void countLowerCaseChars( unsigned char *string )
{
int counts[ UCHAR_MAX ] = { 0 };
while ( *string )
{
counts[ tolower( *string ) ]++;
string++;
}
}