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章内容,关键点:指针的高级应用和输入输出

相关推荐
Re.不晚11 分钟前
Java入门15——抽象类
java·开发语言·学习·算法·intellij-idea
老秦包你会14 分钟前
Qt第三课 ----------容器类控件
开发语言·qt
凤枭香16 分钟前
Python OpenCV 傅里叶变换
开发语言·图像处理·python·opencv
ULTRA??20 分钟前
C加加中的结构化绑定(解包,折叠展开)
开发语言·c++
hairenjing112330 分钟前
在 Android 手机上从SD 卡恢复数据的 6 个有效应用程序
android·人工智能·windows·macos·智能手机
远望清一色37 分钟前
基于MATLAB的实现垃圾分类Matlab源码
开发语言·matlab
confiself1 小时前
大模型系列——LLAMA-O1 复刻代码解读
java·开发语言
XiaoLeisj1 小时前
【JavaEE初阶 — 多线程】Thread类的方法&线程生命周期
java·开发语言·java-ee
杜杜的man1 小时前
【go从零单排】go中的结构体struct和method
开发语言·后端·golang
幼儿园老大*1 小时前
走进 Go 语言基础语法
开发语言·后端·学习·golang·go