实验6 函数---输出数中指定数字的个数

本文介绍了一个C语言程序,用于统计并输出一个整数中特定数字出现的次数。通过定义函数countdigit,可以针对任意整数和指定数字进行统计,如countdigit(10090,0)将返回3。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

【问题描述】读入一个整数,统计并输出该数中指定数字的个数,要求调用函数countdigit(number,digit),他的功能是统计整数number中数字digit的个数。;例如,countdigit(10090,0)的返回值是3.
【输入形式】
【输出形式】
【样例输入】21252,2
【样例输出】Number of digit 2:3
【样例说明】
【评分标准】

#include <stdio.h>
 
int coutdigit(int integer, int digit) {
    int flag=0;
    for(;integer!=0;){
        if(integer%10==digit) flag++;
        integer=integer/10;
    }
    return flag;
}
int main() {
    int integer,digit;
    scanf("%d,%d",&integer,&digit);
    int numberOfDigit = coutdigit(integer,digit);
    printf("Number of digit %d:%d\n",digit,numberOfDigit);
    return 0;
}

<think>我们有一个任务:统计一篇文章中英文大写字母、小写字母、数字和其他字符的个数。文章有3行,每行最多80个字符。我们将使用字符组来存储每行的文本,然后遍历组中的每个字符进行分类统计。注意:我们使用fgets而不是gets,因为gets不安全(容易造成缓冲区溢出),但根据用户提供的引用[1]中的代码,他们使用了gets,但我们会按照安全规范使用fgets。另外,用户提到了puts0和gets0,但实际应为puts和gets,没有0。可能是笔误。步骤:1.定义字符组:由于有3行,每行80个字符,加上一个换行符和字符串结束符,我们可以定义每行长度为82(80个字符+换行符+结束符),或者使用81然后处理换行。2.输入:使用fgets读取每行,注意fgets会包括换行符,然后我们将其替换为结束符(可选,但统计时需要注意换行符被算作其他字符)。3.统计:遍历每个字符,使用ctype.h中的函数(如isupper,islower,isdigit,isspace)来判断字符类型。4.输出:使用puts或printf输出统计结果。注意:在统计时,空格是单独统计的,而其他字符包括换行符、标点等。但是,由于我们使用fgets读取,每行末尾有一个换行符,它会被计入。根据题目要求,换行符应该算作“其他字符”。但是,题目要求每行80个字符,但实际输入可能不足80,所以我们需要按照实际存储的字符串进行统计,直到遇到空字符('\0')。我们参考用户提供的引用[1]中的代码,但做以下改进:-使用fgets替代gets,避免溢出。-整数组大小为每行82个字符(80个字符+换行符+结束符,但实际fgets最多读取81个字符(包括换行符)然后加上结束符,所以我们可以使用82确保安全)。然而,题目要求每行80个字符,所以输入可能正好80个字符(没有换行符)?但实际上,我们输入时通常会按回车,所以输入字符串包括80个字符和一个换行符。因此,我们定义每行为81个字符(实际存储81个字符,其中最多80个字符和一个换行符,再加上一个结束符),所以组应该定义为c[3][81],这样fgets可以读取80个字符(不包括换行符)吗?不对,fgets读取包括换行符。具体:fgets(str,size,stdin)读取最多size-1个字符,然后在最后添加'\0'。如果一行超过size-1,则只读取size-1个字符,剩下的留在缓冲区。因此,如果我们每行最多80个字符加上一个换行符,那么我们需要读取81个字符(80+换行符),加上结束符,需要82个位置。但题目要求每行80个字符,所以我们可以不考虑超过80个字符的情况?如果输入超过80个字符,那么我们需要处理截断。但是,题目要求每行80个字符,我们假设输入不会超过80个字符(不包括换行符)。因此,我们可以设置每行的组大小为82,然后读取81个字符(包括换行符),这样如果输入80个字符,那么换行符会被读入,然后我们再处理。然而,在统计时,换行符会被当作一个字符(其他字符)。如果不需要换行符,我们可以将其替换掉,但题目没有特别说明,所以我们按照实际存储的字符统计(包括换行符)。另外,在引用[1]的代码中,他们定义了c[N][M],其中N=3,M=4,但这是明显不足的,因为每行至少需要80个字符的空间。这应该是写错了,应该是c[3][81]。我们重新设计:步骤:1.定义二维字符组:charlines[3][82];//每行最多82个字符,包括80个字符+换行符+结束符2.循环输入每一行:使用fgets,指定大小为82(即最多读取81个字符)。3.遍历组:使用双重循环,外层循环行(0-2),内层循环列,直到当前字符为'\0'(因为每行不一定都占满80个字符)。4.在遍历每个字符时,判断其类型并计。5.输出结果。注意:空格和换行符是不同的。isspace函数可以检测空格、换行、制表符等。但题目要求单独统计空格?还是统计所有空白字符?引用[1]中单独统计了空格,而其他空白(如换行)算作其他字符。所以,我们在判断时,先判断是否是空格(''),然后再判断其他空白(如换行符)会被归入其他字符。但注意,isspace函数检测的是所有空白字符,包括空格、换行、制表符等。如果题目要求只统计空格(不包括换行、制表),那么我们不能用isspace,而要直接比较字符是否是空格('')。引用[1]的代码中使用了isspace,这样换行也会被当作空格?不对,引用[1]的代码中,空格是单独统计的,换行符在哪里?实际上,gets函数会丢弃换行符,而fgets会保留换行符。因此,在引用[1]的代码中,由于使用了gets,所以每行末尾没有换行符,因此他们用isspace判断的可能只有空格。但在我们的代码中,使用fgets,换行符会存在字符串中,因此我们需要区分。根据题目要求,要求统计空格(应该是空格字符''),而换行符算作其他字符。所以我们不能用isspace,而应该直接判断字符是否等于空格('')。对于其他空白字符(如制表符)我们也算作其他字符。因此,我们这样判断:大写字母:isupper小写字母:islower数字:isdigit空格:字符等于''其他:除了以上(包括换行符、制表符、标点等)注意:在输入字符串中,每行末尾有一个换行符('\n'),所以我们需要将其计入其他字符。代码结构:定义变量:charlines[3][82];inti,j;intupper=0,lower=0,digit=0,space=0,other=0;输入:for(i=0;i<3;i++){printf("请输入第%d行:",i+1);fgets(lines[i],82,stdin);}统计:for(i=0;i<3;i++){j=0;while(lines[i][j]!='\0'){//直到遇到字符串结束符charch=lines[i][j];if(isupper(ch)){upper++;}elseif(islower(ch)){lower++;}elseif(isdigit(ch)){digit++;}elseif(ch==''){//空格space++;}else{other++;}j++;}}但是,注意每行末尾的换行符:上面循环中,当遇到换行符时,它不等于结束符('\0'),所以会被处理。由于换行符不是大写、小写、数字、空格(我们只判断了空格字符''),所以换行符会被计入other。而换行符之后就是'\0',所以结束符不会被统计(因为循环条件是遇到结束符结束,结束符本身不会进入循环体)。但请注意:fgets读取的字符串,最后会有换行符,然后是结束符。所以上面的循环会处理到换行符,然后j++,再判断下一个字符(就是结束符),循环退出。另外,如果一行不足80个字符,那么fgets会在输入的回车处结束,也就是该行在末尾有一个换行符,然后结束符。这样统计是合理的。还有一种情况:如果输入超过81个字符(包括换行符),那么fgets只会读取81个字符(因为第二个参是82,所以读取81个,然后加结束符),剩余字符留在输入缓冲区。但题目要求每行80字符,所以我们认为不会超过。输出:printf("大写字母:%d\n",upper);printf("小写字母:%d\n",lower);printf("数字:%d\n",digit);printf("空格:%d\n",space);printf("其他字符:%d\n",other);但是,这里要注意:换行符被计入了其他字符。而题目要求的“其他字符”包括换行符、标点等,这是符合要求的。另外,我们使用了<ctype.h>中的函数,这些函数需要一个int参,但传入char是安全的(因为会自动提升为int)。完整代码:注意:包含头文件#include<stdio.h>#include<ctype.h>但是,用户提到了puts和gets,所以我们也要展示puts的使用(虽然这里用printf输出)。在输入后,我们可以用puts将某行打印出来。例如,在输入每一行之后,我们可以用puts输出该行(作为回显)?或者按题目要求不需要。根据引用[1]的代码,他们在输入后使用了puts(c[0]),然后输出一个换行。我们可以选择在输入后回显整个文章。修改输入部分:for(i=0;i<3;i++){printf("请输入第%d行:",i+1);fgets(lines[i],82,stdin);}printf("\n文章内容:\n");for(i=0;i<3;i++){puts(lines[i]);//由于每行都有换行符,所以puts输出后会自动换行,这样会导致多一个换行?因为puts会在字符串结束后自动添加换行,而我们的字符串中已经有一个换行符(如果有的话)?}但是,fgets读取的字符串包括换行符,所以puts会在输出该字符串后自动换行,于是会出现两次换行。因此,我们可以去掉字符串中的换行符再输出?或者不用puts,而用printf。我们可以这样输出:for(i=0;i<3;i++){printf("%s",lines[i]);//因为lines[i]中已经包含换行符}但这样和puts效果一样,除了puts会自动添加换行。不过,因为fgets读取的每行末尾有换行符,所以直接用printf会输出两次换行?不会,因为lines[i]中包含一个换行符,printf不会额外添加。所以输出一次换行。我们也可以使用puts,它会自动在末尾添加换行,那么就会变成两个换行(一行被输出两行)。所以为了避免这样,我们可以去掉换行符:但是为了展示puts,我们可以这样:for(i=0;i<3;i++){//将字符串中的换行符去掉if(lines[i][strlen(lines[i])-1]=='\n'){lines[i][strlen(lines[i])-1]='\0';}puts(lines[i]);//这样字符串中就没有换行符了,然后puts输出后会添加一个换行,所以结果是一个换行。}不过,题目并没有要求回显,所以我们可以省略。我们按照引用[1]的方式,在输入后输出整个文章(使用puts),但注意只输出一行(如引用[1]中puts(c[0]),然后输出一个换行符)。这里我们按题目要求来做。但题目没有要求输出文章内容,所以我们可以不输出。综上,我们编写代码:注意:在实际编程中,要确保输入的安全性(使用fgets)和统计的准确性。下面给出完整代码:</think> ### 字符组的定义、引用与统计字符类型 #### 一、字符组定义与引用 字符组是存储字符序列的据结构,以空字符 `\0` 作为结束标志[^1]。定义格式: ```c // 定义三维组存储文章 (3行×80字符) char article[3][81]; // 每行额外预留1个字符存储结束符 ``` 引用元素方法: ```c // 访问第2行第5个字符 char ch = article[1][4]; ``` #### 二、puts() 和 gets() 函数使用 1. **puts() 函数**: ```c puts(article[0]); // 输出第一行(自动添加换行) ``` 2. **gets() 函数(需谨慎使用)**: ```c gets(article[i]); // 读取整行(不检查边界) ``` > ⚠️ **注意**:推荐使用更安全的 `fgets()`: ```c fgets(article[i], 81, stdin); // 限定读取长度 ``` #### 三、字符统计实现 ```c #include <stdio.h> #include <ctype.h> int main() { char article[3][81]; // 3行×80字符 + 结束符 int upper = 0, lower = 0, digit = 0, other = 0; // 安全输入文章 for(int i = 0; i < 3; i++) { printf("输入第%d行:", i+1); fgets(article[i], 81, stdin); // 包含换行符 } // 遍历统计字符 for(int i = 0; i < 3; i++) { for(int j = 0; article[i][j] != '\0'; j++) { if(isupper(article[i][j])) upper++; else if(islower(article[i][j])) lower++; else if(isdigit(article[i][j])) digit++; else if(article[i][j] != '\n') other++; // 排除换行符 } } // 输出统计结果 printf("统计结果:\n"); printf("大写字母: %d\n小写字母: %d\n", upper, lower); printf("数字: %d\n其他字符: %d\n", digit, other); return 0; } ``` #### 四、关键点解析 1. **字符分类原理**: - `isupper()` 检测 $A$-$Z$ - `islower()` 检测 $a$-$z$ - `isdigit()` 检测 $0$-$9$ - 基于 ASCII 值比较实现:$A=65, a=97, 0=48$[^2][^3] 2. **安全输入处理**: - 使用 `fgets()` 避免缓冲区溢出 - 组维度 `[3][81]`(80字符 + 结束符 $\rightarrow$ $80+1=81$) - 换行符 `\n` 单独处理(不计入"其他字符") 3. **遍历终止条件**: - 内层循环结束条件:`article[i][j] != '\0'` - 精确获取有效字符长度:`strlen(article[i])`(需 `<string.h>`) #### 五、学表示 字符分类统计模型: $$C_{\text{type}} = \sum_{i=0}^{2} \sum_{j=0}^{L_i-1} \delta(f_{\text{type}}(c_{ij}))$$ 其中: - $c_{ij}$ 为第 $i$ 行第 $j$ 个字符 - $L_i$ 为第 $i$ 行有效字符 - $f_{\text{type}}$ 为分类函数(大写/小写等) - $\delta$ 为指示函数,当条件满足时值为 1
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值