对自己负责,虽然AI能秒杀这里的所有题目,请勿使用AI。
注意
背诵内容是代码和输出。以下所有需要背诵的代码均不带有解析,请自行理解,不会的问我。
Day 5
今日试题
正在出
Day 4
今日试题
输入与输出二
getchar()
c
int getchar(void);
功能:从标准输入读取一个字符
特性:
- 返回读取的字符(转换为
unsigned char类型) - 如果到达文件末尾或发生错误,返回
EOF(通常为-1) - 无参数,从输入缓冲区读取一个字符
- 会读取空白字符(空格、制表符、换行符等)
用法示例:
c
char c;
c = getchar(); // 读取一个字符
// 常用循环读取直到换行符
while ((c = getchar()) != '\n' && c != EOF) {
// 处理字符
}
putchar()
c
int putchar(int c);
功能:向标准输出写入一个字符
特性:
- 参数
c是要输出的字符(传入int类型,但实际输出低8位) - 返回输出的字符,出错时返回
EOF - 只能输出单个字符
用法示例:
c
char c = 'A';
putchar(c); // 输出字符A
putchar('\n'); // 输出换行符
putchar(65); // 输出ASCII码65对应的字符(也是A)
// 输出字符串
char str[] = "Hello";
for (int i = 0; str[i] != '\0'; i++) {
putchar(str[i]);
}
fgets()
注意
对于含有空格的字符串,只能使用fgets全部读入,不能使用scanf+%s
c
char *fgets(char *str, int n, FILE *stream);
功能:从标准输入读取一行字符串(到换行符为止),最终读取结果包含换行符。
参数:
- str:
char*存储读取字符串的字符数组(缓冲区) - n:
int最大读取字符数(包括结尾的\0) - stream:
FILE*文件流指针,通常为stdin(标准输入)
用法示例:
c
char buffer[100];
fgets(buffer, sizeof(buffer), stdin);
puts()
c
int puts(const char* str);
功能:向标准输出写入字符串,并自动添加换行符
特性:
- 参数
str是要输出的字符串指针 - 输出字符串后自动添加换行符(
\n) - 遇到第一个
\0结束输出 - 成功时返回非负值,出错时返回
EOF
用法示例:
c
char str[] = "Hello World";
puts(str); // 输出"Hello World"并换行
// 等效于:
printf("%s\n", str);
// 注意与putchar的区别
putchar('A'); // 输出单个字符A,不换行
puts("A"); // 输出字符A并换行
对比总结
| 函数 | 用途 | 参数 | 返回值 | 自动换行 | 安全性 |
|---|---|---|---|---|---|
getchar() |
读取单个字符 | 无 | 读取的字符/EOF | 否 | 安全 |
putchar() |
输出单个字符 | int字符 | 输出的字符/EOF | 否 | 安全 |
fgets() |
读取一行字符串 | char*缓冲区 | 缓冲区指针/EOF | 否 | 安全 |
puts() |
输出字符串 | const char*字符串 | 非负值/EOF | 是 | 安全 |
scanf() |
格式化输入 | 格式字符串+变量地址 | 成功读取项数 | 否 | 需谨慎 |
printf() |
格式化输出 | 格式字符串+变量值 | 输出字符数 | 否 | 安全 |
常见使用模式
- 读取直到换行符:
c
int c;
while ((c = getchar()) != '\n' && c != EOF) {
// 处理每个字符
}
- 逐个字符处理字符串:
c
void print_string(const char* str) {
for (int i = 0; str[i] != '\0'; i++) {
putchar(str[i]);
}
}
- 安全输入字符串:
c
char buffer[100];
fgets(buffer, sizeof(buffer), stdin);
注意事项
- gets()已经过时,永远不要在生产代码中使用
- getchar()返回int,而不是char,这是为了能正确处理EOF
- puts()会自动换行,这在某些情况下可能不是你想要的
- 字符函数通常比字符串函数更高效,适合处理大量数据
- 使用这些函数时要注意输入缓冲区的内容,避免残留字符影响后续读取
Day 3
今日试题
c
输入与输出一
常见的转义字符
\n:换行(Newline)\t:水平制表符(Tab),相当于一个长长的空格\':单引号\":双引号\\:反斜杠\0:空字符(Null Terminator),标志着字符串的结尾
scanf
最常见的格式化输入函数,对于第一个字符串参数,若其中的部分是占位符,则按如下方式解析;其余的则按照原样输入,若输入不符合,则读取失败。占位符同下printf。
scanf的占位符修饰没有printf那么丰富,常见的是通过%与字母之间的数字,限定输入位数。
printf
最常见的格式化输出函数,对于第一个字符串参数,若其中的部分是占位符,则按如下方式解析;其余的则按照原样输出。常见的占位符:
%c代表单个字符,对应参数应当为char。%s代表字符串,对应参数应当为char[]的指针(即为数组名)。%d代表整数,对应参数应当为int。%o代表八进制正整数,对应参数应当为int。%x代表十六进制正整数(小写字母),对应参数应当为int。%X代表十六进制正整数(大写字母),对应参数应当为int。%p代表指针所在的位置,对应参数应当为int*。%f代表小数,对应参数应当为float。%lf代表小数,对应参数应当为double。
事实上,每一个占位符都是由
- 前导 % 字符。
- (可选) 一个或多个修改转换行为的标志
-: 转换结果在字段内左对齐(默认情况下右对齐)。+: 有符号转换的符号总是前置在转换结果之前(默认情况下,结果只有在为负时才前置减号)。空格: 如果有符号转换的结果不以符号字符开头,或者为空,则在结果前置空格。如果存在 + 标志,则忽略此标志。#: 执行转换的替代形式。具体效果请参见下表,否则行为未定义。0:对于整数和浮点数转换,使用前导零填充字段而不是空格字符。对于整数,如果明确指定了精度,则忽略此项。对于使用此标志的其他转换,会导致未定义行为。如果存在-标志,则忽略此项。
- (可选) 整数值,指定最小字段宽度。当输出宽度小于整数值时,右对齐时,结果用空格字符(默认,除非选用了2中的0)在左侧填充;如果左对齐,则在右侧填充空格。如果参数值为负,则等同于指定 - 标志并使用正字段宽度(注意:这是最小宽度:值永远不会被截断)。
- (可选) . 后跟整数,用于指定转换的精度。在小数中用于指定小数点后的位数。
Day 2
今日试题
c
注意
此题原答案过长,现已修改
答案:
类型与变量定义
常见类型
常见的类型有int,double,char等。以下介绍常见类型:
char— 用于字符表示的类型。int— 最为常用和兼容的整数类型。范围是−2,147,483,648-2,147,483,648到2,147,483,6472,147,483,647,这个需要记忆。long long— 长整型,用于储存int储存不下的数字。范围是−263∼263−1-2^{63} \sim 2^{63} - 1,大致知道就好。double— 双精度浮点类型。在自己写代码时,除非空间不足,否则对于小数必须使用double而非float。
修饰符
类型修饰符需要了解unsigned,意思即无符号(把最高位的符号位也作为数据储存,范围只有正数部分)
定义修饰符需要了解:
const— 用 const 限定类型声明的对象可能被编译器放置在只读内存中,不可以被赋值,也不可以被指针修改。自己写代码一般不会用上。static— 可以简单的理解为在程序执行过程中,static变量只会被初始化一次,并在初始化后值永久保存,任何处都可访问修改,且修改后所有地方同步。
初始化
对于全局变量和static变量,将默认初始化为0。局部变量(就是剩下的)在未初始化前不可使用。因此,除非变量从输入中读取值,否则必须初始化,尤其需要注意计数、求和类变量。
对于数组,定义时必须用直接的数指明它的长度(大小),可以参见题目上给出的数据范围,然后略微开大一点。避免使用变量进行初始化,避免使用变长数组(VLA)。
c
int n[10]; //✅️
int a=5;
int nn[a]; //❌️
const int aa=5;
int nnn[aa]; //❌️
特别提醒
事实上,上面的2-3可以正常通过编译,只不过不建议这么写
隐式转换
隐式转换是C编译器在某些成精下自动完成的对变量的类型转换:
- 算术运算:当不同类型的操作数参与运算时,C语言会自动将较小类型转换为较大类型,以避免数据丢失。
- 赋值操作:在赋值表达式中,右边表达式的值会自动隐式转换为左边变量的类型,并赋值给它。
- 函数调用:在函数调用时,实参的类型会隐式转换为形参的类型。
转换顺序为:char → short → int → long → float → double
例题
c
以下为AI解析:
🧐 结果分析与解析
🔑 关键知识点
static int counter:它只被初始化一次(为0),每次调用modify_and_print函数时,它的值都会永久保存并递增。int溢出:int的最大值是 2,147,483,6472,147,483,647。当对一个int类型的变量进行加 11 操作,使其超过最大值时,会发生溢出,变成 intint 范围内的最小值(−2,147,483,648-2,147,483,648)。- 隐式类型转换(运算):当
int和unsigned int进行算术运算时,int会被隐式提升为unsigned int,结果也是unsigned int。但是,当结果用%d打印时,又会被解释为int。
逐步执行
Call 1: modify_and_print(2147483647, 200)
counter: 0 →\to 1a: 2,147,483,6472,147,483,647 (int)b: 200200 (unsigned int)
a + b:int21474836472147483647 提升为unsigned int,结果为 2147483647+200=21474838472147483647 + 200 = 2147483847(unsigned int)。- 用
%d打印时,此unsigned int值 21474838472147483847 会被解释为一个int,即 2147483847−232≈−21474834492147483847 - 2^{32} \approx -2147483449。 (此处 2147483847>21474836472147483847 > 2147483647,发生溢出,数值在有符号int范围内循环,结果是负数。)
- 用
result_c = a * 2.0: aa (int) 隐式提升为double,计算 2147483647×2.0=4294967294.02147483647 \times 2.0 = 4294967294.0 (double)。赋值给long long,结果是 4,294,967,2944,294,967,294。
- Output 1:
Stage 1: a + b = -2147483449Stage 1: a * 2.0 = 4294967294
Call 2: modify_and_print(2147483647 + 1, 50)
counter: 1 →\to 2x + 1:2147483647 + 1发生int溢出,传递给a的值是 −2147483648\mathbf{-2147483648} (int的最小值)。a: −2,147,483,648-2,147,483,648b: 5050 (unsigned int)
b - 100: bb (unsigned int) 和 100100 (int) 运算, 100100 提升为unsigned int。结果为 50−100=−5050 - 100 = -50(unsigned int)。unsigned int无法表示负数,−50-50 会在unsigned int范围内回绕(wrap around),即 −50+232=4294967246-50 + 2^{32} = 4294967246。- 用
%d打印时,此unsigned int值 42949672464294967246 会被解释为一个int,结果仍然是 -50。
result_c = a * 2.0: aa (int) −2147483648-2147483648 提升为double,计算 −2147483648×2.0=−4294967296.0-2147483648 \times 2.0 = -4294967296.0 (double)。赋值给long long,结果是 −4,294,967,296-4,294,967,296。
- Output 2:
Stage 2: b - 100 = -50Stage 2: a * 2.0 = -4294967296
Call 3: modify_and_print(-5, 200)
counter: 2 →\to 3a: −5-5 (int)b: 200200 (unsigned int)
a + b:int−5-5 提升为unsigned int。在unsigned int看来,−5-5 会回绕成 232−5=42949672912^{32} - 5 = 4294967291。结果是 4294967291+200=42949674914294967291 + 200 = 4294967491 (unsigned int)。- 用
%d打印时,此unsigned int值 42949674914294967491 会被解释为一个int,即 4294967491−232=1954294967491 - 2^{32} = \mathbf{195}。
- 用
result_c = a * 2.0: −5×2.0=−10.0-5 \times 2.0 = -10.0 (double)。赋值给long long,结果是 −10-10。
- Output 3:
Stage 3: a + b = 195Stage 3: a * 2.0 = -10
✅ 最终输出结果
Stage 1: a + b = -2147483449
Stage 1: a * 2.0 = 4294967294
Stage 2: b - 100 = -50
Stage 2: a * 2.0 = -4294967296
Stage 3: a + b = 195
Stage 3: a * 2.0 = -10
Day 1
基本的C语言程序结构
c
#include<stdio.h>
//全局变量定义区
//函数声明区
int main(){
//主函数执行区
return 0;
}
//函数定义区
基本流结构
if-else
if (i > 1)
if(j > 2)
printf("%d > 1 and %d > 2\n", i, j);
else // this else is part of if(j>2), not part of if(i>1)
printf("%d > 1 and %d <= 2\n", i, j);
结果
情况1: 如果 i <= 1
- 外层if条件不满足
- 无任何输出
情况2: 如果 i > 1 且 j > 2
- 打印
"i > 1 and j > 2\n"
情况3: 如果 i > 1 且 j <= 2
- 打印
"i > 1 and j <= 2\n"
for
c
结果
条件判断: i=1
循环体开始[第1次]: i=1, j=0, k=1
循环体结束[第1次]
条件判断: i=2
循环体开始[第2次]: i=2, j=2, k=2
最终结果: i=4, j=4, k=2
今日试题
读程序,写结果:
c
答案:
