用c/c++进行图形的输出
一.字符串型
【1】实心图形(1-5,12)
1.输入 n 值,输出如图所示矩形
*****
*****
*****
*****
*****
#include <iostream>
using namespace std;
int main() {
int n;
cin>>n;
for(int i=0 ; i<n ; i++) {
for(int j=0 ; j<n ; j++)
cout<<"*";
cout<<endl;
}
return 0;
}
2.输入 n 值,输出如图所示平行四边形
* * * * *
* * * * *
* * * * *
* * * * *
* * * * *
#include <stdio.h>
int main() {
int n;
scanf("%d",&n);
for(int i=0 ; i<n ; i++) {
for(int j=n-i-1; j>0 ; j--)
printf("%2c",'\0');
for(int j=0 ; j<n ; j++)
printf("%-2c",'*');
printf("\n");
}
return 0;
}
3.输入 n 值,输出如图所示高为 n 的等腰三角形
*
* * *
* * * * *
* * * * * * *
* * * * * * * * *
#include <iostream>
using namespace std;
int main() {
int n;
cin>>n;
for(int i=1 ; i<=n ; i++) {
for(int j=0 ; j<n-i ; j++)
printf("%2c",' ');
for(int j=0 ;j<2*i-1 ; j++)
printf("%-2c",'*');
cout<<endl;
}
return 0;
}
4.输入 n 值,输出如图所示高为 n 的倒等腰三角形
* * * * * * * * *
* * * * * * *
* * * * *
* * *
*
#include <iostream>
using namespace std;
int main() {
int n;
cin>>n;
for(int i=n ; i>0 ; i--) {
for(int j=0 ; j<n-i ; j++)
printf("%2c",'\0');
for(int j=0 ;j<2*i-1 ; j++)
printf("%-2c",'*');
cout<<endl;
}
return 0;
}
5.输入 n 值,输出如图所示高和上底均为 n 的等腰梯形
* * * * *
* * * * * * *
* * * * * * * * *
* * * * * * * * * * *
* * * * * * * * * * * * *
#include <iostream>
using namespace std;
int main() {
/*int n;
cin>>n;
for(int i=3; i<=n+2 ; i++) {
for(int j=0 ; j<n-i+2; j++)
cout<<" ";
for(int j=0 ;j<2*i-1 ; j++)
cout<<"* ";
cout<<endl;
}*/ // 错误,第一行*的个数随n的变化而变化会变化,并不是一个常量,不能直接从i=3算起
int n;
cin>>n;
for(int i=1 ; i<=n; i++) {
for(int j=1 ; j<=n-i ; j++)
cout<<" ";
for(int j=1 ; j<=2*i-1+(n-1); j++) {
if(j == 1)
cout<<"*";
else
cout<<" *";
}
cout<<endl;
}
return 0;
}
注:
这种题型最容易只看样例输出图形,如果题目要求n是一个常数可以这样做,否则就极容易出错, 往往会忽略掉随着n变化时图形发生的变化。行与行之间的距离相当与一个空格,故每行*之间的距离是一个空行
12.输入 n 值,输出菱形
*
* * *
* * * * *
* * *
*
#include <iostream>
using namespace std;
int main() {
void f(int n , int i);
int n;
cin>>n;
for(int i=1 ; i<=n ; i++ )
f(n,i);
for(int i=n-1; i>0 ; i-- )
f(n,i);
return 0;
}
void f(int n , int i) {
for(int j=1 ; j<=n-i ; j++)
cout<<" ";
for(int j=1 ; j<=2*i-1 ; j++) {
if(j == 1)
cout<<"*";
else
cout<<" *";
}
cout<<endl;
}
【2】空心图形(6-11,13)[字符串型]
6.输入 n 值,输出如图所示高和上底均为 n 的等腰空心梯形
* * * * * *
* *
* *
* *
* *
* * * * * * * * * * * * * * * *
#include <iostream>
using namespace std;
int main() {
int n;
cin>>n;
for(int i=1; i<=n ; i++) {
for(int j=0; j<n-i; j++)
cout<<" ";
for(int j=1 ;j<=2*i-1+(n-1) ; j++) {
if(i==1 || i==n) {
if(j == 1)
cout<<"*";
else
cout<<" *";
}
else {
if(j==1)
cout<<"* ";
else if(j == 2*i-1+(n-1) )
cout<<"*";
else
cout<<" ";
}
}
cout<<endl;
}
return 0;
}
7.输入 n 值,输出如图所示边长为 n 的空心正六边型
* * * * * *
* *
* *
* *
* *
* *
* *
* *
* *
* *
* * * * * *
#include <iostream>
using namespace std;
int main() {
void f(int n,int i);
int n;
cin>>n;
for(int i=1; i<n; i++)
f(n,i);
f(n,n);
for(int i=n-1; i>0; i--)
f(n,i);
return 0;
}
void f(int n,int i) {
for(int j=0; j<n-i; j++)
cout<<" ";
for(int j=1 ;j<=2*i-1+(n-1) ; j++) {
if(i==1) {
if(j==1)
cout<<"*";
else
cout<<" *";
}
else {
if(j==1 || j==2*i-1+(n-1))
cout<<"*";
else {
if(j<=i || j>i+n-1 )
cout<<" ";
else
cout<<" ";
}
}
}
cout<<endl;
}
return 0;
}
8.输入 n 值,输出X图形
* *
* *
* *
* *
* *
*
* *
* *
* *
* *
* *
#include <iostream>
using namespace std;
int main() {
void f(int n ,int i);
int n;
cin>>n;
for(int i=n ; i>1 ; i--)
f(n,i);
for(int i=1 ; i<=n ; i++)
f(n,i);
return 0;
}
void f(int n ,int i) {
for(int j=1 ; j<=n-i; j++)
cout<<" ";
for(int j=1 ; j<=2*i-1 ; j++) {
if(j == 1 || j ==2*i-1 )
cout<<"*";
else
cout<<" ";
}
cout<<endl;
}
return 0;
}
注:
针对上下对称的图形,一般的做法是将其分成上半部分,中间部分,下半部分。对于上下部分,由于其对称性这样会产生很多重复代码,这个时候可以自定义函数来处理重复代码。对于中间部分,有时可以写在上半部分(下半部分),有时要单独分析,这时一定要看样例分析。
9.输入 n 值,输出Z图形
* * * * *
*
*
*
* * * * *
//数组
#include <iostream>
using namespace std;
int main() {
int n;
cin>>n;
char s[n][2*n-1];
for(int i=0 ; i<n ; i++) {
for(int j=0 ; j<2*n-1 ; j++) {
if(i == 0 || i == n-1) {
if(j%2 == 0) {
s[i][j]='*';
cout<<s[i][j];
}
else {
s[i][j]=' ';
cout<<s[i][j];
}
}
else {
if(j == 2*(n-1-i)) {
s[i][j]='*';
cout<<s[i][j];
}
else {
s[i][j]=' ';
cout<<s[i][j];
}
}
}
cout<<endl;
}
return 0;
}
//非数组
#include <iostream>
using namespace std;
int main() {
int n;
cin>>n;
for(int i=1 ; i<=n ; i++) {
for(int j=1 ; j<=n ; j++) {
if(i == 1 || i == n) {
if(j == 1)
cout<<"*";
else
cout<<" *";
}
else {
if(j == n-i+1)
cout<<"*";
else
cout<<" ";
}
}
cout<<endl;
}
return 0;
}
注:
图形的输出还可以用数组来处理,有时处理会简单,有时处理会很繁杂,具体要看题目要求。
10.输入 n 值,输出K图形
* *
* *
* *
*
* *
* *
* *
#include <iostream>
using namespace std;
int main() {
void f(int n, int i);
int n;
cin>>n;
for(int i=n ; i>1 ;i--)
f(n,i);
for(int i=1 ; i<=n ;i++)
f(n,i);
return 0;
}
void f(int n, int i) {
for(int j=1 ; j<=i ; j++) {
if(j == 1)
cout<<"* ";
else if(j == i)
cout<<"*";
else
cout<<" ";
}
cout<<endl;
}
11.输入 n 值,输出N图形
* *
** *
* * *
* * *
* **
* *
#include <iostream>
using namespace std;
int main() {
int n;
cin>>n;
char s[n][n];
for(int i=0 ; i<n ; i++) {
for(int j=0 ; j<n ; j++) {
if(j == 0 || j == n-1 || j == i) {
s[i][j]='*';
cout<<s[i][j];
}
else {
s[i][j]=' ';
cout<<s[i][j];
}
}
cout<<endl;
}
return 0;
}
13.输入 n 值,输出倒V图形
*
* *
* *
* *
* *
#include <iostream>
using namespace std;
int main() {
int n;
cin>>n;
for(int i=1 ; i<=n ; i++) {
for(int j=1 ; j<=n-i; j++)
cout<<" ";
for(int j=1 ; j<=2*i-1 ; j++) {
if(j == 1 || j ==2*i-1 )
cout<<"*";
else
cout<<" ";
}
cout<<endl;
}
return 0;
}
【3】较难题
L1-002 打印沙漏
(题目链接:L1-002 打印沙漏)
19 *
*****
***
*
***
*****
2
#include<stdio.h> //[1]
#include<iostream>
using namespace std;
int main() {
void f(int h, int i,char ch);
int n;
cin>>n;
char ch;
scanf(" %c%*c",&ch);
/*等效于scanf("%d %c",&n,&ch);*/
int m,s[1000]={1},j=1,ml;
for(int i=3 ; i<=1000 ; i+=2){
s[j]=s[j-1]+2*i; //前一个与后一个的关系
if(s[j-1]<=n && n<s[j]) {
m=s[j-1];
ml=n-m;
break;
}
j++;
}
int h=2*j-1;
for(int i=0 ; i<h/2+1 ; i++)
f(h,i,ch);
for(int i=h/2-1 ; i>=0; i--)
f(h,i,ch);
cout<<ml;
return 0;
}
#include <iostream> //[2]
#include <cmath>
using namespace std;
int main() {
void f(int a,char ch,int i);
int n;
char ch;
cin>>n>>ch;
int a=sqrt((n+1)/2);
for(int i=0 ; i<a ; i++)
f(a,ch,i);
for(int i=a-2; i>=0; i--)
f(a,ch,i);
cout<<n-2*a*a+1;
return 0;
}
void f(int a,char ch,int i) {
for(int j=0; j<i ; j++)
printf("%c",'\0');
for(int j=0; j<2*(a-i)-1 ; j++)
printf("%c",ch);
cout<<endl;
}
分析:这道题的难点就是找规律,找到行数与点数的关系;
行数=sqrt((点数+1)/2);
如果实在找不到规律,可以像[1]一样直接一步一步的处理,直至达到最终目的
输出n=6的五角星
*
***
*****
*******
*********
***********
************************************
******************************
************************
******************
**************
****************
******** ********
****** ******
**** ****
** **
#include <stdio.h>
int main()
{
int i,j;
for(i=1;i<=6;i++) //处理上层顶角
{
for(j=0;j<19-i;j++) //输出空格
printf(" ");
for(j=0;j<2*i-1;j++) //输出*号
printf("*");
printf("\n");
}
for(i=6;i>=3;i--) //处理中层
{
for(j=0;j<6-i;j++)
printf(" ");
for(j=0;j<6*i;j++)
printf("*");
printf("\n");
}
for(i=1;i<=6;i++) //处理下层
{ for(int j=0 ; j<12-i; j++ )
printf(" ");
for(int j=0 ; j<12+2*i ; j++) {
if(i<=2)
printf("*");
else {
if(j>=14-2*i && j<=4*i-3)
printf(" ");
else
printf("*");
}
}
printf("\n");
}
return 0;
}
15.在屏幕上输出一个由*号围成的空心圆
**
* *
* *
* *
* *
* *
* *
* *
* *
* 1 *
* *
* *
* *
* *
* *
* *
* *
* *
* *
* *
**
#include<iostream>
using namespace std;
#include<math.h>
int main() {
double y,x,m;
double r;
cin>>r;
for(y=r;y>=-r;y--) {
m=2.1*sqrt(r*r-y*y); /*计算行y对应的列坐标m,2.1是屏幕纵横比调节系数因为屏幕的
行距大于列距,不进行调节显示出来的将是椭圆*/
for(x=1;x<=3*r-m;x++)
cout<<" "; /*图形左侧空白控制*/
cout<<"*"; /*圆的左侧*/
for(;x<3*r+m;x++)
cout<<" "; /*图形的空心部分控制*/
cout<<"*\n"; /*圆的右侧*/
}
return 0;
}
分析:m=ksqrt(rr-y*y);k不同,说呈现图形的宽窄就不同,并且不同的编译器成⚪时的k不同,所以导致k很难把握;只能形成一个大概的
#include <iostream>
#include <math.h>
using namespace std;
int isAtCircle(int x, int y, int r) { //判断是是否在圆上
int rx = x - r; //将(x, y)转换为相当圆心(r, r)的坐标
int ry = y - r;
double d = sqrt(rx*rx + ry*ry) - r; //计算到圆心的距离
if(fabs(d) < 0.5) //判断到圆心的距离是否为r(允许0.5的误差)
return 1;
else
return 0;
void printCircle(int r) {
int x, y;
for (y=0; y<2*(r+1); y++) {
for (x=0; x<2*(r+1); x++) {
if (isAtCircle(x, y, r)) /*如果这个点在圆上,打印'*',否则,打印' '*/
cout<<"* "; /*因为字符高比宽大,所以加一个空格调整外观*/
else
cout<<" ";
}
cout<<endl;
}
}
int main() {
int r; //输入圆的半径
cin>>r;
printCircle(r);
return 0;
}
分析:这是根据圆的方程来定,并且是根据距离与半径的误差来算,这种方法更可靠;
14.输出如图所示 sin(x) 函数 0 到 2π的图形
imput to m,n:
40 39
---------------------------------------*----------------------------------------
| *
| *
| *
| *
| *
| *
| *
| *
| *
| *
| *
| *
| *
| *
| *
| *
| *
*
* |
* |
* |
* |
* |
* |
* |
* |
* |
* |
* |
* |
* |
* |
* |
* |
* |
*|
#include <iostream>
#include <math.h>
#define PI 3.1415926
using namespace std;
int main() {
cout<<"imput to m,n:\n";
int m,n; //m为初相,n为振幅
do {
cin>>m>>n;
}while(m<=n && m>95); //当m>n且m<96时跳出循环
for(int i=1 ; i<=2*m;i++)
if(i == m )
cout<<"*";
else
cout<<"-";
cout<<endl;
for(double x=10; x<=360; x+=10) {
int y=m+n*sin(x*PI/180);
for(int i=1 ; i<=2*m; i++) {
if(i == y)
cout<<"*";
else if(i == m)
cout<<"|";
else
cout<<" ";
}
cout<<endl;
}
return 0;
}
分析:(1) m > n : m>n: m>n:由于屏幕上的每列的距离大于每行的距离,当 m = n m=n m=n时,会出现图形超界的现象;
(2) m < 96 : m<96: m<96:是屏幕所能显示的最大图形的边界,这个边界依电脑尺寸而定; (3) n > 10 : n>10: n>10:能够较准确的显示图形;
(4) d o u b l e x = 10 ; x < = 360 ; x + = 10 : double x=10; x<=360; x+=10: doublex=10;x<=360;x+=10:把一个步长定义为 10 度,打印时每换一行等于函数的自变量 增加 10
度,能够是图形变得更好看;
(3) y = m + n ∗ s i n ( x ∗ P I / 180 ) : y=m+n*sin(x*PI/180): y=m+n∗sin(x∗PI/180):x表示为度数,度数与弧度的关系:角度 ∗ ( P I / 180 ) = *(PI/180)= ∗(PI/180)=弧度
二. 数字型的图案
【1】实心图案
17.输出数字形成一个矩形(每行从左到右连加,每行结束不置0)的图形
1 2 3 4 5 6
7 8 9 10 11 12
13 14 15 16 17 18
19 20 21 22 23 24
25 26 27 28 29 30
31 32 33 34 35 36
#include <iostream>
using namespace std;
int main() {
int n;
cin>>n;
int k=0;
for(int i=0; i<n ; i++ ) {
for(int j=0 ; j<n ; j++) {
k++; //不置0
printf("%4d",k);
}
cout<<endl;
return 0;
}
18.输出数字倒三角的图形
1 3 6 10 15 21
2 5 9 14 20
4 8 13 19
7 12 18
11 17
16
#include <iostream>
using namespace std;
int main() {
int n;
cin>>n;
int k=1;
for(int i=1 ; i<=n ; i++) {
int m=k; //k是第i行中第一个元素的值
for(int j=1 ; j<=n-i+1 ; j++) {
printf("%3d",m);
m+=i+j; //计算同行下一个元素的值
}
k+=i; //计算下一行中的一个元素
cout<<endl;
}
return 0;
}
分析:此题的关键是找到输出数字和行、列数的关系。审查图形中每行中数字的关系发现:
(1)右边数字和前面数字之差逐次增 1 ;
(2) 同列数字依然是这样的关系,编程的关键转换为找到每一行左方的第一个数字,然后利用行和列的循环变量进行运算就可得到每个位置的数字。用
a i j a_{ij} aij表示第 i i i行第 j j j 列的数字,则 a 11 = 1 a_{11}=1 a11=1;由第 i i i行第 1 1 1列的数字推出第
i + 1 i+1 i+1行第 1 1 1列的数字是 a i + 1 , a i = 1 , 1 + i a_i+1 ,a_i=1 ,1+i ai+1,ai=1,1+i;同样由第 j j j列推出第 j + 1 j+1 j+1 列的数字是 a i , j + 1 = a i , j + i + j a_i,j+1 = a_i,j+i+j ai,j+1=ai,j+i+j。另外只有当 j < i j<i j<i时才输出数字。
19.输入 n 值,输出特殊的数字矩形
1 2 3 4 5
1 1 2 3 4
1 1 1 2 3
1 1 1 1 2
1 1 1 1 1
#include <iostream>
using namespace std;
int main() {
int n;
cin>>n;
int k=1;
for(int i=0; i<n ; i++) {
int m=k; //代表每行第一个元素
for(int j=0 ; j<n ; j++) {
if(j<=i)
printf("%3d",k);
else {
m++;
printf("%3d",m);
}
}
cout<<endl;
}
return 0;
}
22.输出如图所示的数字金字塔
1
1 2 1
1 2 3 2 1
1 2 3 4 3 2 1
1 2 3 4 5 4 3 2 1
1 2 3 4 5 6 5 4 3 2 1
1 2 3 4 5 6 7 6 5 4 3 2 1
1 2 3 4 5 6 7 8 7 6 5 4 3 2 1
1 2 3 4 5 6 7 8 9 8 7 6 5 4 3 2 1
#include <iostream>
using namespace std;
int main() {
int k=1;
for(int i=1 ; i<=9 ; i++) {
int m=k;
for(int j=1 ; j<=9-i ; j++)
cout<<" ";
for(int j=1 ; j<=2*i-1 ; j++) {
if(j<i)
printf("%-2d",m++);
/*等效代码:if(j<i) {
printf("%-2d",m);
m++;
}
*/
//故就j == i 时进入下一条语句时不加1,故if(j<i)而不是if(j<=i)
else
printf("%-2d",m--);
}
cout<<endl;
}
return 0;
}
27.输出如图所示上三角形式的乘法九九表
1 2 3 4 5 6 7 8 9
----------------------------
1 2 3 4 5 6 7 8 9
4 6 8 10 12 14 16 18
9 12 15 18 21 24 27
16 20 24 28 32 36
25 30 35 40 45
36 42 48 54
49 56 63
64 72
81
#include <iostream>
using namespace std;
int main() {
for(int i=1; i<10 ; i++)
printf("%3d",i);
cout<<endl;
cout<<" ----------------------------\n";
for(int i=1 ; i<=9 ; i++) {
for(int j=1 ; j<=9 ; j++) {
if(i<=j)
printf("%3d",i*j);
else
printf("%3c",'\0');
}
cout<<endl;
}
return 0;
}
28.输出如图所示下三角乘法九九表
1 2 3 4 5 6 7 8 9
----------------------------
81
64 72
49 56 63
36 42 48 54
25 30 35 40 45
16 20 24 28 32 36
9 12 15 18 21 24 27
4 6 8 10 12 14 16 18
1 2 3 4 5 6 7 8 9
#include <iostream>
using namespace std;
int main() {
for(int i=1; i<10 ; i++)
printf("%3d",i);
cout<<endl;
cout<<" ----------------------------\n";
for(int i=9 ; i>0 ; i--) {
for(int j=1 ; j<=9 ; j++) {
if(i<=j)
printf("%3d",i*j);
else
printf("%3c",'\0');
}
cout<<endl;
}
return 0;
}
关于printf("%mc",‘字符’);的分析:
处理空格问题时,我们可以使用一个空字符(’\0’)来代替空格,这是一种新做法;
【2】空心图案
23.输入 n 值,输出数字型菱形
Z
Y X
W V
U T
S R
R Q
P O
N M
L
#include <iostream>
#include <ctype.h>
using namespace std;
int main() {
void f(int n, int i, char &ch);
int n;
cin>>n;
char ch='Z';
for(int i=1 ; i<=n ; i++)
f(n,i,ch);
ch++;
for(int i=n-1; i>0 ; i--)
f(n,i,ch);
return 0;
}
void f(int n, int i, char &ch) {
for(int j=0 ; j<n-i; j++)
cout<<" ";
for(int j=1 ; j<=2*i-1 ; j++) {
if(j == 1)
cout<<ch;
else if(j == 2*i-1) {
ch--;
if(!isalpha(ch)) //判段右边是否为非字母字符
ch='Z';
cout<<" "<<ch;
}
else
cout<<" ";
}
cout<<endl;
ch--;
if(!isalpha(ch)) //判段左边是否为非字母字符
ch='Z';
}
分析:这种体型的难点是怎样字符递减和循环; (1)递减:从左到右依次递减,所以要写两个ch–;
(2)循环:有最后一个字母A在右边和在左边这两种情况,需考虑清楚
(3)上下半部分的分界点:中间要加一个ch++;
因为下半部分是从上半部分的最后一个字母开始的,若不加这一步,则其会自动减1;
24.输入顶行字符和图形的高,输出菱形
A A
B B B B
C C C C
D D D D
E 1 E E 2 E
D D D D
C C C C
B B B B
A A
#include <iostream>
using namespace std;
int main() {
void f(int n,int i,char ch);
int n;
char ch;
do {
cin>>ch>>n;
}while(!isalpha(ch)); //当且仅当ch为字母时跳出循环(1)
for(int i=0 ; i<n ; i++) {
if(!isalpha(ch)) { //当ch不是字母时
if(islower(ch-1)) //当ch-1为Z时,ch=A,形成一个闭合的循环(2)
ch='a';
else
ch='A';
}
f(n,i,ch);
ch++;
}
ch--;
for(int i=n-2; i>=0; i--) {
ch--;
if(!isalpha(ch)) {
if(islower(ch-1)) //当ch-1为A时,ch=Z,形成一个闭合的循环(3)
ch='z';
else
ch='Z';
}
f(n,i,ch);
}
return 0;
}
void f(int n,int i,char ch) { //1
for(int j=0 ; j<n-i-1; j++ )
cout<<" ";
for(int j=0 ; j<2*i+1 ; j++ ) {
if(j == 0)
cout<<ch<<" ";
else if(j == 2*i)
cout<<ch;
else
cout<<" ";
}
cout<<endl;
}
/*
void f(int n,int i,char ch) { //2
for(int j=0 ; j<n-i-1; j++ )
cout<<" ";
for(int j=0 ; j<2*i+1 ; j++ ) {
if(j == 0 ||j == 2*i)
cout<<ch;
else
cout<<" ";
}
cout<<endl;
} */
return 0;
}
分析:注意代码的三个注解:
(1)输入是在人手上输入的,如果一开始输入的不是字母,由于其是形成一个闭合的循环,所以如果你一开始输入非字母的字符,结果始终是从A开始,与题意(输入顶行字符
和图形的高,输出菱形)不符;所以一旦不注意就会漏写。
(2)(3)题目的意思是最终结果都是由字母组成的,如果你不写这两段代码,结果会有非字母的形成。所以它要形成一个闭合的循环
(4)
调用自定义函数时,如果不是用指针来做
,就不能直接在自定义函数中改变参数的值,因为函数只是起调用作用