专升本笔记记载-C语言-考试中奇奇怪怪的语法&&编程例题文章推荐

C语言考点总结

编辑编译链接运行语言
源文件.ccl.exe -> .objlink.exe -> .exe运行C
源文件.asmMASM.exe -> .objlink.exe -> .exe运行汇编

编程例题推荐文章: https://blog.csdn.net/liu17234050/article/details/104217830
本文章只记载特殊怪异语法.

规则篇

标识符定义规则

image-20221222082316178

标识符必须以大小写英文字母或者下划线作为首字母.

无语的文字题 (简单收集)

image-20230403151712960

科学计数法语法规则

void Test() {
	// [整数|小数]e[+-]整数[lf]
	int A = (1e3, 2e6f, 3e6l, 4e+5, 1.2e-6);
}
单引号规则
void Test() {
    // 单引号可以放四个内容
	printf('ABCD'); // 输出 ABCD
    // 单引号赋值时, 取最后一位.
    int Test = 'ABCD';
	printf("%c", Test); // 输出 D
}
00截断问题

image-20221222090745023

float后缀f的规则

image-20230324152614435

f前面的内容必须是小数.

printf中的float四舍五入问题

image-20230324181207937

注意: 只有float有四舍五入!!!!如果是int则没有!!!

image-20230405180834106

宏定义问题

void Test(){
    #define A 1
    #define FF A + A
    int x = FF * FF; // int x = 1 + 1 * 1 + 1
    printf("%d", x); // 输出3
    
    // define关键字可以通过undef进行取消.
    #undef A
}

并且, 宏定义不能与变量名冲突, 因为宏定义是常量, 所以宏定义也不允许被修改.

宏定义专升本特别注意事项

image-20230329214212869

常量拓展
void main() {
	const int PI = 3.14;
	PI = 1234; // 报错
}

进制转换

# include <stdio.h>

void main() {
	int Test1 = 012345; // 长度不限制, 八进制
	int Test2 = 0X123123123; // 长度不限制, 十六进制, 0x可以写成0X大写形式.

	int BaJinZhi1 = 0123; // 长度不限制
	char BaJinZhi2 = '\123'; // \ + 3位八进制
	printf("%d, %d", BaJinZhi1, BaJinZhi2);

	// long ShiLiuJinZhi1 = 0x1000; // 长度不限制
	// long ShiLiuJinZhi2 = '\x10'; // \x + 2位16进制, 原因很简单, 字符的ASCII码是 0~127. 不允许超过该范围. 否则出现乱数.
	printf("\n 八进制 %o, 十六进制 %x %X %#x %#X", 123, 123, 123, 123, 123);
}

image-20221222152141826

运算符优先级

image-20230323100528598

算数 > 关系 > 逻辑 > 赋值 > 逗号

例题1: 运算

image-20230323101614155

表达式可以写成 x = (x + ((a % 3) * (int)(x + y) % 2) / 4);

image-20230323104715710

赋值规则

从右向左

void Test() {
	int exam1 = 10;
	int Exam1Result = exam1 += exam1 -= exam1 - exam1; // 结果是 20, 因为赋值是从右向左

	int exam2 = 3;
	exam2 *= exam2 += exam2 - 2; // 16, 从右向左.
}

函数参数执行优先级 (从后往前)

# include <stdio.h>

int Result(int x){
    static int k = 0;
    x += k;
    k ++;
    return x;
}

void main(){
    int x = 0;
    // 函数参数相同时, 从后往前执行
    printf("%d %d", Result(x), Result(x)); // 1 0
    getchar();
}

// 经典例题:
# include <stdio.h>

void main(){
    int* p;
    int a[5] = {4, 3, 5, 6, 1};
    p = a;
    printf("%d %d \n", *p++, (*p)++); 
    /*
        ++ 比 指针优先级高, 又因为函数的参数传递是从后往前.
        结果: 5 4
    */
    printf("%d \n", *p); // 指针已自动+1, 变成3
    getchar();
    
}

scanf本质 (要地址,可修改数组中的内容)

image-20230318213345957

考试函数标准库文件

<stdio.h>
	getchar()
	putchar()
	scanf()
	printf()
	puts()
	gets()
<string.h>
	strcmp()
	strlen()
不需要标准库的函数:
	sizeof()

技巧篇

