第一句子网 - 唯美句子、句子迷、好句子大全
第一句子网 > 【C面试】一道简单的C语言面试题的思考——打印星阵

【C面试】一道简单的C语言面试题的思考——打印星阵

时间:2021-01-06 20:42:32

相关推荐

【C面试】一道简单的C语言面试题的思考——打印星阵

在毕业刚在第一家的公司的时候,项目经理有一次跟我们吐槽说面试一个水客(就是简历上精通C/C++)。聊了几句话,发现那个面试的人水分很大,现场出了一道笔试题。

题目,用c语言打印一个等腰直角三角形效果,三角形腰边长度为四个星星。效果如下

**********

当然临场发挥给出来的题目,实际上就是在纸上画几个星星,让面试者笔试,不会有“等腰直角三角形”这种描述,这题目是我脑(yi)补(yin)出来的。

面试者拿过纸来大手一挥,写出如下答案:

printf("*\n"); printf("**\n"); printf("***\n"); printf("****\n");

“很好,还有别的实现方法吗”经理夸奖道

“没有了”

“那好,写个1000行的”

“……”,面试者哑口无言,心中万马奔腾。

面试结果可想而知。

后来开会跟我们组员说个这次面试顺便吐槽我们组开发编码考虑不周全,第一反应该有两种方法,一种两个循环,一种一个循环。

时间过得好快,转眼间五年过去了,那会还没完全毕业,只是大四下半年在那家公司实习(当然毕业后还是一直待在哪儿),因为这个面试题太经典了,印象忒别深刻,就是不同水平的开发者都能做出这个面试题。今天就趁着深圳大雨,宅在家整理一下实现方案。 方法一、单刀直入,直接printf

printf("*\n");printf("**\n");printf("***\n");printf("****\n");

方法二、printf双循环 外层循环负责换行,内层循环负责打印星星

printf("print by function %s\n", __func__);for (int i = 0; i < num; i++) {for (int j = 0; j < i + 1; j++) {printf("*");}printf("\n");}

方法三、数组赋值 定义一个空字符串,然后在循环中递增赋值星星

char *temp = new char[num + 1];memset(temp, 0, num + 1);for (int i = 0; i < num; i++) {*(temp + i) = '*';printf("%s\n", temp);}delete[] temp;temp = NULL;

方法四、字符串拼接 定义一个空字符串,然后在循环中递增拼接星星

char *temp = new char[num + 1];memset(temp, 0, num + 1);for (int i = 0; i < num; i++) {printf("%s\n", strcat(temp, "*"));}delete[] temp;temp = NULL;

方法五、snprintf控制打印输出

