C语言三位数倒序输出(两种方法)
1. 数学分解法(推荐三位数场景)
原理:分离百位/十位/个位后重组
#include <stdio.h>
int main() {int num, reverse;printf("输入三位数: ");scanf("%d", &num);if (num >= 100 && num <= 999) { int a = num / 100; // 百位int b = num / 10 % 10; // 十位int c = num % 10; // 个位reverse = c*100 + b*10 + a; // 重组printf("倒序: %d\n", reverse);} else {printf("输入非三位数!\n");}return 0;
}
注意:仅适用100-999的整数,输入需验证范围
2. 循环逆序法(通用任意位数)
原理:循环取余动态构建逆序数
#include <stdio.h>
int main() {int num, reverse = 0;printf("输入整数: ");scanf("%d", &num);while (num != 0) {int digit = num % 10; // 取末位reverse = reverse*10 + digit; // 构建逆序num /= 10; // 移除末位}printf("倒序: %d\n", reverse);return 0;
}
注意:
- 负数需先取绝对值再处理
- 末尾0会丢失(如120→21)
🔧 二、EXT4日志解析(纯代码实现)
关键数据结构
// 日志块公共头
struct journal_header_s {__be32 h_magic; // 魔数0xC03B3998__be32 h_blocktype; // 块类型标识__be32 h_sequence; // 事务序列号
};// 描述符块(可变长度)
typedef struct {journal_header_s base_header;journal_block_tag_t tags[]; // 柔性数组存储块标签
} journal_descriptor_header_t;
重点:描述符块长度不固定,需动态计算标签数量
解析流程
- 定位日志区:通过超级块获取
.journal
物理位置 - 事务重放:
void parse_descriptor_block(int dev_fd, uint32_t block_size) {char *block_buf = malloc(block_size);read(dev_fd, block_buf, block_size);journal_descriptor_header_t *desc = (journal_descriptor_header_t*)block_buf;// 计算最大标签数 = (块大小 - 头部大小 - 校验和)/标签大小size_t max_tags = (block_size - sizeof(base_header) - 4) / sizeof(journal_block_tag_t);for (int i=0; i<max_tags; i++) {if (desc->tags[i].t_blocknr == 0) break; // 遇空标签终止recover_block(dev_fd, desc->tags[i].t_blocknr); // 恢复数据块}free(block_buf);
}
技术难点:
- 字节序转换(磁盘数据为大端序)
- 循环队列处理转义块(
JBD2_FLAG_ESCAPE
)
⚙️ 三、队列实现(嵌入式场景)
1. 数组实现循环队列
typedef struct {int *data; // 存储数组int head; // 队首下标int tail; // 队尾下标int capacity; // 队列容量
} CircularQueue;void enqueue(CircularQueue *q, int item) {if ((q->tail+1) % q->capacity == q->head) return; // 队满q->data[q->tail] = item;q->tail = (q->tail+1) % q->capacity; // 循环移动
}int dequeue(CircularQueue *q) {if (q->head == q->tail) return -1; // 队空int item = q->data[q->head];q->head = (q->head+1) % q->capacity;return item;
}
优势:内存连续,访问高效;缺点:容量固定
2. 链表实现动态队列
typedef struct Node {int data;struct Node *next;
} QueueNode;typedef struct {QueueNode *front;QueueNode *rear;
} LinkedQueue;void enqueue(LinkedQueue *q, int item) {QueueNode *node = malloc(sizeof(QueueNode));node->data = item;node->next = NULL;if (q->rear == NULL) { // 空队列q->front = q->rear = node;} else {q->rear->next = node;q->rear = node;}
}int dequeue(LinkedQueue *q) {if (q->front == NULL) return -1; // 队空QueueNode *temp = q->front;int item = temp->data;q->front = q->front->next;if (q->front == NULL) q->rear = NULL; // 队列置空free(temp);return item;
}
适用场景:需动态扩容的场景(如任务调度)
💡 综合复习建议
- 重点题型:
- 数字倒序:掌握数学分解与循环法的适用场景
- EXT4日志:理解描述符块动态解析流程
- 队列编码:能手写循环队列/链表队列的核心操作
- 高频考点:
- 循环队列的队空/队满判断条件
- EXT4日志的事务原子性保障机制
- 倒序算法中的前导零处理
- 实战练习:
// 综合题:用队列实现数字逐位倒序
void reverse_via_queue(int num) {LinkedQueue q;init(&q);while (num) {enqueue(&q, num % 10); // 按位入队num /= 10;}while (!empty(&q)) {printf("%d", dequeue(&q)); // 出队即倒序}
}
【C语言】零基础到项目实战
【C语言/C++】零基础到项目实战
初学者营地:1021486511