垂直柱状图

#include<iostream>
#include<cstring>
#include<cstdlib>
using namespace std;
//思路:
//输入的四行字符串连接到同一个字符串变量s中,for循环统计每个大写字母在s中出现的次数
//cnt存放26个字母每个字母出现次数
//根据cnt绘制带*和空格的柱状图(用二维数组保存至ans)
//最后输出ans即为正解 
string s1,s2,s3,s4;
int cnt[27];
int main()
{
    getline(cin,s1);
    getline(cin,s2);
    getline(cin,s3);
    getline(cin,s4);
    string s=s1+s2+s3+s4; 
    int pos,maxi=0;
    memset(cnt,0,sizeof(cnt));
    for(int i=0;i<s.size();i++)
    {
        if(s[i]-65>=0&&s[i]-65<=25)//过滤掉不是大写字母的字符 
        {
            pos=s[i]-65;//找到遍历到的字母所对应的cnt位置 
            cnt[pos]++;    //每找到26个字母中的一个,对应cnt中的字母个数+1 
        }
    }
    for(int i=0;i<25;i++)//根据出现次数最多的字母绘制柱状图 ,maxi为二维数组ans中的行数 
    {
        if(cnt[i]>maxi)
        maxi=cnt[i];
    }
    char ans[maxi+1][26];//因为最后一行要输出ABCD...所以ans行数为maxi+1 
    memset(ans,'*',sizeof(ans)); //用'*'初始化ans 
//    for(int i=0;i<maxi+1;i++)
//    {
//        memset(ans[i],'A',26*sizeof(char));
//    }
    for(int j=0;j<26;j++)//ans的每一列是每个字母的个数对应的'*'数,所以每一列的空格数即为最大数减去'*'数 
    {
        for(int i=0;i<maxi-cnt[j];i++)//最大行数 - '*'数 = 每一列顶部空格数  
        ans[i][j]=' ';//赋值为空格,注意与'\0'区分  
        ans[maxi][j]=65+j;//最后一行ABCD...Z 
    }
    //输出柱状图 
    for(int i=0;i<maxi+1;i++)
    {
        for(int j=0;j<26;j++)
        {
            if(j==25)//严格按照题目输出格式要求,每行末尾不能有多余空格 
            cout<<ans[i][j];
            else cout<<ans[i][j]<<" ";
        }
        if(i!=maxi)    //严格按照题目输出格式要求,最后一行不能有多余换行 
        cout<<endl;
    }
//    cout<<maxi;
    return 0;
}

现在开始排坑

一、选取读文件的函数

一开始想到的是字符串数组来处理,发现cin.getline()参数里还有读取字符个数这一项,这谁能确定啊,于是搜出来用string类的getline()函数,这下舒服多了,四个字符串相加的操作也简单多了,包括后面遍历时循环条件可以直接用size(),简直便捷下面就说说字符串数组和字符串处理中在这道题里遇到的问题的小区别吧

cin.getline()

 

此函数会一次读取多个字符(包括空格字符)。它以指定的地址为存放第一个读取的字符的位置,依次向后存放读取的字符,直到读满N-1个,或者遇到指定的结束符为止。若不指定结束符,则默认结束符为换行符,此函数并不保留结束符,它通过结束符确定结束,但不保存结束符,它用空字符来替换结束符。当 cin.getline 语句执行时,cin 读取的字符数将比该数字少一个,为 null 终止符留出空间。其语法为:

 

cin.getline(字符指针(char*),字符个数N(int),结束符(char));
 
