课程项目
占平时成绩20%, 即10分, 最高10分, 预计平均分8分
读入一个矩阵, 并把矩阵中的数据画成SVG描述的图表(chart).
矩阵大小最大是15x15.
例如, 矩阵每行画成一条线或一个饼图.
也可以把整个矩阵画成一个平面.
下面例子中是一个极其简单的例子, 同学们将实现华丽的图表, 相互PK获得高分.
说明
有能力的同学可以画多个图
需要读入矩阵的所有数据以反映所画的SVG是动态生成的
如果有需要, 可以自己加入数据或文字, 如图标标题, 数据名称等
评分时会把你画出的SVG放入其他网页中显示, 请不要使用动画或插入javascript代码, 否则可能不能正确显示
课程项目评分可能会使用匿名互评的方式, 为了公平, 请不要在你的SVG中包含个人信息
学习SVG
https://www.runoob.com/svg/svg-tutorial.html
https://c.runoob.com/more/svgeditor/
EXAMPLE INPUT
6 5 5 4 3 3 3 2 1 2 2 2 2
9 8 7 6 7 7 5 5 5 4 5 6 5
13 10 12 10 8 8 8 8 8 9 8 9 8
16 15 15 12 13 11 11 12 9 10 10 11 10
18 18 17 15 16 15 15 15 12 15 14 14 15
20 21 20 20 18 18 18 16 17 18 18 17 18
EXAMPLE OUTPUT
以下为输出的SVG保存为.html文件后,拖到浏览器中显示出来的效果
更多图表例子
https://echarts.apache.org/examples/en/index.html
我的答案
#include <stdio.h>
#include <string.h>
#define PI 3.14159265
double sin(double x){
register double ret;
__asm__ (
"fsin"
: "=t" (ret)
: "0" (x)
);
return ret;
}//计算x(弧度表示)的正弦值
double cos(double x){
register double ret;
__asm__(
"fcos"
: "=t" (ret)
: "0" (x)
);
return ret;
}//计算x(弧度表示)的余弦值。
int main() {
char text[10][100];
int line=0;
int row;
for (int i = 0; i <10; ++ i) {
if(fgets(text[i],100,stdin)==NULL){
line=i;
break;
}
}
//从控制台获取含数字的完整字符串
int number[line][100];
int judge;//用于判断是否读入了数字
for (int i = 0; i <line; ++ i) {
int j=0;
int n;
char *p=text[i];
while(1){
int temp=0;
judge= sscanf(p,"%d %n", &temp,&n);
if(judge==1){
number[i][j]=temp;
p+=n;
++j;
}
else{
row=j;
break;
}
}
}
//用于将字符串中的数字转存至整型数组中
//以上已经实现数据录入到整数数组中 并记录行数line 列数row
int maxnumber=0;
int minnumber=0;
for (int i = 0; i <row; ++ i){
if(number[line-1][i]>maxnumber){
maxnumber=number[line-1][i];
}
if(number[0][i]<minnumber){
minnumber=number[0][i];
}
}
//查找数组中的最大数值 以确定图形的x方向大小 另外查找(伪)最小数值:如果存在小于0则为此小于0的数字 如果不存在则为0
int sizeofpic=(maxnumber-minnumber)*20+80;//每两个数值间间隔为10
double jiaodu=PI*2/row;//夹角大小
printf("<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" width=\"%d\" height=\"%d\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",sizeofpic,sizeofpic);
printf("<rect width=\"%d\" height=\"%d\" fill=\"rgxb(0,0,0)\" stroke-width=\"1\" stroke=\"rgb(0,0,0)\"/>\n",sizeofpic,sizeofpic);
//背景边框
printf("<text x=\"-200\" y=\"30\" stroke=\"rgb(34,139,34)\" font-size=\"20px\" fill=\"rgb(34,139,34)\">雷达图——%d行%d列矩阵<animate attributeName=\"x\" values=\"-200;%d\" begin=\"0s\" dur=\"%ds\" repeatCount=\"1000\" fill=\"freeze\" /></text>\n",line,row,sizeofpic+200,sizeofpic/50);
for (int i = maxnumber-minnumber; i >=0; -- i) {
printf("<circle cx=\"%d\" cy=\"%d\" r=\"%d\" stroke=\"rgb(24,139,15)\" stroke-width=\"4\" fill=\"rgb(22,71,20)\" fill-opacity=\"0.5\" />\n",sizeofpic/2,sizeofpic/2,i*10);
--i;
}//画圆作为背景
printf("<line x1=\"0\" y1=\"%d\" x2=\"%d\" y2=\"%d\" stroke=\"rgb(24,139,15)\" stroke-width=\"4\"/>\n",sizeofpic/2,sizeofpic,sizeofpic/2);
printf("<line x1=\"%d\" y1=\"0\" x2=\"%d\" y2=\"%d\" stroke=\"rgb(24,139,15)\" stroke-width=\"4\"/>\n",sizeofpic/2,sizeofpic/2,sizeofpic);
printf("<line x1=\"%d\" y1=\"%d\" x2=\"%d\" y2=\"-1000\" stroke=\"rgb(24,139,15)\" stroke-width=\"4\"><animate attributeName=\"x2\" values=\"%d;%d;%d;-1000;%d\" begin=\"0s\" dur=\"5s\" repeatCount=\"1000\" fill=\"freeze\" /><animate attributeName=\"y2\" values=\"-1000;%d;%d;%d;-1000\" begin=\"0s\" dur=\"5s\" repeatCount=\"1000\" fill=\"freeze\" /></line>\n",sizeofpic/2,sizeofpic/2,sizeofpic/2,sizeofpic/2,sizeofpic+1000,sizeofpic/2,sizeofpic/2,sizeofpic/2,sizeofpic+1000,sizeofpic/2);
for (int i = 0; i < line ; ++ i) {
printf(" <polyline points=\"");
for (int j = 0; j < row ; ++ j) {
int length=(number[i][j]-minnumber)*10;//目标点离圆心的应有距离
printf("%lf,%lf ",sizeofpic/2+length*sin(jiaodu*j),sizeofpic/2-length*cos(jiaodu*j));
}
printf("%d,%d ",sizeofpic/2,sizeofpic/2-(number[i][0]-minnumber)*10);
printf("\" fill=\"none\" stroke=\"rgb(255,255,0)\" stroke-width=\"3\"/>\n");
}//画折线 标记的每一个点 离圆心的距离都应该是它对应的数值*10
printf("<text x=\"%d\" y=\"%d\" stroke=\"rgb(34,139,34)\" font-size=\"20px\" fill=\"rgb(34,139,34)\">说明:相邻圆环间距为2个单位<animate attributeName=\"x\" values=\"%d;-150\" begin=\"0s\" dur=\"%d\" repeatCount=\"1000\" fill=\"freeze\" /></text>\n",sizeofpic,sizeofpic-20,sizeofpic,sizeofpic/50);
printf("</svg>");
}
代码效果
复刻示例版本
#include <stdio.h>
#include <string.h>
int main() {
char text[10][100];
int line=0;
int row;
for (int i = 0; i <10; ++ i) {
if(fgets(text[i],100,stdin)==NULL){
line=i;
break;
}
}
//从控制台获取含数字的完整字符串
int number[line][100];
int judge;//用于判断是否读入了数字
for (int i = 0; i <line; ++ i) {
int j=0;
int n;
char *p=text[i];
while(1){
int temp=0;
judge= sscanf(p,"%d %n", &temp,&n);
if(judge==1){
number[i][j]=temp;
p+=n;
++j;
}
else{
row=j;
break;
}
}
}
//用于将字符串中的数字转存至整型数组中
//以上已经实现数据录入到整数数组中 并记录行数line 列数row
int maxnumber=0;
int minnumber=100;
for (int i = 0; i <row; ++ i){
if(number[line-1][i]>maxnumber){
maxnumber=number[line-1][i];
}
if(number[0][i]<minnumber){
minnumber=number[0][i];
}
}
//查找数组中的最大数值 以确定图形的x方向大小 另外查找最小数值
printf("<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" width=\"%d\" height=\"%d\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",row*20+50,maxnumber*10+50);
for (int i = 0; i < line ; ++ i) {
printf(" <polyline points=\"");
for (int j = 0; j < row ; ++ j) {
printf("%d,%d",j*20+30,maxnumber*10+20-number[i][j]*10);//参考答案生成的第二个坐标有时会+1
if(j!=row-1){
printf(" ");
}
}
printf("\" fill=\"none\" stroke=\"rgb(%d,100,100)\" stroke-width=\"3\"/>\n",number[i][0]*10+1);
//颜色的生成不知道是怎么样一个规律
}
//上面实现折线的生成 数值越大越靠上 输入的第一组数据打印在最底层(因为数字小)
printf(" <line x1=\"25\" y1=\"%d\" x2=\"%d\" y2=\"%d\" stroke=\"rgb(0,0,0)\" stroke-width=\"1\"/>\n",maxnumber*10+20,row*20+20,maxnumber*10+20);//绘制x轴
printf(" <line x1=\"%d\" y1=\"%d\" x2=\"%d\" y2=\"%d\" stroke=\"rgb(0,0,0)\" stroke-width=\"1\"/>\n",row*20+15,maxnumber*10+18,row*20+20,maxnumber*10+20);//绘制x轴上箭头
printf(" <line x1=\"%d\" y1=\"%d\" x2=\"%d\" y2=\"%d\" stroke=\"rgb(0,0,0)\" stroke-width=\"1\"/>\n",row*20+15,maxnumber*10+22,row*20+20,maxnumber*10+20);//绘制x轴下箭头
printf(" <line x1=\"30\" y1=\"15\" x2=\"30\" y2=\"%d\" stroke=\"rgb(0,0,0)\" stroke-width=\"1\"/>\n",maxnumber*10+25);
//绘制y轴
printf(" <line x1=\"28\" y1=\"20\" x2=\"30\" y2=\"15\" stroke=\"rgb(0,0,0)\" stroke-width=\"1\"/>\n");
//绘制y轴左箭头
printf(" <line x1=\"32\" y1=\"20\" x2=\"30\" y2=\"15\" stroke=\"rgb(0,0,0)\" stroke-width=\"1\"/>\n");
//绘制y轴右箭头
printf("<text x=\"10\" y=\"20\" stroke=\"rgb(100,100,100)\">y</text>\n");
printf("<text x=\"%d\" y=\"%d\" stroke=\"rgb(100,100,100)\">x</text>\n",row*20+10,maxnumber*10+40);
//printf("<a xlink:href=\"https://yizuodi.cn\" target=\"_blank\"><text x=\"10\" y=\"%d\" stroke=\"rgb(100,100,100)\">My blog</text><\\a>\n",maxnumber*10+30);
printf("</svg>");
//打印坐标轴并输出结束符
}