progress

I'd rather be anything but ordinary

0%

不要在知乎问作业!

前几天在知乎又见到有人问作业题,估计就要期末了,不出意外地大佬们又开始教育小学生了。

原问题如下:

输入一行字符,将该字符串中除了字母t以外的其他小写字母变为大写字母

很简单没什么难度,然而大佬们的答案还是让我自愧不如。
1.先给出一个稍微正常点的。出自后缀自动机·张的答案。

#include <stdio.h>
#include <ctype.h>
char s[100010];
void fuck(int index){
s[index]=='\0' || (s[index] = s[index]=='t'?'t':toupper(s[index]),fuck(index+1),true);
}
int main(void){
scanf("%s",s);
fuck(0);
printf("%s",s);
return 0;
}

我来试图解释下,利用fuck函数递归求解,s[index]=='\0'利用与运算的短路特性达到递归基的效果。后面也很好理解,就是判断s[index]是否为t,除了那个true,似乎true没什么用,我们将true去掉,果然编译失败了。

error: could not convert '(((void)(s[index] = ((((signed char)s[index]) != 116) ? ((char)toupper(((int)s[index]))) : 't'))), fuck((index + 1)))' from 'void' to 'bool'

错误信息提示不能将后面的表达式从void转换为bool,仔细想想这个表达式必须是bool值,因为他在一个逻辑表达式里啊,这里还有个知识点,相信大家学c的时候觉得很简单,不过之后因为用的少而忘掉的逗号表达式,一个表达式a,b,c的值是多少?答案是c。此时这个代码就很清晰了,(s[index] = s[index]=='t'?'t':toupper(s[index]),fuck(index+1),true);这是个逗号表达式,最后的true是为了将表达式变成逻辑表达式。如果将最后的参数改成false结果如何,相信你也知道了。
2.第二个是孙明琦的答案。下面给出的答案略作修改,因为我用本机gcc编译不通过原答案。

#include<ctype.h>
#include<stdio.h>
int main();
void nothing(char c) {}
int self(int c) {return c;}
void doit(char c) {
int (*continuations[2])(int) = {toupper, self};
putchar(continuations[c == 't'](c));
main();
}
int main() {
void (*continuations[2])(char) = {doit, nothing};
char ch;
ch = getchar();
continuations[ch == '\n'](ch);
}

此答案主要运用函数指针,continuations[2]是一个函数指针数组。continuations[0]调用函数doit,函数doit又有个同名的函数指针,当然这不影响使用,不在一个作用域下,putchar(continuations[c == 't'](c))每次调用此语句,决定调用哪个函数。当c==’t’是调用self,其余时候调用函数toupper.
未完待续。