当字符数组遇见memset:赋值时踩上的雷

故事要从一道题说起

输入一个大写字母,输出由A到该字母组成的空心正三角形,其中第一行的A输出在第40列。
输入样例:C
输出样例:
在这里插入图片描述

挺平凡的一道题对吧-/-。
我用最基础的知识写了一段很丑的代码之后,回想起最近学了字符串,于是决定用字符数组写一个更好看的解法。(然后就开始踩雷了

我的思路

利用一个二维字符数组来存储这个三角形。
考虑最极端的情况:如果输入Z,那么我们需要打印26行,并且最后一行有65个字符。于是我们构造一个二维数组 tri[26][66]
为了与数组的下标统一,我们不妨规定A是第0行,B是第1行……并且列也从第0列算起。
通过观察可以发现,第39列(顶点A那列)是空心三角形的对称轴。
tri[i] 存储了第i行的内容,同时该行字母的ASCII码为i+65
并且第i行的字母出现在第39-i列与第39+i列;比较特别的是最后一行,字母出现在第39-i到第39+i列之间。
一切都联系起来了qwq!
如此一来只需将二维字符数组初始化为空格,然后在对应的位置修改就好啦!而初始化数组我们知道可以用memset()搞定。
一通分析猛如虎,也就循环套条件。想到这里,不禁感叹:就这就这?
在这里插入图片描述

打脸了

于是我写出了这样的东西

#include <stdio.h>
#include <string.h>
int main()
{
    int i, j;
	char letter, tri[26][66];
    scanf("%c", &letter);
    for (i=0; i<26; i++)
    {   
        memset(tri[i], ' ', sizeof(tri[i]));
    }
    
	for (i=0; i<=letter-'A'; i++)
	{

		tri[i][39-i] = tri[i][39+i] = i+'A';
        if (i == letter-'A')
        {
            for(j=39-i; j<=39+i; j++) tri[i][j] = letter;
            puts(tri[i]);
        }
        else puts(tri[i]);
    }
    
    return 0;
}

(如果你看出来问题在哪以及结果怎样 我觉得就可以溜了

结果当然不会是像样例的一样啦(手动吡牙
在这里插入图片描述
就这就这就不出来了emmm… 好消息是我的思路基本上正确了;坏消息是出了一些undingable的问题orz
问题出在哪已经在标题明示出来了//先假装不知道
经过我反复的调试,这个二维字符数组就有很大的问题!
不过中间空了一大堆,到底是回车还是多得鸭皮的空格?
将memset()一行的** ‘ ’** 先改成**‘#‘** 再试试:
在这里插入图片描述
瞎瞎,眼睛已经谢了
但是我贫困的脑子已经想不出别的东西了,//于是我去睡了一觉
之后 我的直觉告诉我,这么多的#,或许跟26*66有关!
于是我数了数没数这个,我又定义了个a[2][3],您猜怎么着!还真是=-=
那么到底是什么,让一行的字符数组停不下来硬是把整个二维数组的#都整出来了呢!

原来是你

细细想来,什么东西能标记字符数组的终止呢!\0破案了
如此一想,前面之所以在一行内把所有的#都打印出来,根本原因在于每行用于标记结束的\0没了
\0是怎么没了呢。这时候就发现了——雷藏在memset里面。
字符数组与整型数组不同,打印时依据\0来终止。尽管在一维字符数组中去掉最后的\0时,打印是看不出有什么毛病的(再往下打印就超越数组分到的地址了
但是在二维数组中,问题就清晰地暴露出来了:第0行会从tri[0][0]打印到tri[26][66]共1716个字符,第1行会打印从tri[1][0]到tri[26][66]共1650个字符……原因就在于每行少了\0来控制结束。
基于以上,只需将memset一行修改为

memset(tri[i], ’ ', sizeof(tri[i])-1);

给\0留出一个位置即可。
修改后的结果:在这里插入图片描述

总结

debug一个字符数组有关的问题时,可以往\0上面考虑;
遇到问题别死磕,不如先睡一觉//(逃

近日学业繁忙,写这些杂文的时间真就得挤
数学也太难顶了吧

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值