C Primer Plus第十一章编程练习第十一题详解

news2024/11/15 18:42:33

C Primer Plus第十一章第十一题详解

在这里插入图片描述

首先,分析一下要求以及如何对其进行实现,读入十个字符串或者读到文件结尾结束,然后提供一个含有5个选项的菜单分别以四种格式去打印字符串列表,以及退出,循环展示菜单,分别按照对应的格式去打印不同格式的字符串序列。首先我们应该创建一个展示菜单的函数:

void showMenu(void){
    printf("*****************************************************\n");
    printf("请输入您要选择的操作:\n");
    printf("1:打印原字符列表        2:以ASCII中的顺序打印字符串\n");
    printf("3:按长度递增顺序打印     4:按第一个单词的长度打印   \n");
    printf("5:退出\n");
    printf("*****************************************************\n");
}

上面的函数简单的创建了一个菜单,只要循环调用该函数,就可以多次打印出这个菜单。接下来,既然有菜单了,那么我们就要获取用户选择菜单上的值,以确定接下来要根据那个格式去打印字符串序列,所以我们再写一个获取操作参数的函数:

int getCz(void){
    int input;
    while (scanf("%d",&input)!=1||input<1||input>5)
    {
        printf("您输入的值不合法,请重新输入!!\n");
    }
    return input;
}

上面这个函数对用户选择的操作参数进行获取并简单的对其进行校验,以免混入其他数据,只要在展示菜单之后,调用这一个函数,就可以获取用户选择的操作了。接下来,我们就可以依次实现四种不同的打印格式的函数了,首先是第一种打印格式–源字符串列表,将我们获取到的字符串列表数组按照循环依次打印展示即可,完整函数代码如下 :

void showa(char (* a)[SIZE], int n){
    printf("源字符串列表:\n");
    for (int i = 0; i <= n; i++){
        fputs(*(a+i), stdout);
    }
}

然后是第二个打印格式–按照ASCII码顺序打印,看似很简单,实际上实现这个功能并不是很容易,经过好多次的调试之后,才得到目前这一版可用的函数。因为后续有可能还会展示原格式,所以我们排序的时候最好不要更改原格式,我们在函数里面创建一个用于存储该格式的数组。说到这呢,我们其实还可以优化一下,因为程序是循环获取操作参数,有可能反复调用同一参数,我们可以再创建几个参数去记录此种格式是否已经被排序,另外将这几种格式的记录数组放置到几个小函数的外面,比如主函数中。如果已经排序的话,直接展示排序之后的数组即可,这个我们就先不实现了。我们将排序之后的记录数组放到小函数中,无论是否排序过,都进行新一次操作。说回这个函数,我们首先将原数据数组拷贝到函数独有的数组中,再通过strcmp函数对其进行机器排序,再然后调换顺序,进行打印。该打印格式的函数如下:

void showb(char (* a)[SIZE], int n){
    char arrb[ROWS][SIZE];
    char (* acb)[SIZE] = arrb;
    char ac[SIZE];
    for (int i = 0; i <= n; i++){
        strcpy(*(acb+i),*(a+i));
    }
    for (int i = 0; i < n; i++){
        for (int j = i+1; j <= n; j++){
            if (strcmp(*(acb+i),*(acb+j))>0){
                strcpy(ac,*(acb+i));
                strcpy(*(acb+i),*(acb+j));
                strcpy(*(acb+j),ac);
            }   
        }   
    }
    printf("ASCII顺序列表:\n");
    for (int i = 0; i <= n; i++){
        fputs(*(acb+i), stdout);
    }
}

同样,类似的,实现第三个打印格式,按照长度递增顺序打印字符串,也就是说要先根据字符串长度从小到大进行排序,大体上和上面的差不多,略有不同的一点是,我们利用strlen函数去看字符串长度,该函数的完整代码如下:

