【问题标题】:Don't understand function to count digits in character array不理解在字符数组中计算数字的函数
【发布时间】:2016-08-15 17:42:44
【问题描述】:

我很难理解教授对一个计算字符数组中位数的程序的解决方案。

int main(void)
{
    char* s[] = {"12, 34, 56, 78",
                 "82.16, 41.296",
                 "2, -3, 5, -7, 11, -13, 17, -19",
                 "9.00009, 90.0009, 900.009, 9000.09, 90000.9"};
    int i, rows = sizeof(s)/sizeof(s[0]);

    for(i = 0; i < rows; i++) {
      digitCounts( s[i] );
  }
}

void digitCounts(char* s) {
    int counts[10] = { 0 };
    int i = 0;

    while( s[i] != '\0' )
    {
        if('0' <= s[i] && s[i] <= '9')
            counts[ s[i] - '0' ]++;

        i++;
    }

    for(i = 0; i < 9; i++)
        printf("%d, ", counts[i]);

    printf("%d\n\n", counts[i]);
}

有人可以帮我具体理解这部分吗:

while( s[i] != '\0' )
{
    if('0' <= s[i] && s[i] <= '9')
        counts[ s[i] - '0' ]++;

    i++;
}

我理解 while 循环条件:如果 s[i] 处的元素不等于 NUL,则继续。但是 if 语句让我感到困惑,因为您是在比较数值还是字符串值?字符串值如何大于或小于另一个值?例如'1'

请帮助我真的迷路了!

【问题讨论】:

  • 首先 - 这些是“字符值”,而不是“字符串值”。第二:你听说过ASCII编码吗?
  • 他只是检查单个字符的 ASCII 值是否介于或包括字符“0”和“9”的 ASCII 值之间。它们在 ASCII 表中连续排列,这就是为什么您可以只检查上限和下限。
  • counts[ s[i] - '0' ]++;s[i] 处的字符转换为基于0 的字符,方法是减去范围内的最低字符值'0',然后计算该数字在counts[] 中的出现次数具有该索引的数组元素。
  • 这里没有任何东西表明执行字符集是ASCII。很多时候,了解确切的字符集和编码是至关重要的(它很少是 ASCII)。但是,这是可移植的 C 代码,它仅依赖于 C 系统的要求,即具有 '0'-'9' 作为连续的char 值。执行此操作的代码是 s[i] - '0',它是一个表达式,用于计算已知 0-9 数字字符与“0”字符的“距离”。所以,如果你正在查看一个 ASCII 表,你就犯了一个错误。这次不会痛了,但是……。

标签: c arrays character


【解决方案1】:

线

if('0' <= s[i] && s[i] <= '9')

将单个字符串中的单个字符与 字符常量 '0''9'(ASCII 值 48 和 57)进行比较。

