C语言家教记录(八)

C语言家教记录(八)

导语

本次授课的内容如下:指针的高级应用,流和文件

辅助教材为 《C语言程序设计现代方法(第2版)》

指针的高级应用

动态分配、使用、释放

malloc,calloc(一般不用),realloc(一般不用)

null 空指针,也可以用0

null的使用

c 复制代码
if(p==NULL)
if(!p)
if(p!=NULL)
if(p)

malloc的使用

c 复制代码
p=malloc(n+1);//不常用
p=(char*)malloc(n+1);//常用,malloc的分配单位是字节

int* a;
a=malloc(n*sizeof(int));
for(int i=0;i<n;i++)a[i]=0;

calloc的使用

c 复制代码
a=calloc(n,sizeof(int));//自动初始化
struct point { int x, y; } *p;
p = calloc(1, sizeof(struct point));//x,y都为0

realloc的使用,规则见书

c 复制代码
realloc(p,n*sizeof(int));

释放存储空间,例子见书

c 复制代码
p=malloc();
q=malloc();
free(p);
p=q;

char*p=malloc(...);
free(p);
strcpy(p,"abc");//报错,悬空指针问题

示例程序

c 复制代码
char *concat(const char *s1, const char *s2)
{
 char *result ;
 result = malloc(strlen(s1) + strlen(s2) + 1);
 if (result == NULL) {
 printf("Error: malloc failed in concat\n");
 exit (EXIT_FAILURE);
 }
 strcpy(result, s1);
 strcat(result, s2);
 return result;
}
p=concat("abs","def");

链表

概念和例子见书

c 复制代码
struct node
{
	int value;
	struct node *next;
};//链表的节点定义
struct node* first =NULL;

//节点的创建,图见书
struct node* p;
p=malloc(sizeof(struct node));
(*p).value=10;
//等价于
p->value=10;

示例程序

解释插入链表的实现,解释图

c 复制代码
struct node *add_to_list(struct node *list, int n)
{
 struct node *new_node;
 new_node = malloc(sizeof(struct node));
 if (new_node == NULL) {
 printf("Error: malloc failed in add_to list\n");
 exit(EXIT_FAILURE);
 }
 new_node->value = n;
 new_node->next = list;
 return new_node;
}

搜索链表,用书上例子解释

c 复制代码
struct node *search_list(struct node *list, int n)
{
 struct node *p;
 for (p = list; p != NULL; p = p->next)
 if (p->value == n)
 return p;
 return NULL;
}

struct node *search_list(struct node *list, int n)
{
 while (list != NULL && list->value != n)
 list = list->next;
 return list;
}

删除节点,根据书上例子

c 复制代码
struct node *delete_from_list(struct node *list, int n)
{
 struct node *cur, *prev;
 for (cur = list, prev = NULL;
 cur != NULL && cur->value != n;
 prev = cur, cur = cur->next)
 ;
 if (cur == NULL)
 return list; /* n was not found */
 if (prev == NULL)
 list = list->next; /* n is in the first node */
 else
 prev->next = cur->next; /* n is in some other node */
 free (cur);
 return list;
}

指向指针的指针

如果不进行返回,添加结点可能会失效,见书上例子

c 复制代码
void_add_to_list(struct node **list, int n)
{
 struct node *new_node;
 new_node = malloc(sizeof(struct node));
 if (new_node == NULL) {
 printf("Error: malloc failed in add_to_list\n");
 exit(EXIT_FAILURE);
 }
 new_node->value = n;
 new_node->next = *list;
 *list = new_node;
}

指向函数的指针

c 复制代码
void (*pf)(int);
pf=f;//赋值
(*pf)(i);//调用
pf(i);//调用
//pf 可以指向任何带有int 型形式参数并且返回void 型值的函数

double integrate(double (*f)(double), double a, double b);
double integrate(double f(double), double a, double b);//等价

result=integrate(sin,0.0,PI/2);

integrate内可以调用
y=(*f)(x);

qsort函数

c 复制代码
void qsort(void *base, size_t nmemb, size_t size,
 int (*compar) (const void *, const void *));//函数原型

qsort(inventory, num_parts, sizeof(struct part), compare_parts);//调用格式

int compare_parts(const void *p, const void *q)
{
 const struct part *p1 = p;
 const struct part *q1 = q;
 if (p1->number < q1->number)
 return -1;
 else if (p1->number == q1->number)
 return 0;
 else
 return 1;
}
//等价于
int compare_parts(const void *p, const void *q)
{
 return strcmp(((struct part *) p)->name,
 ((struct part *) q)->name);
}