void showc(char (* a)[SIZE], int n){
    char arrc[ROWS][SIZE];
    char (* acc)[SIZE] = arrc;
    char ac[SIZE];
    for (int i = 0; i <= n; i++){
        strcpy(*(acc+i),*(a+i));
    }
    for (int i = 0; i < n; i++){
        for (int j = i+1; j <= n; j++){
            if (strlen(*(acc+i)) > strlen(*(acc+j))){
                strcpy(ac,*(acc+i));
                strcpy(*(acc+i),*(acc+j));
                strcpy(*(acc+j),ac);
            }   
        }   
    }
    printf("长度递增顺序列表:\n");
    for (int i = 0; i <= n; i++){
        fputs(*(acc+i), stdout);
    }
}

最后是按照字符串中第一个单词的长度打印字符串,所以我们就要有一个去计算首单词长度的函数,他没说是升序还是降序,我们按照默认升序进行实现。因为没有标准函数去计算首单词的长度,所以先去搞一个计算首单词的长度的函数。搞一个参数,记录是没进入单词,还是首单词,还是已经出首单词。然后循环去看每一个进入循环的字符,然后记录首单词长度并返回。该函数如下:

int jiSuanWord(char * a){
    int length = 0;
    int flag = 0; 
    while (*a != '\0' && flag != 2){
        if (isspace(*a) && flag == 0){
            continue;
        }else if (!isspace(*a) && flag == 0){
            flag = 1;
            length++;
        }else if (!isspace(*a) && flag == 1){
            length++;
        }else if (isspace(*a) && flag == 1){
            flag = 2;
        }
        a++;
    }
    return length;
}

最后,我们再实现第四种打印格式的函数,大体格式同上面的差不多,只是计算首字母长度使用我们自己写的函数,该函数完整代码如下:

void showd(char (* a)[SIZE], int n){
    char arrd[ROWS][SIZE];
    char (* acd)[SIZE] = arrd;
    char ac[SIZE];
    for (int i = 0; i <= n; i++){
        strcpy(*(acd+i),*(a+i));
    }
    for (int i = 0; i < n; i++){
        for (int j = i+1; j <= n; j++){
            if (jiSuanWord(*(acd+i)) > jiSuanWord(*(acd+j))){
                strcpy(ac,*(acd+i));
                strcpy(*(acd+i),*(acd+j));
                strcpy(*(acd+j),ac);
            }   
        }   
    }
    printf("首单词长度递增顺序列表:\n");
    for (int i = 0; i <= n; i++){
        fputs(*(acd+i), stdout);
    }
}

最后,将上述的函数在主函数合适的位置进行调用,得到下面的主函数:

int main(){
    char arr[ROWS][SIZE];
    int i = 0;
    int cz;
    printf("请输入需要处理的字符串:\n");
    while (fgets(*(arr+i),SIZE-1,stdin) != NULL && i<ROWS-1){
        i++;
        printf("请再次输入需要处理的字符串(输入文件结尾结束):\n");
    }
    showMenu();
    cz = getCz();
    while (cz != 5){
        switch (cz)
        {
        case 1:
            showa(arr, i);
            break;
        case 2:
            showb(arr, i);
            break;
        case 3:
            showc(arr, i);
            break;
        case 4:
            showd(arr, i);
            break;
            
        default:
            break;
        }
        showMenu();
        cz = getCz();
    }
    printf("Done!!!\n");
    getchar();
    return 0;
}

最后,该题完整程序代码以及运行结果如下:

#include<stdio.h>
#include<string.h>
#include<ctype.h>
#define ROWS 3
#define SIZE 100
void showMenu(void);
int getCz(void);
void showa(char (* a)[SIZE], int n);
void showb(char (* a)[SIZE], int n);
void showc(char (* a)[SIZE], int n);
int jiSuanWord(char * a);
void showd(char (* a)[SIZE], int n);
int main(){
    char arr[ROWS][SIZE];
    int i = 0;
    int cz;
    printf("请输入需要处理的字符串:\n");
    while (fgets(*(arr+i),SIZE-1,stdin) != NULL && i<ROWS-1){
        i++;
        printf("请再次输入需要处理的字符串(输入文件结尾结束):\n");
    }
    showMenu();
    cz = getCz();
    while (cz != 5){
        switch (cz)
        {
        case 1:
            showa(arr, i);
            break;
        case 2:
            showb(arr, i);
            break;
        case 3:
            showc(arr, i);
            break;
        case 4:
            showd(arr, i);
            break;
            
        default:
            break;
        }
        showMenu();
        cz = getCz();
    }
    printf("Done!!!\n");
    getchar();
    return 0;
}
void showMenu(void){
    printf("*****************************************************\n");
    printf("请输入您要选择的操作:\n");
    printf("1:打印原字符列表        2:以ASCII中的顺序打印字符串\n");
    printf("3:按长度递增顺序打印     4:按第一个单词的长度打印   \n");
    printf("5:退出\n");
    printf("*****************************************************\n");
}
int getCz(void){
    int input;
    while (scanf("%d",&input)!=1||input<1||input>5)
    {
        printf("您输入的值不合法,请重新输入!!\n");
    }
    return input;
}
void showa(char (* a)[SIZE], int n){
    printf("源字符串列表:\n");
    for (int i = 0; i <= n; i++){
        fputs(*(a+i), stdout);
    }
}
void showb(char (* a)[SIZE], int n){
    char arrb[ROWS][SIZE];
    char (* acb)[SIZE] = arrb;
    char ac[SIZE];
    for (int i = 0; i <= n; i++){
        strcpy(*(acb+i),*(a+i));
    }
    for (int i = 0; i < n; i++){
        for (int j = i+1; j <= n; j++){
            if (strcmp(*(acb+i),*(acb+j))>0){
                strcpy(ac,*(acb+i));
                strcpy(*(acb+i),*(acb+j));
                strcpy(*(acb+j),ac);
            }   
        }   
    }
    printf("ASCII顺序列表:\n");
    for (int i = 0; i <= n; i++){
        fputs(*(acb+i), stdout);
    }
}
void showc(char (* a)[SIZE], int n){
    char arrc[ROWS][SIZE];
    char (* acc)[SIZE] = arrc;
    char ac[SIZE];
    for (int i = 0; i <= n; i++){
        strcpy(*(acc+i),*(a+i));
    }
    for (int i = 0; i < n; i++){
        for (int j = i+1; j <= n; j++){
            if (strlen(*(acc+i)) > strlen(*(acc+j))){
                strcpy(ac,*(acc+i));
                strcpy(*(acc+i),*(acc+j));
                strcpy(*(acc+j),ac);
            }   
        }   
    }
    printf("长度递增顺序列表:\n");
    for (int i = 0; i <= n; i++){
        fputs(*(acc+i), stdout);
    }
}
int jiSuanWord(char * a){
    int length = 0;
    int flag = 0; 
    while (*a != '\0' && flag != 2){
        if (isspace(*a) && flag == 0){
            continue;
        }else if (!isspace(*a) && flag == 0){
            flag = 1;
            length++;
        }else if (!isspace(*a) && flag == 1){
            length++;
        }else if (isspace(*a) && flag == 1){
            flag = 2;
        }
        a++;
    }
    return length;
}
void showd(char (* a)[SIZE], int n){
    char arrd[ROWS][SIZE];
    char (* acd)[SIZE] = arrd;
    char ac[SIZE];
    for (int i = 0; i <= n; i++){
        strcpy(*(acd+i),*(a+i));
    }
    for (int i = 0; i < n; i++){
        for (int j = i+1; j <= n; j++){
            if (jiSuanWord(*(acd+i)) > jiSuanWord(*(acd+j))){
                strcpy(ac,*(acd+i));
                strcpy(*(acd+i),*(acd+j));
                strcpy(*(acd+j),ac);
            }   
        }   
    }
    printf("首单词长度递增顺序列表:\n");
    for (int i = 0; i <= n; i++){
        fputs(*(acd+i), stdout);
    }
}

在这里插入图片描述
在这里插入图片描述

需要对本题说明的是,题目要求是十个字符串组成的字符串列表,但是我在测试程序的时候一直用的是3个,因为好输入,也好看要求的格式实现了吗,屏幕也放得下。所以如果你想看一下十个字符串的效果,或者想试一下EOF的话,就将宏定义SIZE改为10,就可以对十个字符串的序列进行上述的排序了。感兴趣的可以自行去试验一下。因为这一个问题相较于其他的,比较综合,用到了不少前面所学的内容,所以详细分析一下。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1993857.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