右移16位不出0的情况

image-20230404205650654

等价题目

image-20230324155017416

根据题干, 把e设为0, e是0的时候, 表达式为1. 那么根据e是0 -> 结果1得出选项A.

一行法阅读程序

image-20230329210600236

+=-=同一表达式

#include "stdio.h"
void main(){
    int a = 3;
    a += a-= a * a;
    /*
        解析为:
           a = a - a * a
           a = a + a
    */
    printf("%d", a);
    getchar();
}

# include <stdio.h>
void main(){
    int a = 5;
    // a *= a += a++; // 121
    a = a + a++; // a++ 先执行, 后面的是5, 但是前面的a变成了6 结果是 5+6 = 11
    a = a * a; // 11 * 11 = 121

    getchar();
}
++不允许放到等号左边

image-20230327090037253

当然, 下面这种形式也是错误的.

image-20230327090341491

if 坑点

image-20230324154326135

看到if没带大括号, 第一时间反应第一条语句是谁.

取余公式

a % b = a - a / b * b

取余规则

整数 % 整数

三元运算符嵌套问题

image-20230320214025869

注意加上小括号, 这样方便判断.

for逻辑梳理

void main() {
	int i;
	for (i = 0; i < 10; i ++) {
		printf("\n%d", i); // 输出 0~9
	}
	printf("%d", i); // i = 10
    
    int i, j;
	for (i = 0, j = 0; j < 10; i ++, j +=2 ) {
		printf("\n%d, %d", i, j);
		/*
			0, 0
			1, 2
			2, 4
			3, 6
			4, 8
		*/
	}
	printf("\n%d, %d", i, j); // 5, 10
}

image-20230216211623799

for循环作用域问题
# include <stdio.h>
// static 遇到代码块作用域问题
int square(int i){
  return i*i;
}

void main(){
  int i = 0;
  i = square(i);
  // int i 不会进入 for(){} 中 {} 的作用域
  for(; i < 3; i++){
    // static 在 {} 中, 作用域只是在 {} 中.
    static int i = 1;
    i += square(i);
    printf("%d, ", i);
  }
  printf("\n%d", i);
  getchar();
}

进制转换与微机原理的区别 (注意研究)

# include <stdio.h>
// C语言会回到原码.
void main() {
	int num = ~2;
	printf("%d", num); // 结果是 -3
	/*
	运算规则:
		2 的二进制值: 0010
		~2 : 1101 遇到了print, print来对其求补码后输出
		[~2]反 : 1010 [~2]补 : 1011 -> -3 (只是输出的时候输出2进制罢了)

		和微机原理区别: MOV AL, 2
					  NOT AL  (结果是FD) 1111 1101
	*/
    
    /*
		2&-3:
		2的补码: 00000000 00000000 00000000 00000010
		-3的补码:11111111 11111111 11111111 11111101
		&操作:   00000000 00000000 00000000 00000000 (结果是正数, 不需要回推)
	*/
	int result = 2 & -3;
	printf("%d", result); // 结果是 0
}

例题分析集合:

# include <stdio.h>

