目录
3.4:封装函数 实现测量字符串的长度(my_strlen)
3.7: 分装函数完成my_strchr 查找第一个字符出现的位置
3.8: 分装函数完成my_str_insert 在指定位置插入字符串
知识点1【函数的概念】
1、函数的分类:从定义角度分类
1.库函数 (c 库实现的)
2.自定义函数 (程序员自己实现的函数)
3.系统调用 (操作系统实现的函数)
2、函数的分类:从参数角度分类
1.有参函数
2.无参函数
void fun(int x, int y)有参函数
{
}
void fun(void)//无参函数
{
}
3、函数的分类:从返回值角度分类
void fun(){}
int fun(){}
知识点2【函数的3要素】
函数的定义、函数的声明 、函数的调用
函数的定义:确定函数的返回值类型 函数名 函数的参数 实现函数体 (创建函数)
返回值类型 函数名(函数参数)
{
函数体;(函数的功能代码)
}
函数声明:说明函数的返回值类型 函数名 函数的参数 注意:不实现函数体(声明函数存在)
extern 返回值类型 函数名(函数参数);
函数调用:执行函数
函数名(如果有参数就传参);
例如:
#include<stdio.h>
//void fun01();//定义和声明在同一源文件中
extern void fun01();//定义和声明可以在同一源文件 也可以在不同源文件
int main(){
//函数调用
fun01();//正确的
//void fun01();//声明语句
return 0;
}
//函数的定义
void fun01(){
printf("my_fun01\n");
return;
}
知识点3【函数的传参】(重要)
1、无参的函数
void fun01(void)//无参的函数 不需要外界传参
{
}
调用
fun01();
2、int作为函数的参数
#include<stdio.h>
//函数声明
extern int my_max(int a, int b);
void test01(){
//需求:键盘输入两个int数据 比较大小
int data1 = 0, data2 = 0;
printf("键盘输入两个int数据:");
scanf("%d %d", &data1, &data2);
//调用函数实现:获取最大值
int ret = 0;
ret = my_max(data1, data2);
printf("最大值為:%d\n", ret);
}
//函数定义
int my_max(int a, int b){
return a>b?a:b;
}
int main(){
test01();
return 0;
}
函数调用的逻辑
3、数组作为函数的参数
3.1:键盘输入10个int数,寻找出最大值
数组作为函数参数时会被优化为指针变量:int arr[] ---> int *arr
因此不能通过在函数内部对数组形参sizeof来得到数组元素个数,个数只能通过传参得到。
#include <stdio.h>
extern void input_int_array(int arr[], int n);
extern void print_int_array(int arr[], int n);
extern int get_max_from_array(int arr[], int n);
int main(int argc, char const *argv[]){
//键盘输入10个int数,寻找出最大值
int arr[10]={0};
int n = sizeof(arr)/sizeof(arr[0]);
//封装函数 获取键盘输入
input_int_array(arr, n);
//封装函数 输出元素内容
print_int_array(arr, n);
//封装函数 获取数组元素的最大值
int ret = 0;
ret = get_max_from_array(arr, n);
printf("最大值:%d\n", ret);
return 0;
}
//操作形参中的arr等价操作外部实参的arr
void input_int_array(int arr[], int n){
printf("请输入%d个int数据:", n);
int i=0;
for ( i = 0; i < n; i++){
scanf("%d", &arr[i]);
}
return;
}
void print_int_array(int arr[], int n){
int i=0;
for ( i = 0; i < n; i++){
printf("%d ", arr[i]);
}
printf("\n");
return;
}
int get_max_from_array(int arr[], int n){
int max = arr[0];
int i=0;
for ( i = 1; i < n; i++){
if(max < arr[i])
max = arr[i];
}
return max;
}
3.2:键盘输入10个数 分函数完成 数组的排序(冒泡法)
#include <stdio.h>
extern void input_int_array(int arr[], int n);
extern void sort_int_array(int arr[], int n);
extern void print_int_array(int arr[], int n);
int main(int argc, char const *argv[]){
int arr[10] = {0};
int n = sizeof(arr)/sizeof(arr[0]);
//获取键盘输入
input_int_array(arr, n);
//排序
sort_int_array(arr, n);
//遍历数组
print_int_array(arr, n);
return 0;
}
void input_int_array(int arr[], int n){
printf("请输入%d个int数据:", n);
int i=0;
for ( i = 0; i < n; i++){
scanf("%d", &arr[i]);
}
return;
}
void sort_int_array(int arr[], int n){
int i=0, j=0;
for ( i = 0; i < n-1; i++){
int flag = 0;
for ( j = 0; j < n-1-i; j++){
if(arr[j] > arr[j+1]){
flag = 1;
int tmp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = tmp;
}
}
if(flag == 0)
break;//已经有序 不用继续循环
}
return;
}
void print_int_array(int arr[], int n){
int i=0;
for ( i = 0; i < n; i++){
printf("%d ", arr[i]);
}
printf("\n");
return;
}
3.3:键盘输入10个数 分函数完成 数组的逆置
#include <stdio.h>
extern void input_int_array(int arr[], int n);
extern void reverse_int_array(int arr[], int n);
extern void print_int_array(int arr[], int n);
int main(int argc, char const *argv[]){
int arr[10] = {0};
int n = sizeof(arr)/sizeof(arr[0]);
//获取键盘输入
input_int_array(arr, n);
//排序
reverse_int_array(arr, n);
//遍历数组
print_int_array(arr, n);
return 0;
}
void input_int_array(int arr[], int n){
printf("请输入%d个int数据:", n);
int i=0;
for ( i = 0; i < n; i++){
scanf("%d", &arr[i]);
}
return;
}
void reverse_int_array(int arr[], int n){
int start = 0, end = n-1;
while(start < end){
int cur = arr[start];
arr[start] = arr[end];
arr[end] = cur;
start++;
end--;
}
return;
}
void print_int_array(int arr[], int n){
int i=0;
for ( i = 0; i < n; i++){
printf("%d ", arr[i]);
}
printf("\n");
return;
}
3.4:封装函数 实现测量字符串的长度(my_strlen)
#include <stdio.h>
extern int my_strlen(char buf[]);
int main(int argc, char const *argv[]){
char buf[128]="";
//获取键盘输入
fgets(buf,sizeof(buf), stdin);
//分装my_strlen
int len=0;
len = my_strlen(buf);
printf("字符串%s的长度为:%d\n", buf, len);
return 0;
}
int my_strlen(char buf[]){
int i=0;
while(buf[i] != '\0')
i++;
return i;
}
3.5: 分装函数完成my_strcpy 字符串拷贝
#include <stdio.h>
void my_strcpy(char buf1[], char buf2[]);
int main(int argc, char const *argv[]){
char buf1[128]="";
char buf2[128]="";
//获取键盘输入
fgets(buf1,sizeof(buf1), stdin);
//my_strcpy
my_strcpy(buf2, buf1);
//打印
printf("%s\n", buf2);
return 0;
}
void my_strcpy(char buf1[], char buf2[]){
int i = 0;
while(buf1[i]=buf2[i])
i++;
}
3.6: 分装函数完成my_strcat 字符串拼接
#include <stdio.h>
void my_strcat(char buf1[], char buf2[]);
int main(int argc, char const *argv[]){
char buf1[128]="";
char buf2[128]="";
//获取键盘输入
fgets(buf1,sizeof(buf1), stdin);
fgets(buf2,sizeof(buf2), stdin);
//my_strcat
my_strcat(buf2, buf1);
//打印
printf("%s\n", buf2);
return 0;
}
void my_strcat(char buf1[], char buf2[]){
int i = 0, j = 0;
while(buf1[i] && ++i);
while(buf2[j] && (buf1[i++] = buf2[j++]));
}
3.7: 分装函数完成my_strchr 查找第一个字符出现的位置
#include <stdio.h>
int my_strchr(char buf[], char ch);
int main(int argc, char const *argv[]){
char buf[128]="";
//获取键盘输入
fgets(buf,sizeof(buf), stdin);
char ch = '\0';
scanf("%c", &ch);
//my_strcat
int n = my_strchr(buf, ch);
//打印
printf("%d\n", n);
return 0;
}
int my_strchr(char buf[], char ch){
int i = 0;
while(buf[i]){
if(buf[i] == ch)
return i;
i++;
}
}
3.8: 分装函数完成my_str_insert 在指定位置插入字符串
#include <stdio.h>
#include <string.h>
extern void my_str_insert(char buf1[], char buf2[], int pos);
int main(int argc, char const *argv[]){
char buf1[128]="";
char buf2[128]="";
printf("请输入第一个字符串:");
fgets(buf1, sizeof(buf1), stdin);
//strlen是测量字符串的长度 不包含'\0'
buf1[strlen(buf1)-1]='\0';//去掉字符串的中的回车符
printf("请输入第二个字符串:");
fgets(buf2, sizeof(buf2), stdin);
buf2[strlen(buf2)-1]='\0';
//计算buf1的长度
int buf1_len=0;
while(buf1[buf1_len] != '\0')
buf1_len++;
printf("请输入插入的位置:");
int pos = 0;
scanf("%d", &pos);
if(pos<0 || pos > buf1_len){
printf("插入位置必须在%d~%d之间\n", 0, buf1_len);
return 0;
}
//字符串的插入函数
my_str_insert(buf1, buf2, pos);
printf("buf1:%s\n", buf1);
return 0;
}
void my_str_insert(char buf1[], char buf2[], int pos){
//1、计算buf2的长度
int buf2_len = 0;
while(buf2[buf2_len] != '\0')
buf2_len++;
//2、将i定位到buf1的'\0'的位置
int i=0;
while(buf1[i] != '\0')
i++;
//3、从buf1的尾部 逐个字符移动 空出合适的位置
do{
buf1[i+buf2_len] = buf1[i];
} while ((i!=pos) && i--);
//4、将buf2的内容插入到buf1中
int j=0;
while(buf2[j] != '\0'){
buf1[i] = buf2[j];
i++;
j++;
}
return;
}
3.9打字游戏
1、获取随机字符串
如何产生随机数
#include<stdlib.h>
int rand(void)函数通过返回值返回随机数
//是产生随机数之前 一定要设置随机数种子(基准值)
srand(种子);
将随机数变换成字符
//设置随机数种子
//time(NULL)获取当前时间(1970~现在的所经历秒数)
srand(time(NULL));
char ch = '\0';
ch = 'a'+rand()%26;//rand()函数的返回值就是随机数
printf("ch = %c\n", ch);
将其随机的字符放入字符数组中
2、键盘输入字符(不敲回车)
#include <termios.h>
#include <stdio.h>
#include <unistd.h>
char mygetch( ) {
struct termios oldt, newt;
char ch;
tcgetattr( STDIN_FILENO, &oldt );
newt = oldt;
newt.c_lflag &= ~( ICANON | ECHO );
tcsetattr( STDIN_FILENO, TCSANOW, &newt );
ch = getchar();
tcsetattr( STDIN_FILENO, TCSANOW, &oldt );
return ch;
}
判断输入正确 字符原样输出 错误输出'_' 统计正确的数量
3、获取所耗时间
第一个字符输入的时候 纪录时间
int start_time = 0;
start_time = time(NULL);
最后一个字符输入的时候 纪录时间
int end_time = 0;
end_time = time(NULL);
所耗时间:end_time -start_time
下面公布一下我自己实现的程序:
#include <time.h>
#include <stdlib.h>
#include "termios.h"
#include <stdio.h>
#include <unistd.h>
extern void game_init();
extern char mygetch() ;
extern void set_str_rand(char *str);
extern int start_game(char *str, int *time);
int main(int argc, char const *argv[]){
//变量初始化
int right_time = 0;
int game_time = 0;
char str[51] = "";
int str_count = sizeof(str) - 1;
char stat = '\0';
//显示提示信息
game_init();
while(1){
//设置随机字符串
set_str_rand(str);
//按下任意键显示字符串
mygetch();
printf("%s\n",str);
//游戏开始
right_time = start_game(str, &game_time);
//游戏结束
printf("\n输入完成!\n");
printf("用时:%d s\n",game_time);
printf("正确率:%.2f %%\n",(float)right_time/(float)str_count*100);
printf("按下ESC退出,空格键继续!\n");
stat = 0;
while(stat != ' '){
stat = mygetch();
if(stat == 27)
return 0;
}
}
return 0;
}
void game_init(){
printf("***************************************************\n");
printf("* 1、输入过程中无法退出 *\n");
printf("* 2、请按所给字母敲击键盘 *\n");
printf("* 3、按任意键开始测试,按下首字母时开始计时 *\n");
printf("* 4、输入出错,打印以_表示 *\n");
printf("* 5、按下任意键显示字符串 *\n");
printf("***************************************************\n");
}
char mygetch( ) {
struct termios oldt, newt;
char ch;
tcgetattr( STDIN_FILENO, &oldt );
newt = oldt;
newt.c_lflag &= ~( ICANON | ECHO );
tcsetattr( STDIN_FILENO, TCSANOW, &newt );
ch = getchar();
tcsetattr( STDIN_FILENO, TCSANOW, &oldt );
return ch;
}
void set_str_rand(char *str)
{
srand(time(NULL));
int i = 0;
for(i=0; i<50; i++){
//str[i] = rand()%('z' - 'a') + 'a'; //小写字母
//str[i] = rand()%('z' - 'a') + 'A'; //大写字母
while(!(str[i]>='a' && str[i]<='z') && !(str[i]>='A' && str[i]<='Z')) //大小写字母
str[i] = rand()%('z' - 'A') + 'A';
//while(!(str[i]>='a' && str[i]<='z') && !(str[i]>='A' && str[i]<='Z') && !(str[i]>='0' && str[i]<='9')) //大小写字母加数字
// str[i] = rand()%('z' - '0') + '0';
//str[i] = rand()%('z' - '#') + '#'; //所有可显示符号
}
}
int start_game(char *str, int *ti){
int i = 0;
int start_time = 0, end_time = 0;
int right_time = 0;
//计算字符串总长度
int str_count = 0;
while(str[str_count] != '\0' && ++str_count);
//开始读取键盘信息并记录时间
for (i = 0; i < str_count; i++){
char ch = mygetch();
if(i == 0)
start_time = time(NULL);
if(ch == str[i]){
right_time++;
putchar(ch);
}
else{
putchar('_');
}
}
end_time = time(NULL);
*ti = end_time - start_time;
return right_time;
}
知识点4【函数的注意事项】(了解)
1、如果函数的返回值类型省略 默认为int (别这样做)
fun01(){
}
2、如果函数没有参数 请加void修饰 而不是省略不写
void fun01(void){
}
void fun02(){
}
#include <stdio.h>
void fun01(void){
}
void fun02(){
//使用不了传递过来的实参
return;
}
int main(int argc, char const *argv[]){
//fun01(10,20);//err 不允许传参
fun01();//ok
fun02(10,20);//不会报错
return 0;
}
使用函数的好处?
1、定义一次,可以多次调用,减少代码的冗余度。
2、使咱们代码,模块化更好,方便调试程序,而且阅读方便