CPrimerPlus第11章第10题

题目:

编写一个程序,读取输入,直到读入了10个字符串或遇到EOF,由二者中最先被满足的那个终止读取过程。这个程序可以为用户提供一个有5个选项的菜单:输出初始字符串列表、按ASCII顺序输出字符串、按长度递增顺序输出字符串、按字符串中第一个单词的长度输出字符串和退出。菜单可以循环,直到用户输入退出请求。当然,程序要能真正完成菜单中的各项功能。



1.先完成第一个部分,读入字符串。

打算使用指针数组来储存字符串们,先定义并初始化指针字符串(指针需要初始化,指针数组也是,担心成为野指针,所以刚开始全部指向NULL,发现后来就用不了,所以还是用malloc分配一下内存给指针吧)。

    char *str[10];
    for(i=0; i<10; i++)
        str[i] = (char *)malloc(200 * sizeof(char));

按要求读入字符串们,遇到EOF或者读入了10个字符串就停止读入。结果不行,因为函数gets(ptr)如果发现了EOF就返回NULL,不会把EOF读入并让指针ptr指向的(比方说我吩咐了gets()去读EOF符号,他碰到了EOF符号并没有读入,而是跑回来跟我说,臣妾做不到啊~)。

    while(j<10  &&  (*str[j]!=EOF))
    {
        gets(str[j]);
        j++;
    }

所以修改while()中的判断条件,且修改后的while()条件中已经包含了gets()函数,每次判断时已经执行了一遍,所以下面循环中的gets()要删除,只留下j++就好了。

    while( (j<10) && (gets(str[j]) != NULL))//(*str[j]!=EOF)这个作为判断是不行滴
        j++;

2.设计好主函数的思路,分析逻辑,编写主函数部分。主要就是用if和else的组合给选择分类,要注意选择超出选项范围的情况。代码如下

while (scanf("%c",&choice) == 1)
    {
        if(choice < ‘a‘ || choice > ‘e‘)
            printf("choice must be between ‘a‘ and ‘e‘\n");
        if(choice == ‘e‘)
            exit(1);
        else
        {
            if(choice == ‘a‘)
                print_orig(str);
            if(choice == ‘b‘)
                print_as_ascii(str);
            if(choice == ‘c‘)
                print_as_strlen(str);
            if(choice == ‘d‘)
                print_as_1strlen(str);
        }
        getchar();    //清除enter键确认输入时带来的换行字符
        puts("make your choice(a, b, c, d, e):");
        print_table();
    }
    puts("fail reading the choice, good bye!");

    return 0;
}

3.分别编写各个子函数

3.0 打印表头,这个简单,就是printf函数即可

/*******************************打印表头***************************/
void print_table(void)
{
    printf("a) print original text              b) print lines in order of ASCII\n");
    printf("c) print lines in order of strlen   d) print lines in order of first word‘s len\n");
    printf("e) exit\n");
}

3.1 打印原来的字符串们,由于刚开始就考虑使用指针数组,因此挨个指针进行打印就可以了(循环puts(str[i]几次即可))

/**************************打印原字符串们**************************/
void print_orig(char *str[])
{
    int i;
    for(i=0; i<lines; i++)
        puts(str[i]);
}

3.2 按照字符串ascii码大小来打印字符串们,需要对字符串们进行排序,本章讲解了选择排序的算法,在这里正好使用上,我之前的博客也提到了。代码如下,注意注释中的注意。不过经过排序后指针变换了指向的位置,所以执行完选择排序后再想打印出原字符串们,就不能用指针了。我能想到的办法就是再用一组指针,指向这些字符串们,变一组指针,不变另一组指针,打印原字符串们时就用不变的指针数组,选择排序时就用变得指针数组(时间原因自己没有弄了)。