void main() {
	int exam1 = ~2;
	int exam2 = 2 & 3;
	int exam3 = 2 | 3;
	int exam4 = ~- 5;
	int exam5 = 13 & 7;
	int exam6 = 5 | 4;
	int exam7 = -3 ^ 3;
	printf("%d", exam7);
	/*
		exam1 分析:
			2 补码: 00000000 00000000 00000000 00000010
			~取 反: 11111111 11111111 11111111 11111101 (发现是负数, 需要回到原码)
			-1回原: 11111111 11111111 11111111 11111100
			取反回原:10000000 00000000 00000000 00000011 结果-3
		exam2 分析:
			2 补码: 00000000 00000000 00000000 00000010
			3 补码: 00000000 00000000 00000000 00000011
			& 操作: 00000000 00000000 00000000 00000010 (发现正数, 无需回去) 结果2
		exam3 分析:
			2 补码: 00000000 00000000 00000000 00000010
			3 补码: 00000000 00000000 00000000 00000011
			| 操作: 00000000 00000000 00000000 00000011 (发现正数, 无需回去) 结果3
		exam4 分析:
			-5原码: 10000000 00000000 00000000 00000101
			-5反码: 11111111 11111111 11111111 11111010
			-5补码: 11111111 11111111 11111111 11111011
			~ 操作: 00000000 00000000 00000000 00000100 (发现正数, 无需回去) 结果4
		exam5 分析:
			13补码: 00000000 00000000 00000000 00001101
			7 补码: 00000000 00000000 00000000 00000111
			& 操作: 00000000 00000000 00000000 00000101 (发现正数, 无需回去) 结果5
		exam6 分析:
			5 补码: 00000000 00000000 00000000 00000101
			4 补码: 00000000 00000000 00000000 00000100
			| 操作: 00000000 00000000 00000000 00000101 (发现正数, 无需回去) 结果5
		exam7 分析:
			-3原码: 10000000 00000000 00000000 00000011
			-3反码: 11111111 11111111 11111111 11111100
			-3补码: 11111111 11111111 11111111 11111101
			3 补码: 00000000 00000000 00000000 00000011
			^ 操作: 11111111 11111111 11111111 11111110 (发现负数, 需要回去)
			-1操作: 11111111 11111111 11111111 11111101
			取  反: 10000000 00000000 00000000 00000010 结果-2
	*/
    int Test = -2 >> 2;
	/*
		-2 原码: 10000000 00000000 00000000 00000010
		-2 反码: 11111111 11111111 11111111 11111101
		-2 补码: 11111111 11111111 11111111 11111110
		>> 操作: 11111111 11111111 11111111 11111111 (发现负数, 回原)
		-1 操作: 11111111 11111111 11111111 11111110
		取反操作: 10000000 00000000 00000000 00000001 结果-1
	*/
}

字符串长度问题

image-20230324164258759

\0的位置减去首地址, 即可得到长度.

执行顺序问题 (疏忽导致做错)

image-20230326165856789

for while dowhile 循环次数

int i = 0;
while(i < 10){
    i++;
    printf("i = %d \n", i); // 结果十次
}

int i = 0;
do{
    i++;
    printf("i = %d \n", i); // 结果十次
}while(i < 10);

for(int i = 0; i < 10; i ++){} // 结果十次

# include <stdio.h>

void main(){
    int k = 0;
    while(k++ <= 10);
    printf("%d", k);
    // k = 10 时, 执行了一次 k++
    // 第二次判断 又执行了一次 k++
    // 结果是 12
    getchar();
}

递归题目做题思路

image-20230318224515419

选择&阅读题目特别注意
printf
printf要特别注意:
 1. printf到底打印的什么 是%s?%c?%d?%f?等等
 2. printf到底在什么条件下才打印

本质篇

函数无定义类型

image-20230318162453780

数组访问的本质

因为数组的传递形式为首地址传递, 在此发现了一种姿势:

void main() {
	int Arr[] = {1,2,3};
	printf("%d", Arr[0]); // 正常访问形式: 翻译下来则是 "首地址[0]", 则是 "地址+0 存储单元的内容"

	// 引发思考: 是否 首地址[0] 可以取出任何数据的内容
	int myNum = 10;
	printf("%d", (&myNum) [0] ); // 结果为 10, 思路正确.
}
数组赋值问题

image-20230327094111015

只能在初始化的时候进行赋值!!!

数组与指针唯一的区别
# include <stdio.h>
# include <string.h>

void main(){
  char *st = "how are you";
  char a[11];
  printf("%d", a++); // 代码会报错, 原因是, 数组是固定大小, 不允许自增.
  getchar();
  getchar();
}

sizeof 取数组长度坑点

image-20230101094126058

因为数组是首地址传递, 实际上TestSize方法并不知道外部的数据有多少.

指针的几种形式

#include <stdio.h>
#include <stdlib.h>
// 指针的几种形式
void t1() {
	int n1 = 10;
	int* p1 = &n1;
	int** p2 = &p1;
	printf("%d %d", *p1, **p2); // 10 10
}

