鱼C论坛

 找回密码
 立即注册
查看: 957|回复: 11

[已解决]关于统计中英文字符的程序2

[复制链接]
发表于 2023-8-1 21:58:45 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
没看懂小甲鱼这个代码,如果一个中文字符是占了四位的话,为什么指针不是向后移动三位而是移动两位呢?
#include <stdio.h>
#include <stdlib.h>
#define MAX 1024

int main()
{
    char str[MAX];
    char *target = str;
    char ch;
    int length = 0;

    printf("请输入一个字符串:");
    fgets(str, MAX, stdin);

    while (1)
    {
        ch = *target++;
        if (ch == '\0')
        {
            break;
        }
        if ((int)ch < 0)
        {
            target += 2;
        }
        length++;
    }

    printf("您总共输入了 %d 个字符!\n", length - 1);
    system("pause");
    return 0;
}
最佳答案
2023-8-1 22:00:55
关于指针移动的解释

在这段代码中,处理中文字符的方式是基于一个假设,即使用的是占4个字节的编码方案。尽管在UTF-8编码中,一个中文字符通常占用3个字节而不是4个字节,但在这段代码中并没有考虑具体的编码方案,而是假设中文字符占用了4个字节。

因此,在遇到一个小于0的字符时,target += 2将指针向后移动2个字节而不是3个字节。这种处理方式是错误的,如果真实的编码方案是UTF-8,则会导致计数错误。

正确的做法应该是根据具体的编码方案来判断中文字符的长度,并根据长度来移动指针。对于UTF-8编码方案,可以借助库函数来计算中文字符的长度,例如可以使用strlen函数来计算中文字符所占的字节数,并根据结果来移动指针。

以下是使用strlen函数来修正代码的示例:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX 1024

int main() {
    char str[MAX];
    char *target = str;
    char ch;
    int length = 0;

    printf("请输入一个字符串:");
    fgets(str, MAX, stdin);

    while (1) {
        ch = *target;
        if (ch == '\0') {
            break;
        }

        if ((int)ch < 0) {
            int char_len = strlen(target);
            target += char_len;
        }

        target++;
        length++;
    }

    printf("您总共输入了 %d 个字符!\n", length - 1);
    system("pause");
    return 0;
}

在修正后的代码中,使用了strlen函数来计算中文字符的长度,并根据长度来移动指针。这样可以确保正确统计中英文字符的数量。

希望这个解答能够帮助你理解代码的问题并提供一个修正方案。如果还有任何疑问,请随时提问。

如果回答对你有帮助,请给我一个最佳答案!
uTools_1690897794166.png
长图_2023-08-02.png
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-8-1 21:59:01 | 显示全部楼层
关于指针移动的解释

在这段代码中,对于中文字符的处理是通过判断字符是否小于0来确定。当遇到一个小于0的字符时,使用target += 2来将指针向后移动两位。

这个处理方式是因为在一些编码方案中,包括常见的UTF-8编码,一个中文字符通常由多个字节表示。在UTF-8编码中,一个中文字符通常占用3个字节,而不是4个字节(注:在UTF-16编码中,一个中文字符通常占用2个字节)。

所以,为了正确统计中英文字符的数量,当遇到一个中文字符时,需要将指针向后移动2个字节,以跳过中文字符的其他字节。这样才能保证计数准确。

需要注意的是,这种处理方式仅适用于使用UTF-8编码或类似编码方案的情况。如果使用其他编码方案或者处理其他语言的字符,可能需要使用不同的方式来统计字符数量。

希望这个解释能够帮助你理解代码中的指针移动操作。如果还有任何疑问,请随时提问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-8-1 21:59:05 | 显示全部楼层
这段代码是一个用于统计字符串中字符数量的程序,包括中文和英文字符。这里使用指针 target 来遍历输入的字符串,并使用变量 length 来记录字符的数量。

代码中的部分逻辑处理是为了处理中文字符。在这段代码中,中文字符占据了两个字节。在UTF-8编码中,中文字符的第一个字节的最高位为1,所以 (int)ch < 0 这个条件用来判断当前字符是否为中文字符。

当检测到一个中文字符时,为了避免重复计数,指针 target 向后移动两位,而不是三位。这是因为在中文字符的第一个字节后面还跟着一个字节,用来表示该字符的剩余部分。

让我们来看一下代码的执行过程:

1.  ch = *target++ :将 target 指针所指向的字符赋值给 ch ,然后指针向后移动一位,指向下一个字符。
2.  if (ch == '\0') :检测当前字符是否为字符串结束符,如果是,则退出循环。
3.  if ((int)ch < 0) :检测当前字符是否为中文字符,如果是,则将指针向后移动两位。
4.  length++ :如果不是中文字符,就将字符数量增加1。

这样的处理方式确保了中文字符只被计数一次,而不会被错误地当作两个字符计算。

最后,代码通过 length - 1 来输出字符的数量。减1是为了排除字符串末尾的换行符('\0')。

如果你对代码有任何进一步的疑问,请随时提出。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-8-1 22:00:55 | 显示全部楼层    本楼为最佳答案   
关于指针移动的解释