/*********************按ascii码打印字符串们*************************/
void print_as_ascii(char *str[])
{
    int i,j;
    char * p_temp;
    for(i=0; i<lines; i++)
    {
        for(j=i+1; j<lines; j++)
        {
            if(ascii_num(str[i]) > ascii_num(str[j]))    //参考答案是用strcmp()函数来比较字符串的ascii码值大小的,我自己不嫌麻烦又写了个函数(其实是没想到,呜呜~~)
            {
                p_temp = str[i];    //比的是ascii_num(str[i])和ascii_num(str[j]),调换的是str[i]和str[j],这里有映射关系!!映射问题困扰了我半天
                str[i] = str[j];
                str[j] = p_temp;
            }
        }
    }
    print_orig(str);
}

3.3 按照字符串长度来输出字符串们,和上面的套路其实都一样了,只是比较时使用strlen()函数即可。代码如下

/**********************按字符串长度打印字符串们*********************/
void print_as_strlen(char *str[])
{
    int i,j;
    char * p_temp;
    for(i=0; i<lines; i++)
    {
        for(j=i+1; j<lines; j++)
        {
            if(strlen(str[i]) > strlen(str[j]))
            {
                p_temp = str[i];
                str[i] = str[j];
                str[j] = p_temp;
            }
        }
    }
    print_orig(str);
}

3.4 按照字符串中第一个单词的长度来排序并输出字符串们,同上的套路,只是比较时比较首单词的长度而已。我没有仔细考虑具体情况,简单写了个函数(开头的就是空格的话就算0),当然考虑清楚写的缜密些最好了,只是这里我想自己毕竟出于练习的目的,不必花太多时间(其实也写了两三天了,呜呜~,心里烦他了~呜呜~)。

/********************按字符串中首个单词长度打印*********************/
void print_as_1strlen(char *str[])
{
    int i,j;
    char *p_temp;
    for(i=0; i<lines; i++)
    {
        for(j=i+1; j<lines; j++)
        {
            if(first_len(str[i]) > first_len(str[j]))
            {
                p_temp = str[i];
                str[i] = str[j];
                str[j] = p_temp;
            }
        }
    }
    print_orig(str);
}

3.5 在3.2和3.4中自己有写两个简单的小程序,分别计算ascii码值和首单词长度,代码如下(随便写的,不缜密)

int ascii_num(char * p)    //计算一个字符串的ascii码值
{
    int i,asciinum = 0;
    for(i=0; *(p+i)!=‘\0‘; i++)
        asciinum+=*(p+i);
    return asciinum;
}

int first_len(char *p)    //计算一个字符串中首单词的长度
{
    int i;
    for(i=0; *(p+i)!=‘ ‘; i++);
    return i;
}

4.总结

参考答案中使用了二维数组和指针数组,把输入读入二维数组的指针,再用指针数组分别指向各个字符串,算是备份好了原文件,然后折腾指针也不怕损坏原文件的顺序什么的吧。这一点值得学习。参考答案中的选择排序在实现时基本与我的差不多;主函数中没有用if—else组合,而是用的switch—case组合;调用了库函数strcmp(),isalpha(),不浪费资源啊。

经过调试算是能完成任务了吧,但是问题还是有滴,所以我想还是在程序开头位置作好说明,毕竟如果再回头看时能方便回忆和理清思路,尤其是程序稍微有点复杂时(这是我自己编的比较长的程序了,可见自己有多水了。不过路漫漫其修远兮,自己慢慢努力慢慢完善自己吧,加油^_^)。

 
时间: 2024-10-13 00:59:20

CPrimerPlus第11章第10题的相关文章

外部排序-第11章-《数据结构题集》习题解析-严蔚敏吴伟民版

习题集解析部分 第11章 外部排序 ——<数据结构题集>-严蔚敏.吴伟民版        源码使用说明  链接??? <数据结构-C语言版>(严蔚敏,吴伟民版)课本源码+习题集解析使用说明        课本源码合辑  链接??? <数据结构>课本源码合辑        习题集全解析  链接??? <数据结构题集>习题解析合辑       相关测试数据下载  链接? 数据包       本习题文档的存放目录:数据结构\▼配套习题解析\▼11 外部排序    

内部排序-第10章-《数据结构题集》习题解析-严蔚敏吴伟民版

//**留坑待填**// 一.基础知识题 10.1?以关键码序列(503,087,512,061,908,170,897,275,653,426)为例,手工执行以下排序算法,写出每一趟排序结束时的关键码状态: (1)直接插入排序:                            (2)希尔排序(增量d[1]=5): (3)快速排序:                                  (4)堆排序: (5)归并排序:                              