void t2() {
	int n1 = 10, n2 = 20, n3 = 30, n4 = 40;
	int* p[4];
	p[0] = &n1;
	p[1] = &n2;
	p[2] = &n3;
	p[3] = &n4;
	printf("%d %d %d %d", **p, p[1][0], *p[2], **(p+3)); // 10 20 30 40
	/*
		解释:
			**p -> p是首地址 -> *p 得到首地址的值, 也就是p[0]的值 -> *p[0] 对 p[0] 的值进行查找值, 结果是n1的值.
			p[1][0] -> p[1] 中存放 n2 的地址 -> n2地址[0] 也就是 地址[相对位移量] 的形式, 结果是 n2 的值
			*p[2] -> p[2] 是 n3 的地址 -> *n3的地址 则找到 n3 的值
			**(p+3) -> p是首地址, 然后+3, 则是p数组中下标为3的地址 -> *一下则是p[3]的值, 也就是n4的地址 -> *n4的地址 则是n4的值
	*/
}

void t3() {
	int myInt[4] = {1, 2, 3, 4};
	int Length = sizeof(myInt) / sizeof(int);
	int(*p)[4] = myInt;
	for (int i = 0; i < Length; i++) {
		printf("\n%d", *((*p)+i)); // 1 2 3 4
		printf("\n%d", (*p)[i]); // 1 2 3 4
	}
}

int* t4() {
	static int n3 = 10;
	return &n3; // 注意, 这里必须返回 static 的内容
	// 在 main() 函数中执行  printf("%d", *t4()); 打印 10
}

void t5(void) {
	printf("Hello, World");
	// 在main中 int (*p)(void) = t5; p(); 则打印 Hello, World
}

void main() {
	t1();
}

指针与指针之间四则运算, 只允许减法
# include <stdio.h>

void main(){
    int DATA[2] = {1, 2};
    int* p1 = DATA;
    int* p2 = &DATA[1];
    printf("%p - %p = %p = %p", &p1, &p2, p1 - p2, p2 - p1);
    printf("%p + %p = %p = %p", &p1, &p2, p1 + p2, p2 + p1); // error: invalid operands to binary + (have 'int *' and 'int *')
    getchar();
}

二维数组指针问题
# include <stdio.h>

void main(){
    int a[3][4] = {
        {1, 2, 3},
        {4, 5, 6},
        {7, 8, 9}
    }, *p1 = *(a[1]+1), *p2 = *(&a[1][1]), *p3 = ((*(a+1))[1]), *p4 = *(a+0);

    printf("%d %d %d %d", p1, p2, p3, p4);
    // p4 选择了 二维数组的第一行
    getchar();
}

避免与指针操作混淆:

# include <stdio.h>

void main(){
    int a[2][2] = {
        {1, 2},
        {3, 4}
    };
    int *p = a;
    printf("Arr: %p + 1 = %p", a, a + 1); // 加了 2 个 int 单位
    printf("\np: %p + 1 = %p", p, p + 1); // 加了 1 个 int 单位, 指针并不知道是数组还是值
    getchar();
}

字符串数组问题

# include <stdio.h>

void main(){
    char S[6] = {'A', 'B', 'C', 'D', 'E'}; // 不会溢出, 因为数组一旦被赋值, 多余的位变0
    printf("%s", S);
    
    getchar();
    getchar();
}
# include <stdio.h>

void main(){
    char * S = {'0'}; // 语法错误, 指针不允许直接赋值数组
    printf("%s", S);
    
    getchar();
    getchar();
}
二维数组的本质

image-20230319161508010

二维数组用函数接收
# include <stdio.h>
# include <math.h>
# define N 4

int fun(int p[][N]){ // 这种写法也可以, 最后一维必须有值
  return 1;
}

fun2(int *p[N]){ // 这种写法也可以, 默认返回int
  return 2;
}


void main(){
  int b[N][N], x;
  int a = fun(b);
  fun2(b);
  
  getchar();
  getchar();
}
字符串在内存中存放的值

image-20230320113244594

函数原型声明

image-20230319165328506

结构体未初始化全面

# include <stdio.h>

struct Person {
    char name[20];
    int age;
} p1 = {"ZhangSan"};

void main(){
    

    printf("%d", p1.age); // 默认是0
    getchar();
    getchar();
}

scanf & printf 问题

不可以使用 scanf 给 char * 赋值

在接收键盘字符时, 我们只能给char Str[值];数组形式赋值, 不可以给char * Str赋值, 因为指针是两层的, 永远指向一个地址.

image-20230101093137821

注意, 图中的[30]不可以省略为[], 想要省略必须在一行语句中初始化该变量才行, 例如:

int test[] = {1, 2, 3};
scanf %s吃scanf中的字符问题

image-20230319160720398

