c modern approach chapter 17 中简单的复习

2023-05-16

 一、程序remind.c用动态内存实现

1.先回顾13.5中remind.c的实现,如下是自己看书以及自己的体会写成的程序

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>

#define MSG_LEN 60
#define MAX_REMIND 50

int read_message(char msg_str[],int n);

int main(void)
{
int i,j,num_remind = 0,day;   //这里不能忘记num_remind的初始值
char day_str[3],msg_str[MSG_LEN + 1],*reminders[MAX_REMIND];

for(;;)
{
	if(num_remind == MAX_REMIND)
		{ 
		printf("-- No space left-- \n");
			break;
		}
	printf("Enter day and remind: ");
	scanf("%2d",&day);
	
	if(day == 0)
	{
		break;
	}
	
	sprintf(day_str,"%2d",day);
	
	read_message(msg_str,MSG_LEN);

	//查找新提醒的合适的插入位置
	for(i = 0;i < num_remind; ++ i)
	{
		if(strcmp(day_str,reminders[i]) < 0)
		{
			break;
		}
	}

	//移动i后的提醒
	for(j = num_remind; j > i; -- j)
		{
			reminders[j] = reminders[j - 1];	
		}
	reminders[i] = malloc(strlen(msg_str) + 4);

	//分配内存后,必须检测是否分配成功,否则程序会出现不可预料的结果
	if(reminders[i] == NULL)
		{
			printf("-- No space left --\n");
			exit(EXIT_FAILURE);
		}
	strcpy(reminders[i],day_str);
	strcat(reminders[i]," ");
	strcat(reminders[i],msg_str);

	++ num_remind;
	
}
printf("Day Reminder\n");
for(i = 0;i < num_remind; ++ i)
	{
	printf("%s\n",reminders[i]);
	}

//释放动态分配内存
for(i = 0;i != num_remind; ++ i)
	{
	free(reminders[i]);
	}
	return 0;
}

int read_message(char msg_str[],int n)
{
char ch;
int  i = 0;
while(isspace(ch = getchar()))
	;

while(ch != '\n' && i < n)
	{
	msg_str[i ++] = ch;
	ch = getchar();	
	}

msg_str[i] = '\0';

	return i;
}

运行结果:

Enter day and reminders:  24 Susan's birthday
Enter day and reminders:  5 6:00 - Dinner with Marge and Russ
Enter day and reminders:  26 Movie - "Chinatown"
Enter day and reminders:  7 10:30 - Dental appointment
Enter day and reminders:  12 Movie - "Dazed and Confused"
Enter day and reminders:  5 Saturday class
Enter day and reminders:  12 Saturday class
Enter day and reminders:  0 
Day Reminder
  5 Saturday class
  5 6:00 - Dinner with Marge and Russ
  7 10:30 - Dental appointment
 12 Saturday class
 12 Movie - "Dazed and Confused"
 24 Susan's birthday
 26 Movie - "Chinatown"

下面是自己的写的dynamic storage版本的:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>

#define MSG_LEN 60
#define MAX_REMIND 50

int read_message(char msg_str[],int n);

int main(void)
{
int i,j,num_remind = 0,day;   //这里不能忘记num_remind的初始值
char day_str[3],msg_str[MSG_LEN + 1],*reminders[MAX_REMIND];

for(;;)
{
	printf("Enter day and remind: ");
	scanf("%2d",&day);
	
	if(day == 0)
	{
		break;
	}
	
	sprintf(day_str,"%2d",day);
	
	read_message(msg_str,MSG_LEN);

	//查找新提醒的合适的插入位置
	for(i = 0;i < num_remind; ++ i)
	{
		if(strcmp(day_str,reminders[i]) < 0)
		{
			break;
		}
	}

	//移动i后的提醒
	for(j = num_remind; j > i; -- j)
		{
			reminders[j] = reminders[j - 1];	
		}
	reminders[i] = malloc(strlen(msg_str) + 4);

	//分配内存后,必须检测是否分配成功,否则程序会出现不可预料的结果
	if(reminders[i] == NULL)
		{
			printf("-- No space left --\n");
			exit(EXIT_FAILURE);
		}
	strcpy(reminders[i],day_str);
	strcat(reminders[i]," ");
	strcat(reminders[i],msg_str);

	++ num_remind;
	
}
printf("Day Reminder\n");
for(i = 0;i < num_remind; ++ i)
	{
	printf("%s\n",reminders[i]);
	}

//释放动态分配内存
for(i = 0;i != num_remind; ++ i)
	{
	free(reminders[i]);
	}
	return 0;
}