leetcode-二叉树oj题-101.对称二叉树,572.另一颗子树,110.平衡二叉树-c

a、题目链接 101.对称二叉树 572.另一棵树的子树 110.平衡二叉树 一、题目讲解 101.对称二叉树 1、题目 给你一个二叉树的根节点 root &#xff0c; 检查它是否轴对称。 示例1&#xff1a; 输入&#xff1a;root [1,2,2,3,4,4,3 ] 输出&#xff1a;true 示例2&#xff1…

SpringMVC学习笔记---带你快速入门和复习

一、初识SpringMVC 1.1、什么是SpringMVC 1.1.1、什么是MVC MVC是一种软件架构模式&#xff08;是一种软件架构设计思想&#xff0c;不止Java开发中用到&#xff0c;其它语言也需要用到&#xff09;&#xff0c;它将应用分为三块&#xff1a; M&#xff1a;Model&#xff0…

PostgreSQL的学习心得和知识总结(一百五十)|[performance]更好地处理冗余 IS [NOT] NULL 限定符

目录结构 注&#xff1a;提前言明 本文借鉴了以下博主、书籍或网站的内容&#xff0c;其列表如下&#xff1a; 1、参考书籍&#xff1a;《PostgreSQL数据库内核分析》 2、参考书籍&#xff1a;《数据库事务处理的艺术&#xff1a;事务管理与并发控制》 3、PostgreSQL数据库仓库…

书生大模型实战营-基础关卡-1-书生大模型全链路开源体系

开源一周年 性能天梯 2.5能力概览 核心技术思路-模型能力飞轮 核心技术思路-高质量合成数据 大海捞针实验-全绿 解决复杂问题 开源模型谱系 开源生态 数据处理 预训练工具 微调工具 开源评测 部署工具 RAG

鸿蒙AI功能开发【hiai引擎框架-分词、实体抽取】 自然语言理解服务

介绍 本示例展示了使用hiai引擎框架提供的基于自然语言处理服务的分词、实体抽取功能。 本示例模拟了在应用里&#xff0c;输入一段文字&#xff0c;调用分词、实体抽取能力后得到的结果。 需要使用hiai引擎框架通用文字识别接口hms.ai.nlp.textProcessing.d.ts。 效果预览…

03 Canal HA原理及安装

1. Canal HA原理 Canal一般用于实时同步数据场景&#xff0c;那么对于实时场景HA显得尤为重要&#xff0c;Canal支持HA搭建&#xff0c;canal的HA分为两部分&#xff0c;canal server和canal client分别有对应的HA实现。大数据中使用Canal同步数据一般同步到Kafka中&#xff0…

最新虚拟试衣框架IMAGDressing模型部署

IMAGDressing是一个全新的虚拟试衣框架&#xff0c;它由南京理工大学、武汉理工大学、腾讯AI实验室和南京大学共同开发。 该项目旨在通过先进的技术提升消费者的在线购物体验&#xff0c;特别是通过虚拟试穿技术&#xff08;VTON&#xff09;来实现逼真的服装效果。 IMAGDres…

QT界面布局

目录 界面布局 静态布局 动态布局 界面布局 静态布局 静态布局指的是在设计时固定每个控件&#xff08;如按钮、文本框等&#xff09;的位置和大小&#xff0c;无论窗口大小如何变化&#xff0c;控件的位置和大小都不会改变。 动态布局 动态布局指的是控件的位置和大小可…

【解压既玩】PS3模拟器v0.0.32+战神3+战神升天+各存档 整合包 ,完美不死机,没有BUG,旷世神作,强力推荐

战神3是圣莫尼卡公司的大作&#xff0c;PS3 上必玩的游戏之一。 本文收集了战神3和升天两作&#xff0c;附存档&#xff0c;完美不死机&#xff0c;没有BUG&#xff0c;强烈推荐。 解压即玩。 立即下载&#xff1a;【chumenx.com】【解压既玩】PS3模拟器v0.0.32战神3战神升天…

VisionPro二次开发学习笔记9-使用 CogRecordDisplay控件