让%s停止的只有 \n \t 等. B选项想完成,分割的目的要用 %2s, 限制一下字符串的长度.

scanf要求数字长度

image-20230324073335895

答案: B

scanf %c吃\n问题
# include <stdio.h>
# include <math.h>
void main(){
    // 测试1: %d 和 %c
    // 要求: a存入30, c存入字符b
    // int a; char c;
    // scanf("%d%c", &a, &c); // %c当遇到<回车>时, 会将\n吃入 这里只能输入 30b
    // scanf("%c%d", &c, &a); // %c只吃一个字符, 所以可以输入b30, 而且 %d 不会吃入 \n 所以还可以写入 b<回车>30
    // printf("%d %c", a, c);

    // 测试2: %d 和 %lf
    // 要求: a存入30, b存入30
    // int a; double b;
    // scanf("%d%lf", &a, &b); // 数字遇到数字, 只能通过 30<回车>30 来进行读入
    // printf("%d %f", a, b);

    // 测试3: %d 和 %s 
    // 要求: 存入123 和 abc
    int a; char b[20];
    scanf("%d%s", &a, b); // %s 不吃\n, 所以这里可以写入123<回车>abc 或 123abc
    printf("%d %s", a, b);
    getchar();
    getchar();
}

printf 左侧右侧补空格问题 (百分号是左撇子)

image-20230324072602383

数组指针真实案例
# include <stdio.h>

void main(){
    // 指针数组理解
    int a = 10;
    int b = 20;
    int *ptr[2];
    ptr[0] = &a;
    ptr[1] = &b;
    *ptr[0] = 100;
    *ptr[1] = 200;
    printf("%d %d\n", a, b);
    /*
        结果: 100 200
        内存布局
            ptr
               0x00 指针1 -> a地址
               0x00 指针2 -> b地址
    */

   // 数组指针理解
    int OneArr[5] = {1, 2, 3, 4, 5};
    int (*p1)[5] = &OneArr; // 不要再指向首地址了, 指向整个数组的地址.
    for(int i = 0; i < 5; i ++){
        printf("%d ", *(*p1 + i));
    }
    printf("\n");
    /*
        结果: 1 2 3 4 5
        内存布局:
            p1 是一个指针, 指向了包含五个元素的数组
                *p1 : 找到了这个数组, 数组的首地址找到了
                (*p1)[i] : 数组首地址[下标] 访问到了指定元素
                *(*p1) : 找到了这个的首地址, 继续*, 则找到了首地址的值
                *(*p1 + i) : *(首地址 + i)
    */

   // 二维数组指针理解
    int TwoArr[2][3] = {
        {1, 2, 3},
        {4, 5, 6}
    };

    int (*p2)[3] = TwoArr; // 直接指向了数组第一行

    for(int i = 0; i < 2; i++){
        for(int j = 0; j < 3; j ++){
            printf("%d ", (*p2)[j]);
        }
        printf("\n");
    }

    /*
        结果:
            1 2 3
            4 5 6
        内存布局:
            p2 是一个指针, 指向了一个数组的第一行.
                *p2 : 找到了这个数组的第1行第1个数的地址
                **p2 : 找到了这个数组的第1行第1个数的值
                (*p2)[j] : 找到了第1行, 通过选择, 选择到了第1行第j列
                *(p2 + i) : 找到了这个数组第 i 行的地址第1个数的地址, 为什么能选择行?因为有定义[3], 加一次则加3*i, 自然选到第二行
                *(*(p2+i) + j) : 找到了这个数组第 i 行的地址第j个数的值
    */
    getchar();
}

类似数组指针的题目

image-20230328123913937

正确答案是C, 原理与数组指针的本质特别相似.

易错点

image-20230405214753525

二维数组, +n等于+n列, 例如 a+1, 则选到了第二列. 但是一维数组+n等于往后+n.

++ 本质
ax = 10;
ax = ax ++;


MOV AX, 10
PUSH AX
INC AX
POP AX

// 看似是 b = a++; 是先把 a 的内容给b
// 其实是 先把 a 入栈, 然后a自增, 然后再出栈给 b
    
// ++a 正常理解即可
    
; 升级版本
void main(){
    int a = 1;
    int b = 1;
    a = b++ + a ++; // 结果2, 自增仍然失效. 四则中看见 a = a++类型, 不要想着a++自增.
    printf("%d", a);
    getchar();
    getchar();
}
++与三元混淆题目