char *temp = new char[num + 1];memset(temp, 0, num + 1);char *stars = new char[num + 1];memset(stars, '*', num);stars[num] = '\0';for (int i = 0; i < num; i++) {/*** for snprintf you can consider that last index (n - 1) alway set to '\0'.* NOTE: actually it would be setted to '\0' only when source length > n; */snprintf(temp, i + 2, "%s", stars); //printf("%s\n", temp);}delete[] temp;temp = NULL;delete[] stars;stars = NULL;

方法六、memset初始化函数

char *temp = new char[num + 1];memset(temp, 0, num + 1);for (int i = 0; i < num; i++) {memset(temp, '*', i + 1);printf("%s\n", temp);}delete[] temp;temp = NULL;

方法七、memcpy内存拷贝

char *stars = new char[num + 1];memset(stars, '*', num);stars[num] = '\0';char *temp = new char[num + 1];memset(temp, 0, num + 1);for (int i = 0; i < num; i++) {memcpy(temp, stars, i + 1);printf("%s\n", temp);}delete[] stars;stars = NULL;delete[] temp;temp = NULL;

方法八、strncpy字符串拷贝

printf("printf by function %s\n", __func__);char *stars = new char[num + 1];memset(stars, '*', num);stars[num] = '\0';char *temp = new char[num + 1];memset(temp, 0, num + 1);for (int i = 0; i < num; i++) {strncpy(temp, stars, i + 1);printf("%s\n", temp);}delete[] stars;stars = NULL;delete[] temp;temp = NULL;

方法九、printf函数格式化打印

char *temp = new char[num + 1];memset(temp, '*', num + 1);*(temp + num) = '\0';for (int i = 0; i < num; i++) {printf("%.*s\n", i + 1, temp);}delete[] temp;temp = NULL;

方法十、等差数列插入换行符

void arithmetic_progression(int num = 4) {printf("printf by function %s\n", __func__);const int A1 = 2;const int d = 1;const int N = A1 * num + num * (num - 1) * d / 2; char *temp = new char[N];memset(temp, '*', N);int An = 0, sum = 0;for (int i = 0; i < num; i++) {An = A1 + i * d; // actually i is (n - 1)sum += An;*(temp + sum - 1) = '\n';}*(temp + N - 1) = '\0'; // prevent new line on the last.printf("%s\n", temp);delete[] temp;temp = NULL;}

完整的代码 stars.cpp

#include <cstdio>#include <cstdlib>#include <cstring>void directly(int notUse = 0) {printf("print by function %s\n", __func__);printf("*\n");printf("**\n");printf("***\n");printf("****\n");}void twofor(int num = 4) {printf("print by function %s\n", __func__);for (int i = 0; i < num; i++) {for (int j = 0; j < i + 1; j++) {printf("*");}printf("\n");}}void char_array(int num = 4) {printf("print by function %s\n", __func__);char *temp = new char[num + 1];memset(temp, 0, num + 1);for (int i = 0; i < num; i++) {*(temp + i) = '*';printf("%s\n", temp);}delete[] temp;temp = NULL;}void char_strcat(int num = 4) {printf("print by function %s\n", __func__);char *temp = new char[num + 1];memset(temp, 0, num + 1);for (int i = 0; i < num; i++) {printf("%s\n", strcat(temp, "*"));}delete[] temp;temp = NULL;}void char_snprintf(int num = 4) {printf("print by function %s\n", __func__);char *temp = new char[num + 1];memset(temp, 0, num + 1);char *stars = new char[num + 1];memset(stars, '*', num);stars[num] = '\0';for (int i = 0; i < num; i++) {/*** for snprintf you can consider that last index (n - 1) alway set to '\0'.* NOTE: actually it would be setted to '\0' only when source length > n; */snprintf(temp, i + 2, "%s", stars); //printf("%s\n", temp);}delete[] temp;temp = NULL;delete[] stars;stars = NULL;}void char_memset(int num = 4) {printf("print by function %s\n", __func__);char *temp = new char[num + 1];memset(temp, 0, num + 1);for (int i = 0; i < num; i++) {memset(temp, '*', i + 1);printf("%s\n", temp);}delete[] temp;temp = NULL;}void char_memcpy(int num = 4) {printf("printf by function %s\n", __func__);char *stars = new char[num + 1];memset(stars, '*', num);stars[num] = '\0';char *temp = new char[num + 1];memset(temp, 0, num + 1);for (int i = 0; i < num; i++) {memcpy(temp, stars, i + 1);printf("%s\n", temp);}delete[] stars;stars = NULL;delete[] temp;temp = NULL;}void char_strncpy(int num = 4) {printf("printf by function %s\n", __func__);char *stars = new char[num + 1];memset(stars, '*', num);stars[num] = '\0';char *temp = new char[num + 1];memset(temp, 0, num + 1);for (int i = 0; i < num; i++) {strncpy(temp, stars, i + 1);printf("%s\n", temp);}delete[] stars;stars = NULL;delete[] temp;temp = NULL;}void printf_format(int num = 4) {printf("printf by function %s\n", __func__);char *temp = new char[num + 1];memset(temp, '*', num + 1);*(temp + num) = '\0';for (int i = 0; i < num; i++) {printf("%.*s\n", i + 1, temp);}delete[] temp;temp = NULL;}/*** 等差数列* An = A1 + (n - 1) * d;* sum(A) = A1 * n + n * (n - 1) * d / 2;*/void arithmetic_progression(int num = 4) {printf("printf by function %s\n", __func__);const int A1 = 2;const int d = 1;const int N = A1 * num + num * (num - 1) * d / 2; char *temp = new char[N];memset(temp, '*', N);int An = 0, sum = 0;for (int i = 0; i < num; i++) {An = A1 + i * d; // actually i is (n - 1)sum += An;*(temp + sum - 1) = '\n';}*(temp + N - 1) = '\0'; // prevent new line on the last.printf("%s\n", temp);delete[] temp;temp = NULL;}typedef void (*star_printer)(int);int main(int argc, char* argv[]) {star_printer funclist[] = {directly, twofor, char_array, char_strcat,char_snprintf, char_memset, char_memcpy, char_strncpy,printf_format, arithmetic_progression};const int N = sizeof(funclist) / sizeof(*funclist);for (size_t i = 0; i < N; i++) {printf("%lu --> ", i);(*(funclist[i]))(4);}return 0;}

说明: 删除指针通常是定义宏变操作,上面示例中是裸写代码,通常不建议这么做。

释放指针数组的宏操作

#define SAFE_DELETE_ARR(p) {if (NULL != (p)) {delete[](p); (p) = NULL;}}

编译及运行

$ g++ stars.cpp

$ ./a.out

0 --> print by function directly**********1 --> print by function twofor**********2 --> print by function char_array**********3 --> print by function char_strcat**********4 --> print by function char_snprintf**********5 --> print by function char_memset**********6 --> printf by function char_memcpy**********7 --> printf by function char_strncpy**********8 --> printf by function printf_format**********9 --> printf by function arithmetic_progression**********

看起来有十种实现方法!而实际上主要实现方法就是四种:直接打印(方法一),双循环控制打印(方法二),单循环赋值打印(方法三到方法八),字符串定点换行(方法十)。至于方法九,虽然可以算独立方法,其实也只不过在语言接口上下功夫罢了,换中语言(java,c#)可能就不能发挥作用了。方法三到方法八都是赋值法,只是在c语言的api上下功夫罢了。

这道面试题之所以经典是因为对于不同水平的面试者能够考察其对C C++理解的深度,对API的掌握情况。

后记,当初我当场想到方法是方法二双循环print和方法六memset,后来问了经理的答案是什么,他出题时用方法八snprintf,用memset写出来的时候他很惊讶,因为他自己也没考虑到有这种方法,当然我也没想到snprintf方法。要答案也是有技巧的,我们当初早就转正了,好奇心驱使下我在开会后把代码撸好QQ给他才问答案的。

说说我的面试吧,经理的技术思维很厉害,当初面试因为技术方面没啥问题,经理突然问我“你觉得测试重要吗,假如神州飞船出现故障会怎样”,我现场拿起笔和纸写一个多项式,指着多项式中指数高的变量“故障分等级,事故后果就多项式的和,神舟飞船这种故障的指数应该大一点”,然后,没然后了,哈哈

========-07-22特别提醒=========

鲁迅小说《孔乙己》中,孔乙己告诉孩子们说,茴香豆有四种写法,即茴、回、囘、囬,还有一种是“口”字里面有个“目”字。本篇博客是本人上周末下大雨时闲时写的总结分享,这里要提醒编程初学者不要过分纠结这种细枝末节的知识,有好多重要的知识架构,计算机原理、网络、设计模式、数据结构才是干货,值得慢慢积累。现在C++最新标准已经到C++了,C++早已在新的开源项目中广泛使用了。C++和C++98某种程度上讲就是两种语言。学习C++不要像清华某唐的教材还在纠结运算符优先级(不确定的直接括号秒杀),

i += ++i;这种牛角尖问题,我曾经自学中也走入这样的误区。特地提醒,不要被误导。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。