使用 CogRecordDisplay控件 这个示例展示了如何使用 CogRecordDisplay 在表单上显示 Blob Tool 的 LastRunRecord 图形。 它还演示了如何通过 BlobTool 的 LastRunRecordEnable 属性有选择性地启用或禁用不同的图形特性。这个模式可以应用于所有 VisionPro 工具。 具体步骤如…

实验25.创建文件

已完成实验 已完成实验链接 简介 实验 25. 创建文件 总结 inode 就是文件 i_no 就是 inode 号i_sectors 是块地址数组,表示这个文件的内容是那些块构成的.如果是文件,那么块的内容是文件的内容如果是目录,那么这些块的内容是一个个目录项 dir_entry 目录项 是目录文件的…

思科CCIE最新考证流程

CCIE CCIE&#xff0c;全称Cisco Certified Internetwork Expert,是美国Cisco公司于1993年开始推出的专家级认证考试。被全球公认为IT业最权威的认证&#xff0c;是全球Internetworking领域中最顶级的认证证书。 CCIE方向 CCIE主要有六大方向&#xff1a;企业基础架构Enterp…

JDK源码——Atomic包(一)

包介绍 JDK的atomic包提供了一组原子类&#xff0c;用于多线程环境中的原子操作&#xff0c;确保线程安全和高性能。 Atomic包是Java在并发编程中的重要工具&#xff0c;它利用CAS&#xff08;Compare-And-Swap&#xff09;机制保证操作的原子性&#xff0c;同时避免了重量级…

3.Redis数据类型(二)

LIST List 是一个简单的双向链表&#xff0c;支持从两端进行插入和删除操作。 常用命令&#xff1a; lpush/rpush/lrange lpush 插入一个或多个元素到列表的左端。 rpush 插入一个或多个元素到列表的右端。 lrange key start stop 获取元素&#xff08;前闭后闭&#xff0…

构建可刷卡手持终端,思路与必备元素剖析-SAAS 本地化及未来之窗行业应用跨平台架构

构建可刷卡手持终端&#xff0c;思路与必备元素剖析 一、终端开发必要性 1.终端携带方便&#xff0c;适合空间小&#xff0c;外出 2.可供电&#xff0c;外带设备比较方便 3.大多数终端可以不需要网络独立使用&#xff0c;适合特殊场景 二、终端软件爱基本功能 1.便捷的终端…

Java重修笔记 第三十天 异常

异常的分类 1. Error&#xff08;错误&#xff09;&#xff1a;Java虚拟机无法解决的致命问题&#xff0c;例如StackOverflowError[栈溢出] 2. Exception&#xff08;异常&#xff09;&#xff1a;其它因编程错误或偶然的外在因素导致的一般性问题&#xff0c;可以使用针对性…

【iOS多线程(四)】线程安全+13种锁

线程安全13种锁 线程安全1. 为什么要线程安全出现线程安全的原理解决方法 2. 自旋锁和互斥锁自旋锁(Spin lock)互斥锁两种锁的加锁原理对比两种锁的应用 3. 13种锁1. OSSpinLock (已弃用&#xff09;2. os_unfair_lock3.pthread_mutex 4. NSLock5. NSRecursiveLock6. NSConditi…

C++ IOStream

IOStream 类流特性 不可赋值和复制缓冲重载了<< >> 状态位 示例 状态位操作函数coutcin getget(s,n)/get(s,n,d):getline otherif(!fs)/while(cin) operator void*()与 operator!()代码示例 File Stream open 函数 文件打开方式 文件读写 读写接口 一次读一个字符…

SpringBoot学习之EasyExcel解析合并单元格(三十九)

本解析主要采用反射来修改EasyExcel 返回的默认数据结构实现。 一、待解析表格 二、依赖 全部pom.xml文件如下,仅作参考: <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLo…

LLM - 使用 HuggingFace + Ollama 部署最新大模型 (GGUF 格式 与 Llama 3.1)

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/141028040 免责声明&#xff1a;本文来源于个人知识与公开资料&#xff0c;仅用于学术交流&#xff0c;欢迎讨论&#xff0c;不支持转载。 Ollama…