流和文件

stdin,stdout,stderr简单介绍

简单介绍二进制文件

简单介绍输入输出重定向和命令行

文件操作

fopen,fclose,freopen等

tmpfile,fflush,remove,rename跳过

c 复制代码
FILE *fopen(const char * restrict filename, const char * restrict
 mode);//函数原型

fp=fopen("a.txt","r");//路径和模式,运行之后输入从键盘改成文件
//解释参数r w a r+ w+ a+,参数可以组合

int fclose(FILE *stream);//关闭文件

FILE *freopen(const char * restrict filename, const char * restrict mode, FILE * restrict stream);//重定向

if (freopen("foo","w", stdout) == NULL) {
 /* error; foo can't be opened */
}//最好先关闭再重定向

//解释从命令行获取文件名
int main(int argc, char *argv[])
{
 ...
}

示例程序

c 复制代码
#include <stdio.h>
#include <stdlib.h>
#define FILE_NAME "example.dat"
int main(void)
{
 FILE *fp;
 fp = fopen(FILE_NAME, "r");
 if (fp == NULL) {
 printf("Can't open %s\n", FILE_NAME);
 exit(EXIT_FAILURE);
 }
 ...
 fclose(fp);
 return 0;
}

#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
 FILE *fp;
 if (argc != 2) {
 printf("usage: canopen filename\n");
 exit (EXIT_FAILURE);
 }
 if ((fp = fopen(argv[1], "r")) == NULL) {
 printf("%s can't be opened\n", argv[1]);
 exit (EXIT_FAILURE);
 }
 printf("%s can be opened\n", argv[1]);
 fclose(fp);
 return 0;
}

变量和格式化io

简介fprintf和printf,见书

简介fscanf和scanf,见书

简介fputc,putc,putchar,fgets,gets

sprintf,snprintf,针对字符数组的输出

sscanf,针对字符数组的输入

文件定位和块输入输出跳过,简单勾一下

示例程序

c 复制代码
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
 FILE *source_fp, *dest_fp;
 int ch;
 if (argc != 3) {
 fprintf(stderr, "usage: fcopy source dest\n");
 exit(EXIT_FAILURE);
 }
 if ((source_fp = fopen(argv[1], "rb")) == NULL) {
 fprintf (stderr, "Can't open %s\n", argv[1]);
 exit(EXIT_FAILURE);
 }
 if ((dest_fp = fopen(argv[2], "wb")) == NULL) {
 fprintf (stderr, "Can't open %s\n", argv[2]);
 fclose(source_fp);
 exit(EXIT_FAILURE);
 }
 while ((ch = getc(source_fp)) != EOF)
 putc (ch, dest_fp);
 fclose(source_fp);
 fclose(dest_fp);
 return 0;
}

总结和复习

本次授课讲述第17章和第22章内容,关键点:指针的高级应用和输入输出

相关推荐
CarIise2 小时前
C语言基础课程笔记:硬件原理、数据类型、结构体与格式化输入输出详解
c语言·开发语言·笔记
leoZ2312 小时前
Vue3 还原一个企业级后台-14-项目总结
开发语言·人工智能·后端·opencv·计算机视觉·数据挖掘·rust
GeekZHR2 小时前
C语言指针2:数组名、二级指针、指针数组,一次把“指针和数组“讲透
c语言·数据结构·算法·指针
zlinear数据采集卡2 小时前
数据采集卡从入门到精通(7):流水线型ADC——级级接力,高速与高精的平衡术
开发语言·arm开发·嵌入式硬件·fpga开发·c#
Dr.kangder3 小时前
嵌入式面试总结(二十一)——C语言关键字
c语言·开发语言·面试·职场和发展·架构·虚拟化
W_326003 小时前
Python-OpenCV:库、环境搭建、图片与摄像头解析
开发语言·图像处理·python·opencv·机器学习
zhy295633 小时前
在 QAIRT Genie SDK 上部署 Llama 3.2 1B 模型:从环境准备到 C++ 推理
开发语言·c++·llama
云上飞476369623 小时前
Windows WSL2 + Docker 环境下NVIDIA PhysicsNeMo 安装指南
windows·docker·physicsai·physicsnemo
爱跳舞的烤冷面3 小时前
自学嵌入式第N天(Linux篇——文件编程)
java·开发语言·前端
weixin_6683 小时前
取消Windows 11 默认精简的鼠标右键文件夹菜单
windows·计算机外设