int read_message(char msg_str[],int n)
{
char ch;
int  i = 0;
while(isspace(ch = getchar()))
	;

while(ch != '\n' && i < n)
	{
	msg_str[i ++] = ch;
	ch = getchar();	
	}

msg_str[i] = '\0';

	return i;
}

运行结果:

Enter day and remind: 12 j89adfjia9psdfjasdf 
Enter day and remind: 23 jiasdmfioasdf 
Enter day and remind: 4 ajiosdfmiopasdmf asdf
Enter day and remind: 56 jiasmdfio;asdf asdf
Enter day and remind: 13 jioasmdf;ioasdf asdf
Enter day and remind: 2 jiouasdnmfio;asdf as
Enter day and remind: 0
Day Reminder
 2 jiouasdnmfio;asdf as
 4 ajiosdfmiopasdmf asdf
12 j89adfjia9psdfjasdf 
13 jioasmdf;ioasdf asdf
23 jiasdmfioasdf 
56 jiasmdfio;asdf asdf

下面自己第一次复习动态分配内存建立链表的一个例子?一编译就错了?错在哪里了?

找到答案了,原来是把问面名给弄错了。c文件的后缀是.c,如果写成c++,gcc编译器就会报错了。

下面是自己改正后的代码:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

static int cnt  = 0;
struct node {
	int value;
	struct node * next;
};

//插入后,首节点就是实实在在的首节点,没有头节点
struct node * add_node(struct node * list,int n)
{
struct node * new_node = malloc(sizeof(struct node));
if(new_node == NULL)
	{
	printf("-- no space left --\n");
	exit(EXIT_FAILURE);
	}
new_node -> value = n;
new_node -> next = list;
++ cnt;
return new_node;

}

//print a link list 's data
void print(struct node * list)
{
struct node * ptr;
//ptr = list不能换成 ptr = list -> next
for(ptr = list; ptr != NULL ; ptr = ptr -> next)
	{
		printf("%d\n",ptr -> value);
	}
}

int main()
{
struct node * ptr = NULL;
struct node * ret = add_node(ptr,10);
ret = add_node(ret,20);
ret = add_node(ret,30);
print(ret);



	return 0;
}

自己编写的另一个程序,给一个链表的基础上增加一个链表。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

static int cnt  = 0;
struct node {
	int value;
	struct node * next;
};

struct node * add_node(struct node * list,int n)
{
struct node * new_node = malloc(sizeof(struct node));
if(new_node == NULL)
	{
	printf("-- no space left --\n");
	exit(EXIT_FAILURE);
	}
new_node -> value = n;
new_node -> next = list;
++ cnt;
return new_node;

}

//print a link list 's data
void print(struct node * list)
{
struct node * ptr;
//ptr = list不能换成 ptr = list -> next
for(ptr = list; ptr != NULL ; ptr = ptr -> next)
	{
		printf("%d\n",ptr -> value);
	}
}

//在link list ptr的基础上,添加一些列数据,如果ptr ==NULL
//相当于直接创建一个新的 link list
struct node *add_list(struct node * ptr)
{
	int n;
	struct node * new_node = NULL;
	for(;;)
		{
		printf("enter a integer number:");
		scanf("%d",&n);
		if(n == 0)
			return ptr;	
		new_node = malloc(sizeof(struct node));
		if(new_node == NULL)
			{
			printf(" --no space left --\n");
			exit(EXIT_FAILURE);
			}
		new_node -> value = n;
		new_node -> next = ptr;
		ptr = new_node;
		}

}



int main()
{
struct node * ptr = add_list(NULL);
print(ptr);


	return 0;
}

 17.3.3函数指针的其他用途

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
void tabulate(double (*f)(double),double,double,double);

int main()
{
double final,increment,initial;


printf("Enter initial value:");
scanf("%lf",&initial);
printf("Enter final value:");
scanf("%lf",&final);
printf("Enter increment:");
scanf("%lf",&increment);

printf("    x     sin(x)\n"
	"_ _ _ _       _ _ _ _\n");

tabulate(&sin,initial,final,increment);
printf("    x    cos(x)\n"
	"_ _ _ _       _ _ _ _\n");
tabulate(&cos,initial,final,increment);
printf("    x    tan(x)\n"
	"_ _ _ _      _ _ _ _\n");
tabulate(&tan,initial,final,increment);


	return 0;
}



void tabulate(double (*f)(double),double first,double last,double incr)
{
double x;
int i,num_increment;
num_increment = ceil((last - first) / incr);
for(i = 0; i <= num_increment; ++ i)
	{
		x = first + i * incr;
		printf("%10.5f %10.5f\n",x,(*f)(x));	
	}
}


注:gcc编译器中命令行结尾需要加  -lm,如下所示(123是编译后可执行文件名称):