请记住,C 中的 字符串 是一系列字符值,后跟一个 0 值终止符,字符串文字 由双引号分隔 (") .字符串(包括字符串文字)存储char 的数组。 s 的每个元素都包含char 数组的第一个字符的地址,类似于以下1

   +---+         +---+---+---+
s: |   | ------> |'1'|'2'| 0 |
   +---+         +---+---+---+
   |   | ----+
   +---+     |   +---+---+---+    
   |   | -+  +-> |'3'|'4'| 0 |
   +---+  |      +---+---+---+ 
    ...   |
          |      +---+---+---+
          +----> |'5'|'6'| 0 |
                 +---+---+---+

因此,s[0] 指向 字符串 "12"s[1] 指向字符串 "34",等等。每个 s[i] 都传递给 digitCounts 函数,它逐个字符遍历字符串并检查每个字符是否为数字。

C语言定义保证数字字符'0''1''2'等的值是连续的,所以'0'和@之间的任何字符值987654339@ 必须是数字字符。所以条件

if ( '0' <= s[i] && s[i] <= '9' )

正在检查每个s[i] 是否为数字字符('0''9' 等字符常量由单引号分隔)。请注意,有一个库函数可以做同样的事情,但它还考虑了语言环境:

#include <ctype.h>
...
if ( isdigit( s[i] ) ) // does the same thing as the line above.   

你教授的代码……不是很好。如果他对main 中的字符串数组(例如numberStringList)与digitCounts 的输入参数(例如numberString)使用不同的名称,那就太好了;我认为这解释了你的一些困惑。他应该向您展示如何使用isdigit 函数而不是手动破解支票。


  1. main 中,s 被声明为指向char (char *[]) 的指针数组。数组的大小取自初始化器列表中的初始化器数量。

    初始化器中的每个字符串字面量也是char 的数组,但在大多数情况下,数组表达式会被转换(“decay” ) 指向指针表达式,表达式的值是数组第一个元素的地址。所以每个s[i] 都存储字符串文字的地址,而不是文字本身。

【讨论】:

  • 可以把char* s[] = {"12, 34, 5 ...看作一个二维数组吗?对于函数digitCounts,如何将代码更改为整体查看“12”,而不是分别查看“1”和“2”?像这样? while( s*[i] != '\0' )?
  • @CheetahBongos:我不认为它是一个二维数组,因为数组“行”(字符串本身)不能保证在内存中是相邻的。您当然可以将其编入索引,就像它是一个二维数组(s[0][0] == '1's[0][1] == '2's[1][0] == '3' 等),但它不像二维数组那样布局在内存中。
  • @CheetahBongos:要将字符串作为一个整体,只需使用不带任何下标的s。但是,您无法将 strings 与单个字符进行比较 - s != '\0' 不起作用,或者至少它不会做您想要的。 C 字符串处理是 非常 原始的 - 没有字符串数据类型。它们只是char 的数组,C 中的大多数字符串处理实际上是逐个字符完成的。
  • @CheetahBongos 不是二维的,它可以暗示一个矩形矩阵,这种类型的数组的术语是“不规则数组”或数组数组。
  • @John Bode:c 逐个字符处理字符串会使其在字符串处理方面比其他语言慢吗?
【解决方案2】:
while( s[i] != '\0' ) //while char at index i is not '\0' (end of string)
{
    if('0' <= s[i] && s[i] <= '9') //if char at index i is between '0' and '9' (a digit)
    counts[ s[i] - '0' ]++; // increase digit count. (counts is an array of       size 10 where each index corresponds to digits 0-9

    i++;
}

【讨论】:

    【解决方案3】:
    while( s[i] != '\0' ){
       if('0' <= s[i] && s[i] <= '9')
          counts[ s[i] - '0' ]++;
       i++;
    }
    

    此循环迭代直到s[i] 等于'\0'。然后比较字符,即 '0'&lt;=s[i] 在这两者都是字符而不是字符串(基于 ASCII 值比较)。

    然后,如果满足条件,则特定索引处的计数在数组counts 中递增。如果s[i] 处的字符为'1',则索引计数加一。这个 's[i]-'0' 给出了特定的整数,因为 '1'-'0'1 作为它们的 ASCII 值之间的差异。

    【讨论】:

      【解决方案4】:

      都是char

      通过if 语句,您可以了解字符是否为数字(不等式实际上作用于每个char 的ASCII 值)。

      【讨论】:

        【解决方案5】:

        这里char* s[] 表示二维字符数组或字符串数​​组。在digitCounts 中,参数是char* s,它是一维数组或字符串。这就是为什么s[0] 或 s[] 的第一个元素将是 '1',而不是 '12'。

        另外,'1' &lt;= '9' 表示字符 1 和 9 的 ASCII 值比较。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-04-07
          • 2013-05-03
          • 1970-01-01
          • 2018-04-20
          • 1970-01-01
          • 2015-08-25
          • 2013-11-02
          • 2020-05-06
          相关资源
          最近更新 更多