【问题标题】:Why doesn't my character counter work properly? [duplicate]为什么我的字符计数器不能正常工作? [复制]
【发布时间】:2021-06-17 23:27:50
【问题描述】:

我最近开始学习 C 语言,目前正在尝试编写一个简单的程序,该程序应该返回一个字符被使用的次数,但输出是错误的。 为什么它不能正常工作?任何帮助将不胜感激。 代码如下:

#include <stdio.h>

main() {
    int c, i;
    int ndigit[25]; //a = 97

    while( (c = getchar()) != EOF) {    
        ++ndigit[c - 97];
    }
    
    for (i = 0; i < 26; i++) {  
        putchar(i + 97);
        printf(" = %d\n", ndigit[i]);
    }
}

这是带有单词“hello”的输出:

a = 8
b = 0
c = 4203649
d = 0
e = 4202641
f = 0
g = 84
h = 1
i = 12260176
j = 0
k = 1
l = 2
m = -1
n = -1
o = 85
p = 0
q = 1
r = 0
s = 4203673
t = 0
u = 0
v = 0
w = 84
x = 0
y = 0
z = 0

【问题讨论】:

  • 您想当然地认为getchar 读取的每个字符都是小写字母字符,您的字符集是ASCII
  • 您应该使用c +/- 'a' 而不是c +/- 97。并且您的数组未初始化,这意味着它包含随机数。您应该将所有项目设置为 0。
  • 你应该将ndigit初始化为26
  • 你可以使用 ```Your code `` 来包含你的代码而不缩进。

标签: c


【解决方案1】:

当您创建一个新数组时,它可能包含随机数。您需要手动将其设置为 0。一种方法是使用以下函数:

memset(ndigit,0,sizeof(int)*26);

您还需要包含 string.h 才能使用它

编辑:忘记了数组是 int 类型,所以我们需要将大小乘以 int 的大小

Edit2:我也认为你希望你的数组大小为 26

【讨论】:

  • 他也可以写int ndigit[26] = {0} 将整个数组设置为0s
  • @superior 可以在 C++ IDK 中工作,如果它可以在 C 中工作的话
  • @CEPB 不是真正的文档,而是stackoverflow.com/a/2589751/9665272
【解决方案2】:

您的问题是您的数组可能包含随机值。在C/C++ 中,您不能保证在程序开始时内存被清零,而是您可能会得到之前存在的任何内容。如上所述,您可以使用一些内置函数,但只需这样做:

int ndigit[26]; // as mentioned in comments and in previous answers English alphabet has 26 characters

for (int i = 0; i < 26; ++i)
   ndigit[i] = 0;

// rest of you code here

另一个问题主要是您必须输入return 0,原因与您的数组相同。如果没有return 0,可以返回随机值。

main () {
   // your code here

   return 0;
}

每个@superior 你也可以使用

ndigit[26] = {0}

然而,这是 C99 标准,不严格遵循它的编译器将不会初始化数组。我知道 4.xx 之前的 gcc 版本没有。

编辑: 这是我的输出与您的(OP 代码)输入hello

a = 4543
b = 0
c = 0
d = 0
e = 1318238529
f = 32604
g = 121
h = 1
i = 37
j = 57
k = 1136
l = 2
m = 1
n = 0
o = 4195998
p = 0
q = 142
r = 0
s = 0
t = 0
u = 4195920
v = 0
w = 4195568
x = 0
y = -1400909520
z = 32767

这是我的答案的输出,带有for() 循环,并建议{0}

a = 0
b = 0
c = 0
d = 0
e = 1
f = 0
g = 0
h = 1
i = 0
j = 0
k = 0
l = 2
m = 0
n = 0
o = 1
p = 0
q = 0
r = 0
s = 0
t = 0
u = 0
v = 0
w = 0
x = 0
y = 0
z = 0

【讨论】:

  • 他也可以写 int ndigit[26] = {0} 将整个数组设置为 0s
  • 大声笑,@Superior 感谢您的评论,并将其包含在我的回答中,我不得不提到这是 C99,直到最近一些编译器和一些 Linux 扭曲器有点落后。
【解决方案3】:

我目前正在尝试编写一个简单的程序,它应该返回一个字符被使用的次数

这是一个相当不错的入门练习。

一些注释可以让您更容易更快地获得结果:

  • 使用编译器的能力来帮助您
    • 如果您使用 gcc 或 clang:-stdc18 -Wall -Wextra -pedantic -pedantic-errors

您会注意到main() 函数无效。 C 不允许无类型函数。正确的main 需要隐式或显式返回int。如果有疑问,只要知道它默认会return 0

你也没有初始化你的数组。这会产生后果——比如现在不知道从内存中读取会发生什么。


修复程序的建议是不要使用幻数。这是一个陷阱(假设97 早在'a' 之前就会过时)。使用 'a' - 或者更好的是,使用 C 库中的常量。

一旦 unicode 发挥作用,下面的一切都会出错,但它可以很好地计算“字节”值。

#include <stdio.h>
#include <string.h>
#include <limits.h> /* UCHAR_MAX (almost never anything but 255) */

char friendlify(unsigned char x) { /* unsigned to char cast ... */
    /* this is just for presentation - purely ASCII friendly */
    /* ternary operator: (condition) ? (true) : (false) */
    return x < '.' || x > '~' ? '.' : x;
}

int main() {
    int c;
    /* make room for all `char`s (unsigned chars really) */
    unsigned ndigit[UCHAR_MAX+1] = {0}; /* zero initialize */

    while ((c = getchar()) != EOF) {
        /* since getchar returns an unsigned - (unless EOF) we're not worried here) */
        ++ndigit[c];
    }

    printf("Collected:\n");
    for (unsigned i = 0; i <= UCHAR_MAX ; ++i) {
        /* just print characters included in the input */
        if (ndigit[i]) { /* assuming zero hits aren't interesting */

            /* %02X and the `i` makes it print the hex value of that particular byte */
            printf("0x%02X  %c  Count = %u\n", i, friendlify(i), ndigit[i]);
        }
    }
}

【讨论】:

  • 很好的答案,但我认为C doesn't allow type-less functions 不适用于main()。默认情况下它会返回 int。
  • @CEPB 谢谢!但是,关于main:不,不会。 main 需要声明为int 否则你的程序无效。
  • 是否包含在 C99 中?
  • LOL 刚刚找到它,它在 C99 和更高的标准中,但是 ANSI C 和 gcc 仍然允许函数在没有指定返回类型的情况下运行,在这种情况下它是 intstackoverflow.com/a/16136583/5550963
  • @CEPB 我认为所有 C 标准都允许非“标准(通用)”实现特定的特殊化,以实现嵌入式完美。编辑:我以 C++ 的想法为生——我可能完全错了
猜你喜欢
  • 2019-01-22
  • 1970-01-01
  • 1970-01-01
  • 2021-09-25
  • 1970-01-01
  • 2012-06-12
  • 2019-08-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多