刚刚看到 @wood-mirror 的 从0开始记笔记,刚好最近我也有在刷 LeetCode,想起一点点印象深刻的小小经历,记下来应该也挺有意思的。
大一大二的时候年少轻狂,以为某些高级语言就是一切,对C语言也是没有多上心,以至于现在在写一些很简单的东西,在需要保证代码质量的时候,要纠结许久才能下决定。所以我也是尝试选择 C 的方式来做题目,也算是强化一下基本功吧 ?
用 C 语言写代码有个好,通过它可以让你弄清楚,计算机底层可以给你什么基本能力,什么能力是需要通过这些基本的东西通过封装的方式实现的。
然后做题的时候常常就遇到一些数组和字符串(也就是 char 数组)操作的问题,学计算机导论或者组成原理的时候我们知道,电脑在最底层能给我们的其实只是通过地址访问内存的数据,从内存里读取机器指令一步步执行的能力,C语言算是一个封装程度比较低的语言,所以你可以在其中看到很多机器的影子。
C语言的数组,粗略来说,也就相当于,在内存里面开一块地址连续的空间,然后用变量保存它的首地址。至于它有多长,当前到了第几个元素,怎么像 Python 里面的列表一样 append ,需要自己再通过别的方式去实现它。
然后我在做 integer to roman 那道题,结果需要一个字符串,那就先找一块空间给这个字符串,然后设置个标记保存一下最后一个元素的位置:
char* result = (char *)malloc(sizeof(char) * 30);
int p = 0;
然后往这块内存塞字符的时候,最开始是想着:
result[p] = 'I';
p++;
写着写着,看着面条一样的代码,一个操作要两行代码来做,还反反复复,也是挺难受的,看着重复的代码,脑洞打开,好像?可以直接把 p++
换成 result[p++]
?++
运算符放在变量后面,变量自增,但是返回原来的值。
于是插入字符的代码变成了:
result[p++] = 'I';
最后再来个
result[p++] = '\0';
结束这个字符串。
代码变得舒服了不少,好像越来越喜欢 C 语言了(逃
附上好不容易 AC 的代码:
// num to char
char table(int num) {
switch (num) {
case 1000:
return 'M';
case 500:
return 'D';
case 100:
return 'C';
case 50:
return 'L';
case 10:
return 'X';
case 5:
return 'V';
case 1:
return 'I';
}
return ' ';
}
char* intToRoman(int num) {
// result str
char* result = (char *)malloc(sizeof(char) * 30);
int p = 0;
int list[] = {1000, 500, 100, 50, 10, 5, 1};
for (int i = 0; i < 7; i++) {
while (num >= list[i]) {
result[p++] = table(list[i]);
num -= list[i];
}
if (i == 0 || i == 2 || i == 4) {
if (num > 9 * list[i + 2] - 1) {
result[p++] = table(list[i + 2]);
result[p++] = table(list[i]);
num -= 9 * list[i + 2];
}
}
if (i == 1 || i == 3 || i == 5) {
if (num > 4 * list[i + 1] - 1) {
result[p++] = table(list[i + 1]);
result[p++] = table(list[i]);
num -= 4 * list[i + 1];
}
}
}
result[p++] = '\0';
return result;
}