[r@localhost 17]$ gcc 2.c -o  123  -lm

运行结果:

Enter initial value:0  
Enter final value:.5
Enter increment:.1
    x     sin(x)
_ _ _ _  _ _ _ _
   0.00000    0.00000
   0.10000    0.09983
   0.20000    0.19867
   0.30000    0.29552
   0.40000    0.38942
   0.50000    0.47943
    x    cos(x)
_ _ _ _ _ _ _ _
   0.00000    1.00000
   0.10000    0.99500
   0.20000    0.98007
   0.30000    0.95534
   0.40000    0.92106
   0.50000    0.87758
    x    tan(x)
_ _ _ _ _ _ _ _
   0.00000    0.00000
   0.10000    0.10033
   0.20000    0.20271
   0.30000    0.30934
   0.40000    0.42279
   0.50000    0.54630

 关于qsort函数的使用方法:

qsort原型:

void qsort(void *base,size_t nmem,size_t size,int (*compare)(const void*,const void *));

各参数介绍(注意原型中很有很多通用指针void*)

base:必须指向数组的第一个元素(如果是对数组的一段区域进行排序,那么base指向这段区域的第一个元素),在一般的情况下,base就是数组的名字。

nmem:是要排序的元素的数量(不一定是数组中元素的数量)。

size是每个数组的元素的大小,用字节衡量。

compare是指向比较函数的指针。

例题1.把一个整数数组进行排序。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>


int compareInt(const void *p,const void *q )
{
	return  *((int *)p) - *((int *)q);
}

int main()
{
int a[]  = {1,2,100,3,45,67};
qsort(a,sizeof(a) / sizeof(a[0]),sizeof(a[0]),compareInt);
int i;
for(i = 0;i != 6; ++ i)
	{
		printf("%d ",a[i]);	
	}
	return 0;
}

例题2.对字符数组(内放c型字符串)进行排序

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

int compareChar(const void* p,const void *q)
{
	return *((char*)p) - *((char*)q);
}

int main()
{
char arr[] = "asdfaajklx";
size_t sz = sizeof(arr) / sizeof(arr[0]);
//因为sizeof把数组末尾的\0也算在内了,所以长度是sz-1
qsort(arr,sz - 1,sizeof(char),compareChar);   //如果长度传入sz,那么原来数组末尾的\0也参与排序,
					      //原来数组将不会以\0结尾了,用%s输入时候直接空
int i;
printf("%s",arr);


	return 0;
}

运行结果:

aaadfjklsx

解决方法:改正compareString,解释如下:

//这里注意:p和q中存放指向元素的指针,本题中元素类型是char*,所以元素指针类型是char**,
//char**再经过解引用即可转换成char*类型,char*类型字符串即可采用strcmp比较大小,如下:
int compareString(const void* p,const void *q)
{
	return strcmp(*(char**)p,*(char**)q);//先转换成元素的指针类型,char**
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

c modern approach chapter 17 中简单的复习 的相关文章

随机推荐

  • HTTP报文头解析(图文)

    一 通用头部字段 xff08 General Header Fields xff09 该字段在请求头和响应头都会使用到 xff0c 下方是常用的通用头部字段 xff1a 1 Cache Control 用来操作缓存的工作机制 xff0c 下
  • socket的TIME_WAIT状态的原因及解决办法和避免的办法

    一查看现在time wait的数量及浅析 netstat an grep TIME WAIT wc l 发现系统存在大量TIME WAIT状态的连接 xff0c 通过调整内核参数解决 xff0c 在 etc sysctl conf中加入 n
  • 数据库常见索引解析(B树,B-树,B+树,B*树,位图索引,Hash索引)

    B树 即二叉搜索树 xff1a 1 所有非叶子结点至多拥有两个儿子 xff08 Left和Right xff09 xff1b 2 所有结点存储一个关键字 xff1b 3 非叶子结点的左指针指向小于其关键字的子树 xff0c 右指针指向大于其
  • 在一棵IPv4地址树中彻底理解IP路由表的各种查找过程

    1 IPv4地址空间树 IPv4的整个地址空间可以构成一棵完美的二叉树 xff0c 因为它完全占满了整个4G的地址空间 这棵树如下所示 xff1a 需要指明的是 xff0c 完全画出这幅图是不可能的 xff0c 如果一个节点的直径小到1mm
  • 常用编码方式说明

    各种语言需要交流 xff0c 经过翻译是必要的 xff0c 那又如何来翻译呢 xff1f 在计算机中提供了多种翻译方式 xff0c 常见的有 ASCII ISO 88591 GB23112 GBK UTF 8 UTF 8 UTF 16等 它
  • 报文头格式以及常用协议端口

    IP协议是TCP IP协议族的动力 xff0c 它为上层协议提供无状态 无连接 不可靠的服务 优点 xff1a 简单 xff0c 高效 无状态指 xff1a IP通信双方不同步传输数据的状态信息 xff0c 所有的IP数据报的传输都是独立的
  • iOS中NSThread子线程需要建立NSAutoreleasePool

    今天做iOS开发时碰到一个问题 xff1a 在主线程打开一个大约400多K的文件读取数据时 xff0c 界面明显有停顿感 xff0c 于是尝试用NSThread建立子线程来负责读取文件数据 却发现子线程的运行速度奇慢无比 xff0c 刚开始
  • 报数游戏3

    题目描述 xff1a xfeff xfeff 一种报数游戏是从1开始连续报数 xff0c 如果报到7的倍数 xff08 7 xff0c 14 xff0c 21 xff0c 28 xff09 或者包含数字7的数 xff08 7 xff0c 1
  • c++ 关于流的重要帖子聚集

    1 关于clear 带参数版本 的2个例子 C 43 43 ios clear 用法及代码示例 纯净天空 2 关于unget的一个例子 unget C 43 43 标准库 开发文档 文江博客 3 关于peek的一个例子 C 43 43 中的
  • Mac无法访问Windows共享文件解决办法

    先按照网上教程 xff0c 在Windows下允许远程 xff0c 然后设置文件夹共享出来 xff0c 再在Mac上通过smb登录 xff0c 输入用户名和密码窗口总是抖动 xff0c 一直连接不上 xff0c 此时用另一台同一局域网的Wi
  • 虚拟机VMware安装ArchLinux及配置过程_详细202002_001#

    1 安装前准备工作 安装手册地址 xff1a https wiki archlinux org index php Installation guide版本为archlinux 2020 02 01 x86 64 isoVMware安装 x
  • VSCode C++环境配置

    VSCode C C 43 43 Windows 环境配置 第一次写博客 xff0c 编程小白 xff0c 码龄不足一年 xff0c 望大家批评改正 废话 许多像我一样的初级码农 xff0c 最开始接触的编程语言可能是C语言 xff0c 学
  • 服务器离线安装GitLab

    服务器离线安装GitLab并还原迁移的数据 1 下载gitlab的离线安装包 xff0c 默认el6 我下载的是el7 xff0c 以下简称el7 rpm 最好不要有openssh的rpm文件 2 登录服务器 xff0c 新建一个文件夹 s
  • leetcode刷题B部分

    目录 文章目录 目录50 Pow x n xff08 回到目录 目录 xff09 54 螺旋矩阵 59 xff08 回到目录 目录 xff09 58 最后一个单词的长度 xff08 回到目录 目录 xff09 59 螺旋矩阵 II 54 x
  • 【Java】字符串列表List<String>数字、字母、汉字混合排序(按中国人使用习惯排序)

    一 概要 本方法根据中国人使用习惯实现了 xff1a 总体按照按数字 字母 汉字升序 xff1b 数字之间按数值大小升序排序 xff1b 字母之间按ascii升序排序 xff1b 汉字之间按拼音升序排序 二 方法入口 span class
  • response.buffer用法

    不知道大家对Buffer了解多少 xff0c 很多人对这个概念都比较模糊 xff0c 尤其是在asp中 很多初学者在编写asp程序时很少用到这条语句 xff0c 下面我就来说说Buffer的用途以及它在asp程序中的作用 一 Buffer
  • 安装office时报错:an error occurred during the installation of assmbly component

    方法一 xff1a 删除office相关注册表 1 开始 xff0d xff0d 运行 xff0d xff0d 输入regedit xff0c 回车打开注册表找HKEY CURRENT USER Software Microsoft Off
  • mysql数据库的备份和恢复

    问题 想从我虚拟机上 xff0c 把数据库移到阿里云服务器上 解决方法 备份数据库 数据库名叫dddd mysqldump u root p span class hljs code 96 dddd 96 span gt dddd sql
  • Xcode如何打包Mac程序为 .dmg镜像文件

    打包Mac程序为 dmg镜像文件 获取可运行程序 按住crtl 43 b 编译程序 xff0c 编译完成之后打开Product文件夹 xff0c 选择编译好的程序 xff0c 鼠标右键点击Show in Finder 创建文件夹 在桌面新建
  • c modern approach chapter 17 中简单的复习

    一 程序remind c用动态内存实现 1 先回顾13 5中remind c的实现 xff0c 如下是自己看书以及自己的体会写成的程序 include lt stdio h gt include lt string h gt include