字符串习题

打印 上一主题 下一主题

主题 1021|帖子 1021|积分 3067

单词个数统计

原作:

输入: 一行字符串。仅有空格和英文字母构成。
输出:
英文字母个数letter_num
单词个数word_num
出现最多的字母max_letter
出现最多的字母的出现次数max_letter_frequ
处理处罚:

  • 统计并输出此句子英文字母的个数;
  • 统计并输出此句子中单词的个数;
  • 查找此句子中出现次数最多的字母(不区分大小写,大小写字母是相同的)及次数。当出现最多的字母不止一个时,全部找到,并输出找到的所有字母及次数。(输出次序按字母次序,且输出时字母全部小写)
  1. int main() {
  2.    //输入:一行字符串。仅有空格和英文字母构成。
  3.    char arr[1024];
  4.    string s;
  5.    fgets(arr, sizeof(arr), stdin);
  6.    s = arr;
  7.    //英文字母个数
  8.    int letter_num = 0;
  9.    //单词的个数
  10.    int word_num = 0;
  11.    map<char,int> myMap;
  12.    //处理
  13.    //统计并输出此句子英文字母的个数
  14.    for (int i = 0; i < s.size(); i++) {
  15.        if (s[i] != ' ') {
  16.            letter_num++;
  17.            //将s[i]统一转成小写
  18.            if (s[i] >= 'A' && s[i] <= 'Z') {
  19.                s[i] += 32;
  20.            }
  21.            myMap[s[i]]++;
  22.            if (s[i] == ' ' && s[i + 1] != ' ') {
  23.                word_num++;
  24.            }
  25.        }
  26.    }
  27.    //输出:英文字母的个数
  28.    printf("%d\n", letter_num);
  29.    //输出:单词的个数
  30.    printf("%d\n", word_num);
  31.    //输出:出现次数最多的字母
  32.    map<char,int>::iterator it;
  33.    //找到字母出现的最多次数
  34.    int max = 0;
  35.    for (it=myMap.begin(); it != myMap.end(); it++) {
  36.        if (it->second > max) {
  37.            max = it->second;
  38.        }
  39.    }
  40.    //找到值为max的所有键
  41.    vector<char>max_letters;
  42.    for (it = myMap.begin(); it != myMap.end(); it++) {
  43.        if (it->second == max) {
  44.            max_letters.push_back(it->first);
  45.        }
  46.    }
  47.   //打印输出max_letters数组中的值
  48.    for (int i = 0; i < max_letters.size(); i++) {
  49.        printf("%d ", max_letters[i]);
  50.    }
  51.    printf("\n");
  52.  
  53.    return 0;
  54. }
复制代码
代码分析

上述代码存在几处的错误,我们来表明一下:
1.输入语句发生错误:
  1. scanf("%s", arr);
复制代码
%s 读取碰到空格就结束了,以是无法读入整行句子。句子有空格的话,后面的内容根本读不到。
应改为:
  1. fgets(arr, sizeof(arr), stdin);
复制代码
2.英文字母个数,单词个数统计错误:
按照上面的写法, 会把非空格的字符都算进去,但题目要求只统计英文字母个数。 即 如果 s 是换行符 \n,也会被统计进去。
正确的改法应该是:
  1. if ( (s[i] >= 'A' && s[i] <= 'Z') || (s[i] >= 'a' && s[i] <= 'z') ) {
  2.    letter_num++;
  3. }
复制代码
或者用 isalpha(s)。 isalpha() 是标准C库函数,作用是判定字符是否为英文字母(A-Z,a-z)。
对于统计单词个数:你要使用上述的这个语句来统计单词个数,得先去掉开头和结尾的空格。
或者保举使用下列的做法:
  1. bool in_word = false;
  2. for (int i = 0; i < s.size(); i++) {
  3.    if (isalpha(s[i])) {
  4.        if (!in_word) {
  5.            word_num++;
  6.            in_word = true;
  7.        }
  8.    } else if (s[i] == ' ') {
  9.        in_word = false;
  10.    }
  11. }