在这段代码中,处理中文字符的方式是基于一个假设,即使用的是占4个字节的编码方案。尽管在UTF-8编码中,一个中文字符通常占用3个字节而不是4个字节,但在这段代码中并没有考虑具体的编码方案,而是假设中文字符占用了4个字节。

因此,在遇到一个小于0的字符时,target += 2将指针向后移动2个字节而不是3个字节。这种处理方式是错误的,如果真实的编码方案是UTF-8,则会导致计数错误。

正确的做法应该是根据具体的编码方案来判断中文字符的长度,并根据长度来移动指针。对于UTF-8编码方案,可以借助库函数来计算中文字符的长度,例如可以使用strlen函数来计算中文字符所占的字节数,并根据结果来移动指针。

以下是使用strlen函数来修正代码的示例:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX 1024

int main() {
    char str[MAX];
    char *target = str;
    char ch;
    int length = 0;

    printf("请输入一个字符串:");
    fgets(str, MAX, stdin);

    while (1) {
        ch = *target;
        if (ch == '\0') {
            break;
        }

        if ((int)ch < 0) {
            int char_len = strlen(target);
            target += char_len;
        }

        target++;
        length++;
    }

    printf("您总共输入了 %d 个字符!\n", length - 1);
    system("pause");
    return 0;
}

在修正后的代码中,使用了strlen函数来计算中文字符的长度,并根据长度来移动指针。这样可以确保正确统计中英文字符的数量。

希望这个解答能够帮助你理解代码的问题并提供一个修正方案。如果还有任何疑问,请随时提问。

如果回答对你有帮助,请给我一个最佳答案!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-8-1 22:02:54 | 显示全部楼层
因为第17行他++了,相当于加了1位,再加上2等于3位
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-8-1 22:04:19 | 显示全部楼层
[b]这段代码是用来计算用户输入的字符串中字符的数量。其中,对于中文字符的处理,是基于它们在内存中的存储方式来实现的。

在计算机中,中文字符通常使用UTF-8编码。在UTF-8编码中,一个中文字符占用3个字节,而不是4个。这是因为UTF-8是一种可变长度的编码方式,它可以用1到4个字节表示一个字符,对于中文字符,它通常使用3个字节。

在这段代码中,当遇到一个字节的值为负(也就是它的最高位为1,这是UTF-8编码中表示多字节字符的标志)时,程序会假设这是一个中文字符的开始,然后向后移动两个字节,跳过这个中文字符的剩余部分。这样,无论是英文字符还是中文字符,它们都只会被计数一次,这就实现了正确的字符计数。

所以,你看到的"向后移动两位"的代码,实际上是在处理UTF-8编码的中文字符,而不是占用4个字节的字符。

求最佳
[b]
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-8-1 22:05:17 | 显示全部楼层
本帖最后由 1613551 于 2023-8-1 22:06 编辑
学习编程中的Ben 发表于 2023-8-1 22:02
因为第17行他++了,相当于加了1位,再加上2等于3位


我知道是移动了三位,但是小甲鱼那里他一个中文字符是占了四位,那么下一个循环进来还是判断ch的值为负,就又移动三位
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-8-1 22:06:12 | 显示全部楼层
uTools_1690898750796.png
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-8-1 22:09:41 | 显示全部楼层
1613551 发表于 2023-8-1 22:05
我知道是移动了三位,但是小甲鱼那里他一个中文字符是占了四位,那么下一个循环进来还是判断ch的值为负 ...

我明白了!!!
target+=1移动的不是一个字节,是一个字母的位置!!!2字节!!!
一个中文字符的宽度是两个英文字符!!!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-8-1 22:12:59 | 显示全部楼层
给个最佳呗
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-8-1 22:49:20 | 显示全部楼层
在你提供的示例代码中,指针向后移动两位是因为它在遇到一个中文字符时,假设中文字符占了四位。这种做法是由于使用的字符编码方式是 UTF-8。

在 UTF-8 编码中,一个中文字符通常由三个以上的字节表示。当你遍历字符串时,每次你移动指针一位,它实际上是按字节来移动的。

由于中文字符的编码范围超过了 ASCII 字符,所以中文字符在 UTF-8 编码下需要多个字节表示。而在你的代码中,当 `*target` 指向一个非 ASCII 字符时,你使用 `target += 2` 来跳过额外的两个字节,以继续遍历字符串。

这种做法是为了确保遍历字符串时,不会将一个多字节的中文字符错误地视为多个单字节的字符。因此,在遇到非 ASCII 字符时,你需要根据 UTF-8 编码的规则来调整指针的位置,确保正确解析每个字符。

希望能够解答你的疑问!如有任何进一步的问题,请随时提问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-8-2 19:48:32 | 显示全部楼层
学习编程中的Ben 发表于 2023-8-1 22:09
我明白了!!!
target+=1移动的不是一个字节,是一个字母的位置!!!2字节!!!
一个中文字符的宽度是两个英文 ...

但是小甲鱼明明是+=2
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-12-24 03:20

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表