当前位置: 首页 > article >正文

二级C语言2024-3易错题

1 结构

一个C语言程序是由( )。

A. 一个主程序和若干子程序组成
B. 函数组成
C. 若干过程组成
D. 若干子程序组成

一个C语言程序是由多个部分组成的,其中最核心的部分是函数。在C语言中,函数是实现特定功能的代码块,它们可以被重复调用以执行相同的任务。因此,选项B是正确的。

而一个程序可能包含多个函数


2 输出相关

下列叙述中正确的是( )。

A. 调用printf()函数时,必须要有输出项
B. 使用putchar()函数时,必须在之前包含头文件stdio.h
C. 在C语言中,整数可以以二进制、八进制或十六进制的形式输出
D. 调节getchar()函数读入字符时,可以从键盘上输入字符所对应的ASCII码

正确答案:B
关于C语言中的输入和输出函数,以下是对各选项的解释:

  • A.
    错误。printf()函数可以没有输出项,例如,printf(“Hello, world!\n”); 中的 “Hello, world!” 就是一个输出项,它可以输出字符。 但这样的一种情况 printf(“”); 是合法的,只是它什么都不输出。
  • B.
    正确。putchar() 函数是标准库函数,它是定义在 stdio.h 中的。因此要使用 putchar(),必须包含头文件 stdio.h。正确的写法如下:
#include <stdio.h>

int main() {
   putchar('A');
   return 0;
}
  • C.
    错误。C语言中的标准库函数 printf 并不直接支持二进制输出。整数可以使用八进制和十六进制的形式输出,但必须通过合适的格式控制符,例如,基于八进制使用 %o,基于十六进制使用 %x 或 %X。C语言中没有直接的格式化控制符来输出二进制。不过可以通过一定的逻辑实现二进制输出。
  • D.
    错误。getchar() 函数从标准输入读取下一个字符,并返回该字符的ASCII值。如果说”调节getchar()函数读入字符时,可以从键盘上输入字符所对应的ASCII码“,意思是要把字符转换成它的ASCII码来输入,这是不符合实际操作的。实际操作是直接输入字符,由getchar()捕获。例如输入 A 则 getchar() 返回 65(这是A的ASCII值)。

所以,正确答案是 B。


3 字符串比较

下述语句中,在字符串s1和s2相等时显示"they are Equal"的是( )。

A. if(*s1==*s2) puts(“they are Equal”);
B. if(!strcmp(s1,s2)) puts(“they are Equal”);
C. if(s1==s2) Puts(“they are Equal”);
D. if(strcmp(s1,s2)) puts(“they are Equal”);

正确答案 B.

  • A.
    这个条件仅比较了s1和s2的第一个字符是否相等。
  • C.
    这里使用的是直接指针比较(s1 == s2),它检查的是s1和s2这两个指针是否指向内存中的同一个地址,而不是比较它们所指向的内容是否相等。

strcmp

strcmp 是 C 语言标准库中的一个函数,用于比较两个字符串。它位于 <string.h> 头文件中。这个函数通过逐字节比较两个字符串来判断它们是否相等以及它们之间的顺序关系。下面是 strcmp 函数的一些关键点:

函数原型
int strcmp(const char *s1, const char *s2);
参数:

s1: 指向第一个要比较的以空字符终止的字符串。
s2: 指向第二个要比较的以空字符终止的字符串。

返回值:
  • 如果 s1 和 s2 完全相同,则返回 0。
  • 如果 s1 小于 s2(根据字典序),则返回一个小于 0 的整数。
  • 如果 s1 大于 s2(根据字典序),则返回一个大于 0 的整数。

这里的“小于”和“大于”是基于 ASCII 值进行比较的。例如,在 ASCII 中,大写字母 ‘A’ 到 ‘Z’ 的值小于小写字母 ‘a’ 到 ‘z’ 的值。


4 函数指针

给定程序中,函数fun的功能是用函数指针指向要调用的函数,并进行调用。规定在__2__处使fa指向函数f1,在__3__处使fb指向函数f2。当调用正确时,程序输出:

x1=5.000000,x2=3.000000,x1x1+x1x2=40.000000

请在程序的下划线处填入正确的内容并把下划线删除,使程序得出正确的结果。

注意:源程序存放在考生文件夹下的BLANK.C中。