复制代码
复制代码
正确代码

  1. #define  _CRT_SECURE_NO_WARNINGS
  2. #include<cstdio>
  3. #include <stdio.h>
  4. #include<string>
  5. #include<vector>
  6. #include<map>
  7. using namespace std;
  8. int main() {
  9.    //输入:一行字符串。仅有空格和英文字母构成。
  10.    char arr[1024];
  11.    string s;
  12.    fgets(arr, sizeof(arr), stdin);
  13.    s = arr;
  14.    //英文字母个数
  15.    int letter_num = 0;
  16.    //单词的个数
  17.    int word_num = 0;
  18.    map<char,int> myMap;
  19.    //处理
  20.    //统计并输出此句子英文字母,单词的个数
  21.    bool in_word = false;//标记是否在单词中
  22.    for (int i = 0; i < s.size(); i++) {
  23.        if (isalpha(s[i])) {
  24.            letter_num++;
  25.            //统一转成小写,再加入myMap
  26.            char ch = tolower(s[i]);
  27.            myMap[ch]++;
  28.            //再统计单词
  29.            if (!in_word) {
  30.                word_num++;
  31.                in_word = true;
  32.            }
  33.        }else if (s[i] == ' ') {
  34.            in_word = false;//遇到空格说明单词结束
  35.       }
  36.    }
  37.    //输出:英文字母的个数
  38.    printf("%d\n", letter_num);
  39.    //输出:单词的个数
  40.    printf("%d\n", word_num);
  41.    //输出:出现次数最多的字母
  42.    map<char,int>::iterator it;
  43.    //找到字母出现的最多次数
  44.    int max = 0;
  45.    for (it=myMap.begin(); it != myMap.end(); it++) {
  46.        if (it->second > max) {
  47.            max = it->second;
  48.        }
  49.    }
  50.    //找到值为max的所有键
  51.    vector<char>max_letters;
  52.    for (it = myMap.begin(); it != myMap.end(); it++) {
  53.        if (it->second == max) {
  54.            max_letters.push_back(it->first);
  55.        }
  56.    }
  57.   //打印输出max_letters数组中的值
  58.    for (int i = 0; i < max_letters.size(); i++) {
  59.        printf("%c ", max_letters[i]);
  60.    }
  61.    printf("\n");
  62.   //打印输出出现最多的字母的出现次数
  63.    printf("%d\n", max);
  64.    return 0;
  65. }
复制代码

浮点数加法

原作:

输入:有2行,分别表示两个加数num1 num2
输出: 一个小数部门不为0的浮点数
处理处罚: 求2个浮点数相加的和
思路:
我们要运算的数已经凌驾了浮点数精度,称此类问题为高精度盘算。
此题给的两个数都凌驾了float和double的精度,以是我们可以把他们表示为两个字符串,举行运算。
我们要做的实际上就是用字符串模拟小学时学的竖式盘算。
1)对齐:把小数点的位置对齐
2)先盘算右边的小数,即举行小数运算
3)再举行左边的整数,即举行整数运算
对于运算的过程:从右往左算,且盘算的是a+b+进位(carry)%10
对于整数的运算,由于两个加数的位数可能不一样,以是我们要实现i,j分别指向两个加数,我们运算的结束条件是,a没访问完或者b没访问完或者carry==1(即可能存在两个都访问完了,但还有进位的环境,比方11+99,在11和99的岗位都访问完了,还要向前再加一位)
  1. #define  _CRT_SECURE_NO_WARNINGS
  2. #include<cstdio>
  3. #include <stdio.h>
  4. #include<string>
  5. using namespace std;
  6. /*
  7. 参数:一个字符串a
  8. 返回值:a的整数部分
  9. 处理:提取a的整数部分
  10. */
  11. string GetInteger(string a) {
  12.    return a.substr(0, a.find('.'));
  13. }
  14. //提取a的小数部分
  15. string GetFraction(string a) {
  16.    return a.substr(a.find('.') + 1);
  17. }
  18. /*
  19. 处理:获取小数计算的结果,已经最终的进位
  20. 因为返回值只能返回一个,我们要两个结果,故我们都使用引用进行传递。
  21. */
  22. void FractionPlus(string& res, int& carry, string fa, string fb) {
  23.    int size = max(fa.size(), fb.size());
  24.    while (fa.size() < fb.size()) {
  25.        fa.push_back('0');
  26.    }
  27.    while (fb.size() < fa.size()) {
  28.        fb.push_back('0');
  29.    }
  30.    //开始运算
  31.    res.resize(size);//给res申请内存空间
  32.    carry = 0;
  33.    for (int i = size - 1; i >= 0; i--) {
  34.        //'0'='0'
  35.        //'3'='0'+'3'
  36.        if (fa[i] + fb[i] + carry - '0' > '9') {
  37.            res[i] = fa[i] + fb[i] +carry- '0' - 10;
  38.            carry = 1;
  39.        }
  40.        else {
  41.            res[i] = fa[i] + fb[i] + carry - '0';
  42.            carry = 0;
  43.        }
  44.    }
  45.    return;
  46. }
  47. /*
  48. 进行整数运算,整数加法运算不需要修改进位值,只需要获取小数运算得到的
  49. 进位值
  50. */
  51. void IntegerPlus(string& res, int carry, string ia,string ib) {
  52.    res.clear();
  53.    for (int i = ia.size() - 1, j = ib.size() - 1; i >= 0 || j >= 0 || carry == 1; --i, --j) {
  54.        //a,b都还没访问完
  55.        if (i >= 0 && j >= 0) {
  56.            if (ia[i] + ib[j] + carry - '0' > '9') {
  57.                //结果要插入到上一个结果的前面
  58.                res.insert(res.begin(), ia[i] + ib[j] + carry - '0' - 10);
  59.                carry = 1;
  60.            }
  61.            else {
  62.                res.insert(res.begin(), ia[i] + ib[j] + carry - '0');
  63.                carry = 0;
  64.            }
  65.            //只有a的情况          
  66.        }else if (i >= 0 &&j < 0) {
  67.            if (ia[i] + carry > '9') {
  68.                //结果要插入到上一个结果的前面
  69.                res.insert(res.begin(), ia[i] + carry - 10);
  70.                carry = 1;
  71.            }
  72.            else {
  73.                res.insert(res.begin(), ia[i] + carry);
  74.                carry = 0;
  75.            }
  76.        }else if (i < 0 && j >= 0) {//只有b的情况
  77.                        if (ib[j] + carry > '9') {
  78.                            //结果要插入到上一个结果的前面
  79.                            res.insert(res.begin(), ib[j] + carry - 10);
  80.                            carry = 1;
  81.                        }else {
  82.                            res.insert(res.begin(), ib[j] + carry);
  83.                            carry = 0;
  84.                         }
  85.         }else { //只有进位
  86.                            res.insert(res.begin(), '1');
  87.                            carry = 0;
  88.                    }
  89.                }
  90.            }
  91. int main() {
  92.    string a;
  93.    string b;
  94.    char arr1[1024];
  95.    char arr2[1024];
  96.    while (scanf("%s%s", arr1, arr2) != EOF) {
  97.        a = arr1;
  98.        b = arr2;
  99.        string ia = GetInteger(a);
  100.        string ib = GetInteger(b);
  101.        string fa = GetFraction(a);
  102.        string fb = GetFraction(b);
  103.        string fres;
  104.        int carry;
  105.        FractionPlus(fres, carry, fa, fb);
  106.        string ires;
  107.        IntegerPlus(ires, carry, ia, ib);
  108.        string result = ires + '.' + fres;
  109.        printf("%s\n", result.c_str());
  110.    }
  111.    return 0;
  112. }