image-20230328125821265

看似是一条语句, 实际上是三条语句.

程序设计题

// 编程序:在主函数中输入 10 个等长的字符串,子函数对它们排序,最后在主函数中输出排好序的字符串。
// 自己编写 strcmp 函数, 用 mystrcmp
# include <stdio.h>
# include <string.h>
# define N 3

void printArr(char Strs[3][5]){
    for(int i = 0; i < N; i ++){
        printf("%s, ", Strs[i]);
    }
}

int myStrcmp(char * s1, char * s2){
    while(*s1++ == *s2++);
    return *s1 == '\0' ? 0 : (*s1 > *s2 ? 1 : -1);
}

void main(){

    char Strs[3][5]; // 字符串长度是4
    
    for(int i = 0; i < N; i ++){ // 得到所有字符串
        printf("请输入第 %d 个字符串 (长度是4): ", i + 1);
        scanf("%s", Strs[i]);
    }

    for(int i = 0; i < N - 1; i++){
        for(int j = 0; j < N - 1 - i; j++){
            if(myStrcmp(Strs[j], Strs[j + 1]) > 0){
                for(int k = 0; k < 5; k++){
                    int c1 = Strs[j][k];
                    Strs[j][k] = Strs[j + 1][k];
                    Strs[j + 1][k] = c1;
                }
            }
        }
    }

    printArr(Strs);

    getchar();
    getchar();
}

# include <stdio.h>
# include <math.h>

// 最大公约数, 最小公倍数
void fun(int MAX, int MIN){
    int temp, x; // temp: 临时变量 x: 最小公倍数
    // 最大公约数, 最小公倍数模板
    /*
        MAX MIN
        24  15  -> 24%15=9
        15  9   -> 15%9=6
        9   6   -> 9%6=3
        6   3   -> 6%3=0
        3   0   -> 最大公约数是3

        最小公倍数公式: MAX*MIN / 他俩的最大公约数
    */
    if(MAX < MIN){ // 把最大的数给 MAX
        temp = MAX;
        MAX = MIN;
        MIN = temp;
    }
    x = MAX * MIN;
    while(MIN > 0){
        temp = MAX % MIN;
        MAX = MIN;
        MIN = temp; // 最大公约数算法
    }
    x /= MAX; // 最小公倍数
    printf("最大公约数: %d, 最小公倍数: %d", MAX, x);
}

