PAT B1027. 打印沙漏(20)

本文介绍了一个使用C语言实现的程序,该程序能够接收用户输入的符号数量和指定符号,打印出最大可能的沙漏形状,并输出剩余未使用的符号数量。通过巧妙的循环和条件判断实现了沙漏图案的构建。

本题要求你写个程序把给定的符号打印成沙漏的形状。例如给定17个“*”,要求按下列格式打印

*****
 ***
  *
 ***
*****

所谓“沙漏形状”,是指每行输出奇数个符号;各行符号中心对齐;相邻两行符号数差2;符号数先从大到小顺序递减到1,再从小到大顺序递增;首尾符号数相等。

给定任意N个符号,不一定能正好组成一个沙漏。要求打印出的沙漏能用掉尽可能多的符号。

输入格式:

输入在一行给出1个正整数N(<=1000)和一个符号,中间以空格分隔。

输出格式:

首先打印出由给定符号组成的最大的沙漏形状,最后在一行中输出剩下没用掉的符号数。

输入样例:
19 *
输出样例:

*****
 ***
  *
 ***
*****
2

思路:嵌套for循环比较麻烦,把个数弄清楚就比较easy了

#include<cstdio>
int main(){
    int N;
    char a;
    scanf("%d",&N);
    getchar();
    scanf("%c",&a);
    int k=2;
    int num=0;
    int sum=-1;
    while(sum<=N){
        sum+=k;
        k+=4;
        num++;
    }
    int rem=N-sum+k-4;
    for(int i=num-1;i>0;i--){
        for(int j=0;j<num-i-1;j++){
            printf(" ");
        }
        for(int x=0;x<(2*i-1);x++){
            printf("%c",a);
        }
        printf("\n");
    }
    for(int i=1;i<num-1;i++){
        for(int j=0;j<num-i-2;j++){
            printf(" ");
        }
        for(int y=0;y<(2*i+1);y++){
            printf("%c",a);
        }
        printf("\n");
    }
    printf("%d\n",rem);
    return 0;
} 
你的代码**目标是打印一个菱形或沙漏形状的图案**,但目前存在几个关键问题: --- ### ❌ 问题分析 #### 1. **输入顺序错误** ```c ch = getchar(); scanf("%d", &n); ``` 你先读 `ch`,再读 `n`,但题目输入格式是: ``` N 符号 ``` 例如: ``` 7 * ``` 所以你应该先读整数 `n`,再读字符(包括空格后的符号)。 你现在这样写会导致: - `getchar()` 读的是数字字符的第一个字符(比如 `'7'`),而不是 `*` - 然后 `scanf` 读 `n` 成功,但 `ch` 被赋值为 `'7'` —— 完全错了! ✅ 正确方式:先读 `n` 和 `ch` --- #### 2. **判断奇偶并报错不符合题意** 你写了: ```c if(n%2==0){ printf("必须为奇数!"); } ``` 但这道题中: - `n` 是**可用符号的数量**,不是图形的大小! - 我们要找的是:用最多可能的符号组成沙漏,而不是让用户输入“行数” 而你把 `n` 当成了“最大行星号数”,还要求它是奇数 —— 这是对题目的误解。 --- #### 3. **逻辑完全偏离原题要求** 本题是 PAT 经典题:“打印沙漏”([PAT B1027](https://pintia.cn/problem-sets/994805260223102976/problems/994805294251491328)) > 给定 N 个符号,打印能组成的最大沙漏,并输出剩余符号数。 而你的程序: - 没有计算最多能用多少符号 - 没有输出剩余符号数 - 直接以 `n` 作为顶层星数打印 → 如果 `n=1000`,会尝试打印上千行星号?严重超限! --- ### ✅ 正解思路回顾(正确做法) 我们需要: 1. 输入 `N`(总符号数)和字符 `c` 2. 找最大高度 `h`,使得 `2*h*h - 1 <= N` 3. 打印沙漏(上半 h 行,下半 h-1 行) 4. 输出 `N - (2*h*h - 1)` --- ### ✅ 正确完整代码(修正版) ```c #include <stdio.h> int main() { int N; char c; scanf("%d %c", &N, &c); // 正确读取格式 // 寻找最大 h,满足 2*h*h - 1 <= N int h = 1; while (2 * h * h - 1 <= N) { h++; } h--; // 回退到最大合法值 int used = 2 * h * h - 1; // 实际使用符号数 // 上半部分:从 i = h 到 1,每行星数 = 2*i - 1 for (int i = h; i >= 1; i--) { int spaces = h - i; int stars = 2 * i - 1; for (int j = 0; j < spaces; j++) putchar(' '); for (int j = 0; j < stars; j++) putchar(c); putchar('\n'); } // 下半部分:从 i = 2 到 h for (int i = 2; i <= h; i++) { int spaces = h - i; int stars = 2 * i - 1; for (int j = 0; j < spaces; j++) putchar(' '); for (int j = 0; j < stars; j++) putchar(c); putchar('\n'); } // 输出剩余符号数 printf("%d\n", N - used); return 0; } ``` --- ### 🔍 示例运行 **输入:** ``` 19 * ``` **输出:** ``` ***** *** * *** ***** 2 ``` 完全符合! --- ### 🧠 总结:你原来代码的问题 | 错误 | 说明 | |------|------| | `getchar()` 在 `scanf` 前 | 读错了字符顺序 | | 把 `n` 当成行宽 | 应该是总符号数,需动态计算可用层数 | | 没有处理“尽可能多使用符号” | 缺少核心逻辑 | | 没有输出剩余数量 | 题目明确要求 | ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值