复制代码




代码分析

以上代码有一些语法值得我们再次复习。
1.字符串操作
  1. a.find('.');//找到字符串中第一次出现 . 的位置,返回下标。如果找不到,返回 string::npos
  2. a.substr(0, pos)//从下标 0 开始,截取 pos 长度的子串
复制代码
2.max() 是 C++ 标准库 <algorithm > 中的函数,用来返回两个值中的较大值。
知识点

将大写字母转为小写字母的方式

用tolower() 或者使用ASCII码
tolower() 是 C 标准库 里的函数
  1. #include <cctype>
  2. char lower = tolower('A'); // 结果是 'a'
复制代码
在 ASCII 表中:


  • 大写字母 'A' 到 'Z' 的值是 65 ~ 90
  • 小写字母 'a' 到 'z' 的值是 97 ~ 122
  • 大小写之间的差值是 32
  1. if (ch >= 'A' && ch <= 'Z') {
  2.    ch += 32;
  3. }
复制代码
字符情势举行十进制运算的原理

如今我们想以字符情势举行十进制运算。
字符 '0' ~ '9' 在 ASCII 表中对应十进制数值 48~57。故 '3' + '6' = 51 + 54 = 105;在十进制运算中3 + 6 = 9;显然,9的ASCII码不是105,故我们不能简单的将两个字符相加来实现。那该怎么办?
==》由于字符和十进制数字的关系有字符 - '0' = 对应的十进制数字
如果你要对两个字符表示的数字相加(模拟竖式加法),你必要先把它们转换成数字再相加:
('3' - '0') + ('6' - '0') = 3 + 6 = 9
在上面的案例中,你可以看作 fa - '0' 得到数字,fb - '0' 得到数字,
然后数字相加,最后 + '0' 变回字符存进 res
以是我们可以直接归并表示为fa + fb + carry - '0'
另外为什么可以与'9'表示,由于fa + fb + carry - '0' 这个效果是字符情势的,而在字符表示下:最大个位数字是 '9'(ASCII 57),如果 这个效果大于'9',也就对应了数字运算中的效果大于9,也就是竖式加法里的“要进位”条件。


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

东湖之滨

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表