不得增行或删行,也不得更改程序的结构!

给定源程序:

#include  <stdio.h>
double f1(double x)
{return x*x;}
double f2(double x, double y)
{return x*y;}
double fun(double a, double b)
{
/**********found**********/
  __1__ (*f)();
  double r1, r2;
/**********found**********/
  f = __2__ ;   /* point fountion f1 */
  r1 = f(a);
/**********found**********/
  f = __3__ ;   /* point fountion f2 */
  r2 = (*f)(a, b);
  return r1 + r2;
}
main()
{double x1=5, x2=3, r;
  r = fun(x1, x2);
  printf("\nx1=%f, x2=%f, x1*x1+x1*x2=%f\n",x1, x2, r);
}

函数指针的基础

声明函数指针

在C/C++中,声明一个函数指针需要遵循一定的语法格式,因为这关系到函数返回类型以及参数类型的准确性。最基本的格式如下:

返回类型 (*指针名称)(参数类型1, 参数类型2, ...);

例如,对于一个无参数且返回值为void的函数,函数指针的声明如下:

void (*funcPtr)();

而对于一个有两个int参数并返回int的函数,声明如下:

int (*func_ptr)(int, int);
函数指针的初始化

函数指针可以通过将函数的名称(函数名在程序中作为它的地址)赋值给它来初始化:

int add(int a, int b) {
    return a + b;
}

int (*func_ptr)(int, int) = add;

//或者可以采用另一种方式,先声明后赋值:
int (*func_ptr)(int, int);
func_ptr= add;
使用函数指针
  • 通过指针调用函数
    初始化后,你就可以通过函数指针调用函数了:

  • 使用函数指针调用函数
    一旦函数指针指向了一个具体的函数,我们就可以使用 (*指针变量名)(参数列表) 的形式来通过该指针调用函数。

int result = (*func_ptr)(3, 4); // 调用 add 函数,传入参数 3 和 4
//或者,由于函数指针的语法糖,我们也可以这样写:
int result = func_ptr(3, 4); // 同样调用 add 函数

int result = add(3, 4);
函数指针作为参数

函数指针可以作为参数传递给其他函数,这是编写回调函数的一种常用方法:

实现简易的计算函数:

#include <stdio.h>

int add(int a, int b) {
    return a + b;
}

int subtract(int a, int b) {
    return a - b;
}

int calculate(int a, int b, int (*operation)(int, int)) {
    return operation(a, b);
}

int main() {
    int a = 5, b = 3;
    printf("Add: %d\n", calculate(a, b, add));
    printf("Subtract: %d\n", calculate(a, b, subtract));
    return 0;
}

排序:

#include <stdio.h>

// 比较函数原型可以留空,因为在你的示例中并未直接使用到这个函数
int compare(int a, int b);

// 排序函数,接受一个数组、数组长度和一个比较函数指针
void sort(int *array, int length, int (*compare_func)(int, int)) {
    for (int i = 0; i < length - 1; ++i) {
        for (int j = 0; j < length - 1 - i; ++j) {
            if (compare_func(array[j], array[j + 1]) > 0) {
                // 交换元素
                int temp = array[j];
                array[j] = array[j + 1];
                array[j + 1] = temp;
            }
        }
    }
}

// 比较函数,用于升序排序
int ascending(int a, int b) {
    return a - b;
}

// 比较函数,用于降序排序
int descending(int a, int b) {
    return b - a;
}

int main() {
    int numbers[] = {5, 2, 9, 1, 5, 6};
    int length = sizeof(numbers) / sizeof(numbers[0]);

    // 使用升序比较函数进行排序
    sort(numbers, length, ascending);
    printf("Ascending order: ");
    for (int i = 0; i < length; i++) {
        printf("%d ", numbers[i]);
    }
    printf("\n");

    // 重新排序为降序,需重新赋初值
    for (int i = 0; i < length; i++) {
        numbers[i] = {5, 2, 9, 1, 5, 6}; // 若想重复上述数组,需要重新设置此数组的值
    }
    
    // 使用降序比较函数进行排序
    sort(numbers, length, descending);
    printf("Descending order: ");
    for (int i = 0; i < length; i++) {
        printf("%d ", numbers[i]);
    }
    printf("\n");

    return 0;
}
函数指针的应用场景
  • 回调函数:函数指针让我们在运行时决定调用哪个函数,这对于实现回调函数机制非常有用。
  • 状态机:在状态机模式中,函数指针可以用来表示不同状态下的行为。
  • 简化函数列表:通过函数指针数组,可以简化对一组函数的引用和管理。
  • 提高性能:在某些情况下,函数指针可以减少函数调用的开销,尤其是在循环内部调用时。