用法:
#include <iostream>
using namespace std;
int main()
{
    char a[30];
    cin.getline(a, 10);
    for( int i=0; i<10; i++ )
        cout << a[i] << " ";
    return 0;
输入:1234567890123
输出:1 2 3 4 5 6 7 8 9 _ (第10位存放字符串结束符'\0')
注意到cin.getline()需指定读取字符个数,若读取时不清楚要读取的字符个数,则可以用string的getline()
 
getline()

用于string类的。使用需包含头文件#include<string>。getline(cin,string s),接收一个字符串,可以接收空格、回车等

getline是string模板类下的一个函数,功能是读取证行的语句其原型为:

istream& getline ( istream &is , string &str , char delim );

其中 istream &is

表示一个输入流,譬如cin;string&str表示把从输入流读入的字符串存放在这个字符串中(可以自己随便命名,str什么的都可以);

char delim表示遇到这个字符停止读入,在不设置的情况下系统默认该字符为'\n',也就是回车换行符(遇到回车停止读入)

举例:

string line;
 
cout<<"please cin a line:"
 
getline(cin,line,'#');
 
cout<<endl<<"The line you give is:"<<line;

那么当输入"You are the #best!"的时候,输入流实际上只读入了"You are the",#后面的并没有存放到line中。

然后程序运行结果应该是这样的:

please cin a line:You are the #best!
 
The line you give is:You are the

而且这里把终止符设为#,你输入的时候就算输入几个回车换行也没关系,输入流照样会读入,譬如:

    1. please cin a line:You
    2.   
    3.  are the best!

那么如果把getline()作为while的判断语句会怎么样呢?让我们一起来分析一下while(getline(cin,line))语句

注意这里默认回车符停止读入,按Ctrl+Z或键入EOF回车即可退出循环。

在这个语句中,首先getline从标准输入设备上读入字符,然后返回给输入流cin,注意了,是cin,所以while判断语句的真实判断对象是cin,也就是判断当前是否存在有效的输入流。在这种情况下,不管你怎么输入都跳不 出循环,因为你的输入流有效,跳不出循环。

用法:

1 #include<bits/stdc++.h>
2 using namespace std;
3 int main()
4 {
5     string a;
6     getline(cin,a);     
7     cout<<a;
8     return 0;
9 }

 

与cin.getline()的区别:

          1.cin.getline()接收输入字符串的是字符串数组或字符串指针,getline()是string类型。

                                    2.cin.getline()可以接收空格,但不能接收回车;getline()可以接收空格和回车

                                    3.cin.getline()如果没有设置第三个参数(结束条件)会在数组结尾是'\0',但getline()不会

具体详见:

https://www.cnblogs.com/hchacha/p/6517564.html

函数原型参见:http://www.cplusplus.com/reference/istream/istream/getline/

标准信息来自《c++primer》和《c++ primer plus》,另http://blog.csdn.net/vanwaals/article/details/5753556

http://blog.csdn.net/mylovepan/article/details/7940719

 

二、字符串(字符数组)相加

1.用于字符数组(指针)的strcat()

原型   extern char *strcat(char *dest, const char *src);


在C中,则存在于<string.h>头文件中。
在C++中,则存在于<cstring>头文件中。
将两个char类型连接。

char d[20]=“GoldenGlobal”; char *s=“View”; strcat(d,s);

结果放在d中
printf("%s",d);
输出 d 为 GoldenGlobalView (中间无空格)
d和s所指内存区域不可以重叠且d必须有足够的空间来容纳s的字符串。
返回指向d的指针。

2.两个字符串string相加

两个string对象可以相加,结果是两个string拼接而成。

string s1 = "hello", s2 = "world";
string s2 = s1 + s2;        // 结果为helloworld

字符(串)也可以和string对象相加,因为标准库允许将字符字面值和字符串字面值转换成string对象,但要求在+号两侧必须至少有一个为string:

// 允许字符字面值与string相加
    string s4 = s1 + ',' + s2;    // 输出hello,world
    string s5 = ',' + '=';        // 实质上为','和'='的ASCII码值相加,相加得不到字符串“,=”且会报错
    string s6 = s1 + ',' + '=';     // 连加原理
    string s7 = ',' + '=' + s1;        // error
————————————————
版权声明:本文为CSDN博主「BLoneliness」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/BLoneliness/article/details/87079561

其中,s5会编译出错,+号两侧的运算对象都不是string, 而s6等效于

string s6 = (s1 + ',') + '=' ;

其中表达式s1 + ','是一个string对象。 而s7等效于

string s7 = (',' + '=' ) + s1;

括号里的表达式试图将两个字符字面值加在一起,而编译器根本做不到这一点。

 

三、'\0'和' '的区别(太坑) (附加'\0','0'和"0"的区别)

1.'\0'和' '的区别

  '\0'和空格不是同一个概念。
  '\0'表示字符串结束符,代表字符串结束,而空格是一个普通字符,显示在文本中可以选中。
  '\0'的ASCII码为0,空格的ASCII码为32,两个不是同一个字符
  在计算机程序中通常使用'\0'表示字符串结束,空格为文本字符,二者完全不同

比如一个字符串,是以字符'\0'结束,而一个字符串中是可以有空格的,如:“your name”

所以,题目中要是说到柱状图由空格和'*'组成,你在赋值的时候就用' '或者它的ASCII值:32 来表示,千万不能用'\0'。(T_T)

 

2.'\0','0'和"0"的区别

  首先比较一下‘\0’和‘0’的区别。有一个共同点就是它们都是字符,在c语言中,字符是按其所对应的ASCII码来存储的,一个字符占一个字节。请看第一个ASCII码,对是0,对应的字符是(Null),其实就是 ‘\0’,即空字符。判断一个字符串是否结束的标志就是看是否遇到‘\0’,如果遇到‘\0’,则表示字符串结束。而字符‘0’对应的ASCII码是 48,48对应的十六进制数就是0x30。

 

  接下来比较一下“0”和‘0’的区别。首先“0”是字符串常量,字符串常量是由一对双引号括起的字符序列。例如:“CHINA”,“I LOVE YOU”,“123”等都是合法的字符串常量。‘0’是字符常量,字符串常量和字符常量是不同的量。1:字符常量由单引号括起来;字符串常量由双引号括起 来。2:字符常量只能是单个字符;字符串常量则可以含一个或多个字符。

四、memset()用法

最后  审题啊审题,要求输入输出格式,一个都不能少!!!

不能有多余的空格和换行!!!

注:个别内容有借鉴

 

posted @ 2020-02-04 16:36  林夕雪儿  阅读(238)  评论(0编辑  收藏  举报