void main() {
	/* 99乘法表 */
	/*
		for (int i = 1; i <= 9; i ++) {
			for (int j = 1; j <= i; j ++) {
				printf("%d * %d = %d ", j, i, i * j);
			}
			printf("\n");
		}
	*/
	
	/*金字塔*/
	// 金字塔1
	/*
		for (int i = 1; i <= 5; i++) {
			for (int j = 1; j <= i; j ++) {
				printf("*");
			}
			printf("\n");
		}
	*/
	// 金字塔2
	/*
		for (int i = 1; i <= 6; i++) {
			// 打印空格
			for (int j = 1; j <= 6 - i; j ++) {
				printf(" ");
			}
			// 打印星号
			for (int k = 1; k <= 2 * i - 1; k ++) {
				printf("*");
			}
			printf("\n");
		}
	*/

	// 金字塔3
	/*
		for (int i = 1; i <= 9; i ++) {
			// 打印空格
			for (int j = 1; j <= 9 - i; j ++) {
				printf(" ");
			}
			for (int k = 1; k <= 2 * i - 1; k ++) {
				printf("*");
			}
			printf("\n");
		}
	*/

	// 空心菱形
	/*for (int i = 1; i <= 5; i ++) {
		for (int j = 1; j <= 5 - i;j++) {
			printf(" ");
		}
		for (int k = 1; k <= 2 * i - 1;k ++) {
			if (k == 1 || k == 2 * i - 1) {
				printf("*");
			}
			else {
				printf(" ");
			}
		}
		printf("\n");
	}
	for (int i = 4; i >= 1; i--) {
		for (int k = 1; k <= 5 - i; k ++) {
			printf(" ");
		}
		for (int j = 1; j <= 2 * i - 1; j ++) {
			if (j == 1 || j == 2 * i - 1) {
				printf("*");
			}
			else {
				printf(" ");
			}
		}
		printf("\n");
	}*/
    
    
    
    // 斐波那契数
    /* 递归函数
        int fbn(int num) {
            if (num == 1 || num == 2) {
                return 1;
            }
            else {
                return fbn(num-1) + fbn(num-2);
            }
        }
    */
    /* for 循环完成
    	int f1 = 1, f2 = 1, f;
        for (int i = 3; i <= 7; i++) {
            f = f1 + f2;
            f1 = f2;
            f2 = f;
        }
        printf("%d, %d", f, fbn(7));
    */
    
    // 有一堆桃子,猴子第一天吃了其中的一半,并再多吃了一个!以后每天猴子都吃
	// 其中的一半,然后再多吃一个。当到第十天时,想再吃时(还没吃),发现只有
	// 1个桃子了。问题:最初共多少个桃子?
    /*
    	int taozi(int day) {
            if (day == 10) {
                return 1;
            }
            else {
                return (taozi(day + 1) + 1)*2;
            }
        }
    */
    
    // 判断素数 (素数是只能被1以及本身整除的数)
    /*int isprime(int x) {
        for (int i = 2; i < x; i++) {
            if (x % i == 0) {
                // 不是素数
                return 0;
            }
        }
        return 1; // 是素数
    }*/
    
    # include <stdio.h>

    // 用递归的方法将一个整数n转换成字符串, 例如: 输入1234, 应输出字符串 "1234". n的位数不确定, 可以是任意位数的整数.
    void Converter(int nums) {
        int n = nums; // 除 10 判断上面是否还有内容
        if ((n = n / 10) != 0) Converter(n);
        putchar(nums % 10 + '0'); // 余 10 得到最后一位
    }

    void main() {
        int nums;

        printf("请输入数字: ");
        scanf("%d", &nums);

        Converter(nums);
    }
    
}
字符串的四种操作
# include <stdio.h>

void main(){
    // 串连接
    // 数组
    // char s1[30] = "Hello", s2[30] = "World";
    // int i = 0, j = 0;
    // while(s1[i]) i++; // i到 \0 位置
    // while(s1[i++] = s2[j++]);
    // printf("%s", s1);
    // 指针
    // char s1[30] = "Hello", s2[30] = "World";
    // char *p = s1, *q = s2;
    // while(*p) p++; // i到 \0 位置
    // while(*p++ = *q++);
    // printf("%s", s1);

    // 串求长
    // 数组
    // char s1[] = "HelloWorld";
    // int i = 0;
    // while(s1[i]) i++;
    // printf("%d", i);
    // 指针
    // char s1[] = "HelloWorld";
    // char *p = s1;
    // while(*p++);
    // printf("%d", p-1-s1);

    // 串拷贝
    // char s1[30] = "HelloHacker", s2[30] = "World";
    // int i = 0, j = 0;
    // while(s1[i++] = s2[j++]);
    // printf("%s", s1);

    // 串删除某一字符串
    char s1[30] = "HelloHacker", s = 'l', *q = s1, *p;
    while(*q){
        if(*q == s){
            p = q;
            while(*p){
                *p = *(p+1);
                p++;
            }
            *p = '\0';
            continue;
        }
        q++;
    }
    printf("%s", s1);

    getchar();
}

ABCD 变为 BCDA
# include <stdio.h>
// 字符串逆序
void main(){
    char ch[20] = "ABCDEF", *p1 = ch, *p2 = ch, c;
    while(*p2++ != '\0');
    p2 -= 2;
    while(p2 > p1){
        c = *p2;
        *p2 = *p1;
        *p1 = c;
        p2--;
        p1++;
    }
    printf("%s", ch);
    getchar();
}
找最大值
# include "stdio.h"

int main(){
  int a = 10, b = 20, c = 50;
  int max = 0;
  // if 比较法
  // if(a > b){
  //   max = a;
  // }else{
  //   max = b;
  // }
  // if(max < c){
  //   max = c;
  // }
  
  // 三元运算符比较法
  int data = a > b ? (b > c ? b : c) : (b > c ? b : c) ;

  printf("%d", data);

  getchar();
  getchar();
  getchar();
  getchar();
  return 0;
}

公式题
# include "stdio.h"
# include "math.h"