注意事项
  • 类型安全:确保函数指针类型与其指向的函数原型完全匹配,否则会导致不可预期的错误。
  • 空指针风险:未初始化的函数指针或被故意设置为NULL(或nullptr)的函数指针在使用前应该总是被检查是否为空,以避免运行时错误。
  • 可读性和复杂性:虽然函数指针非常强大,但它们也会增加代码的复杂性。明智的做法是在需要它们的强大功能时才使用它们。
C++中的额外考量

在C++中,函数指针仍然有其用途,但是现代C++越来越倾向于使用std::function和lambda表达式来实现类似的功能,这些方法提供了更好的类型安全和异常安全性。

#include <functional>
#include <iostream>

int add(int a, int b) {
    return a + b;
}

int main() {
    std::function<int(int, int)> func = add;
    std::cout << "Add Result: " << func(3, 4) << std::endl;

    auto multiply = [](int x, int y) { return x * y; };
    std::cout << "Multiply Result: " << multiply(3, 4) << std::endl;

    return 0;
}

std::function是C++11引入的一个类模板,能封装任何可调用的对象(包括函数指针、成员函数指针、甚至functor),提供了一个相对安全的调用方式。Lambda表达式则提供了一种便捷的方式来定义匿名函数。

总结来说,函数指针是C和C++中一种强大的特性,它为软件设计提供了灵活性,特别是在需要动态行为选择的场合。然而,随着C++的发展,一些更安全、更现代的替代方案正在变得流行。


写在后面的话

这套卷子就分析到这里,说实话,现在和几年前已经不是一个时代了。在如今这个时代,拥抱大模型是大势所趋。放在以前,想查找一些资料,一般就是上网自行查找,到书上找,或者向他人请教,但现在只需要打开网页,随便搜索一个大模型就能提问,甚至部分浏览器也集成了大模型,搜索时还会自动帮你总结整理,十分方便!


http://www.kler.cn/news/313656.html

相关文章:

  • 小叶OJ 2716: 过河问题 ← 贪心算法
  • Liveweb视频汇聚平台支持GB28181转RTMP、HLS、RTSP、FLV格式播放方案
  • nodejs 013:Prect 样式复用(multiple classes)例子
  • yolo自动化项目实例解析(二)ui页面整理 1.78
  • macOS Sequoia 正式版(24A335)黑苹果/Mac/虚拟机系统镜像
  • 2024华为杯E题:高速公路应急车道紧急启用模型
  • Broadcast:Android中实现组件及进程间通信
  • 使用 Anaconda 环境在Jupyter和PyCharm 中进行开发
  • 【计算机网络】网络层协议解析
  • NVM(node.js版本工具)的使用
  • 虚拟机ens33网卡不显示inet地址(已设置NOBOOT为yes)
  • 蓝桥杯2024省C
  • IDEA 2024.3 EAP新特征早览!
  • 音视频入门基础:AAC专题(4)——ADTS格式的AAC裸流实例分析
  • 微信小程序05-常用API下
  • EmguCV学习笔记 VB.Net 12.2 WeChatQRCode
  • 【FPGA】编程方式
  • Django学习实战篇六(适合略有基础的新手小白学习)(从0开发项目)
  • AUTOSAR_EXP_ARAComAPI的5章笔记(7)
  • iPhone 16系列:摄影艺术的全新演绎,探索影像新境界
  • Java面试篇基础部分-Java语言中的锁有哪些?
  • 基于SpringBoot+Vue的图书管理系统
  • 【设计模式-备忘录】
  • 计算机网络 ---- OSI参考模型TCP/IP模型
  • Cisco Catalyst 9000 Series Switches, IOS XE Release 17.15.1 ED
  • RabbitMQ消息转换器
  • 一条sql是如何执行的详解
  • Win10 安装Node.js 以及 Vue项目的创建
  • 构建现代应用的Python Serverless架构详解
  • Python中 BeautifulSoup和Selenium 定位元素和获取元素值的方法