《Cracking the Coding Interview》——第17章:普通题——题目10

2014-04-28 23:54 题目:XML文件的冗余度很大,主要在于尖括号里的字段名.按照书上给定的方式进行压缩. 解法:这题我居然忘做了,只写了一句话的注解.用python能够相对方便地实现,因为有直接的XML工具可以调用.书上的那种要求应该是符合前序遍历规则. 代码: 1 # 17.10 Parse an XML file, and try to save some space by mapping every item name to an integer index. 2 # Ans

3.26日第六次作业,第10章质量,11章人力

3.26日 第六次作业,第10章质量,11章人力 1.质量管理基本原则   以实用为核心的多元要求.系统工程.职工参与管理.管理层和第一把手重视.保护消费者权益.面向国际市场. 2.质量管理的目标顾客满意度.预防胜于检查.各阶段内的过程.   质量管理既重视结果也重视过程   实施组织主动采纳的质量改进措施(如全面质量管理.持续改进等) 3.质量管理的主要活动有哪些项目的质量管理可以分解为质量策划.质量保证与质量控制三个过程.质量策划是指确定与项目相关的质量标准,并决定如何达到这些质量标准.质量

鸟哥Linux私房菜知识点总结10到11章

最近翻看了一本<鸟哥的Linux私房菜>.这是一本基础的书,万丈高楼平地起,会的不多但可以学.这是我整理的一些知识点,虽然很基础.希望和大家共同交流. 第10章 vim程序编辑器 按键说明: /word       向下寻找一个名称为word的字符串 ?word 向上寻找一个名为woed的字符串 ndd          删除光标所在的向下的n行 nyy         复制光标所在的向下的n行 j         将光标所在行与下一行的数据结合成同一行 u         复原前一个操作 [

Rspec: everyday-rspec实操: 第10章测试其他功能,第11章TDD

10.测试文件上传 作者推荐的Paperclip,官方维护组已经不推荐使用deprecated. 推荐使用rails自带的 ActiveStorage. Active Storage: 推进文件上传到云存储,并附加这些文件到Active Record object.它 和本地驱动服务一起用于开发和测试.也支持反射文件到附属服务作为备份backups and migrations. http://guides.rubyonrails.org/active_storage_overview.html

10章、11章

一.典型用户和典型场景 Visual Studio的经典用户 怎样定义典型用户 从典型用户到场景 用例 规格说明书 功能说明书 定义好相关的概念 规范好一些假设 避免一些误解,界定一些边界条件 描述主流的用户/软件交互步骤 一些好的功能还会有副作用 服务质量的说明 功能驱动的设计 构造总体模型 构造功能列表 制定开发计划 功能设计阶段 实现具体功能 11章 分析和设计方法 图形建模和分析方法 表达实体和实体之间的关系 表达数据的流动 表达控制流 统一的表达方式 其他设计方法 形式化的方法 文学化

《Cracking the Coding Interview》——第17章:普通题——题目13

2014-04-29 00:15 题目:将二叉搜索树展开成一个双向链表,要求这个链表仍是有序的,而且不能另外分配对象,就地完成. 解法:Leetcode上也有,递归解法. 代码: 1 // 17.13 Flatten a binary search tree into a doubly linked list by inorder traversal order. 2 // Use postorder traversal to do the flattening job. 3 #include

《Cracking the Coding Interview》——第17章:普通题——题目14

2014-04-29 00:20 题目:给定一个长字符串,和一个词典.如果允许你将长串分割成若干个片段,可能会存在某些片段在词典里查不到,有些则查得到.请设计算法进行分词,使得查不到的片段个数最少. 解法:用空间换取时间的动态规划算法,首先用O(n^2)的时间判断每一个片段是否在字典里.这个过程其实可以通过字典树来进行加速,时间上能优化一个阶,不过我没写,偷懒用<unordered_set>代表了字典.之后通过O(n)时间的动态规划,dp[i]表示当前位置的查不到的片段的最少个数.对于懂代码的