C语言基础非常重要,为什么字符串输出不正常呢?
发表于: 2019-03-09 21:48:00 | 已被阅读: 84 | 分类于: C语言
最近公司部门里来了两个刚毕业的新同事小明和小华,小伙子头脑很灵活,交待给任务时,一般都能有不错的想法。但是基本功略差,写出的C语言代码很难看。中午吃饭时,正巧跟他们碰到一起,我就提到嵌入式程序开发要注重基础,没想到被他俩鄙视了,哈哈。他们认为研究基础的都是码农,程序员要注重的是思维和架构设计。

来看看这个问题
可是,作为前线程序员,就算有好想法好设计,也得有相匹配的代码能力把它们实现出来吧。正好,今天群里有小伙伴(@别挤我)提了个问题,请看下面的C语言代码:
#include <stdio.h>
void del_space(char* str)
{
int i, j = 0;
for(i=0; str[i]!='\0'; i++){
if(' '!=str[i])
str[j++] = str[i];
}
}
int main()
{
char str[] = "hello Embed Time!";
del_space(str);
printf("%s\n", str);
return 0;
}

这段C语言代码比较简单,应该能明白小伙伴的意图是定义一个 del_space() 函数,用于删除字符串中的空格。在 main() 函数中传递给 del_space() 函数的是“hello Embed Time!”,小伙伴的
实践是检验真理的唯一标准,我们编译并执行这段C语言代码,如下:
# gcc t.c
# ./a.out
helloEmbedTime!e!

这其实是一道基础题
这道题比较典型,并没有涉及到花里胡哨的技巧,明显是一道基础题。于是我把这个问题发给了小明和小华,没有别的意思,纯粹是觉得题目比较有意思。

#include <string.h>
void del_space(char* str)
{
int i, j = 0;
char a[30];
memset(a, 0, 30);
for(i=0; str[i]!='\0'; i++){
if(' '!=str[i])
a[j++] = str[i];
}
strcpy(str, a);
}

小伙伴的C语言程序,没有按照预期输出的真正原因
其实,只要有 C语言中字符串默认“截止条件”的概念,小伙伴遇到的问题就清晰了。请看下面这几个C语言中常用的量:
int a = 8;
char b = '8';
char c[] = "8";
从人类语言来看,变量 a, b, c 都表示 8 这个符号,但是在 C语言中它们是有差异的:a 表示整数 8,b 表示字符 8,c则表示字符串 8。相信即使是 C语言初学者也明白 8 和 '8' 的区别,那字符串 “8”和字符 '8' 的区别在哪里呢?
从字面意思看,字符

#include <stdio.h>
#include <string.h>
int main()
{
char a[6] = "123456";
printf("%lu\n", strlen(a));
a[3] = '\0';
printf("%lu\n", strlen(a));
return 0;
}

# gcc t.c
# ./a.out
6
3
现在再来看小伙伴遇到的问题,就一切清楚了,他的C语言程序未能按照预期输出的原因在于: del_space() 函数中的目标 str 没有指定结束字符 '\0',将之加上就一切正常了。请看:
void del_space(char* str)
{
int i, j = 0;
for(i=0; str[i]!='\0'; i++){
if(' '!=str[i])
str[j++] = str[i];
}
str[j] = '\0';
}

小结
从这个案例能够看出,至少在嵌入式C语言程序开发中,基础真的很重要。基础不扎实的话,遇到问题就很难写出消耗资源少,运行效率高的程序。你看,小伙伴遇到的问题,明明只需要多写一个字节的赋值语句就能解决,小明没能发现这一点,他新写的函数运行时会使用更大的内存,消耗更多的时间,而且函数的通用性也不够好。