int main(){
  int a, b, c;
  double Gen, x1, x2;
  scanf("%d%d%d", &a, &b, &c);
  if(a == 0){
    printf("a不能是0!");
    return 0;
  }
  Gen = sqrt(b * b - 4 * a * c);
  if(Gen >= 0){
    x1 = (-b + Gen) / (2 * a);
    x2 = (-b - Gen) / (2 * a);
    printf("方程的两个根分别为: %f %f", x1, x2);
  }else{
    printf("方程无根!");
  }
  getchar();
  getchar();
  getchar();
  getchar();
  return 0;
}

分子分母题

image-20230324170621976

以后初始化用do{}while(); 不用图中的案例. 会少加一位.

结构体地址加箭头的写法 (用指针也可以实现)

image-20230318230027267

进制转换 (包括微机原理)
# include <stdio.h>
# include <math.h>
# define N 20

int myZhuanHuan(int Num, int Now, int Dist){
    if(Now == 10 && Dist != 10){
        // 顺进制: 对目标进制取余 余数倒排
        int Result[N], i = 0, j = 0;
        int NumRes = 0;
        while(Num > 0){
            Result[i++] = Num % Dist;
            Num /= Dist;
        }
        for(j = i-1; j >= 0; j--){
            NumRes = NumRes * Now + Result[j];
        }
        return NumRes;
    }else if(Now != 10 && Dist == 10){
        // 逆进制: 余目标进制取位 乘当前进制的N次方 相乘后相加在一起
        int Result = 0;
        int Index = 0;
        while(Num > 0){
            int NowDist = 1;
            for(int i = 0; i < Index; i++){
                NowDist = NowDist * Now;
            }
            Result += (Num % Dist) * NowDist;
            Num /= Dist;
            Index ++;
        }
        return Result;
    }else{
        return myZhuanHuan(myZhuanHuan(Num, Now, 10), 10, Dist);
    }
}

void main(){
    // 题目1: 要求将八进制521转化为十进制数
    /*
        思路: C语言默认为10进制为1组, 所以
            "10进制" -> "其他进制" : 除 "其他进制" 取余法
            "其他进制" -> "10进制" : 位置加权法 (加权的是其他进制)
        
        微机原理中: 默认16进制为一组, 所以
            "16进制" -> "其他进制" : 除 "其他进制" 取余法
            "其他进制" -> "16进制" : 位置加权法 (加权的是其他进制)

        总结: 顺进制 -> 对目标进制取余 余数倒排
             逆进制 -> 对目标进制取余 乘当前进制的N次方 相加在一起
    */
    // int myOct = 521;
    // int myResult = 0;
    // int myIndex = 0;
    // while(myOct > 0){
    //     int Temp = myOct % 10; // 目的进制取位
    //     int Temp2 = 1;
    //     for(int i = 0; i < myIndex; i++){
    //         Temp2 *= 8; // 乘当前进制权
    //     }
    //     myResult += Temp * Temp2;
    //     myOct /= 10;
    //     myIndex ++;
    // }
    // printf("%d", myResult);

    printf("%d", myZhuanHuan(32, 8, 16));

    getchar();
    getchar();
}

凯撒密码

image-20230327153613803

A变成Z, B变成Y的算法

image-20230403155258523

后面使用了未定义的值, 这种情况while中必然有赋值操作!!!

斐波那契数
# include <stdio.h>
# include <math.h>

void main(){
  // 斐波那契数列累加
  int f1 = 1, f2 = 1, f, i, sum = 0;
  sum += f1 + f2;
  for(i = 3; i <= 20; i++){
    f = f1 + f2;
    sum += f;
    f1 = f2;
    f2 = f;
    
  }

  printf("%d", sum);

  getchar();
  getchar();
}
接收键盘字符骚操作
getchar() 循环 (因为scanf不会接收空格)
# include <stdio.h>
void main(){
    char myStrs[30];
    int i = 0;
    while((myStrs[i] = getchar()) != '\n'){ // \n的时候停止
        // 判断逻辑...运行逻辑...
    }
    getchar();
}
scanf() 循环 (因为getchar接收的都是ASCII码)
# include <stdio.h>
# include <math.h>


void main(){
  int num;
  scanf("%d", &num);
  while(num >= 1 && num <= 13){ // 何时退出
    // 判断逻辑...
    scanf("%d", &num);
  }

  getchar();
  getchar();
}
  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值