数据结构中的C语言编程基础

article/2025/7/23 3:36:25

​ 在学习数据结构时,需要我们编写许多的程序,对于一些变量的定义、结构体的声明、指针的使用,需要有一个统一的标准,这样才能方便我们使用、并简化记忆难度。

​ 本文结合自身的编程经验和高分笔记中对考研数据结构编程的一些建议,整理出这么一篇C语言编程入门基础,主要面向数据结构中数据类型的定义,希望能对你有所帮助。

1.Hello World示例

#include <stdio.h>int main()
{/* 我的第一个 C 程序 */printf("Hello, World! \n");return 0;
}

​ 上面就是编程语言学习的’创世之光’–Hello World!,只要他执行成功了,那么我们就算是一只脚踏进了圈子。

资源分配图

​ 一个基础的C程序,主要包含五个部分:预处理器指令(include加载的头文件)、函数、变量、语句&表达式、注释。

2.C基础语法

​ C语言的基础语法,不在本文赘述,可以参考下面文章进行学习或复习。

​ C语言教程

3.输入与输出

​ 当我们提到输入时,这意味着要向程序填充一些数据。输入可以是以文件的形式或从命令行中进行。C 语言提供了一系列内置的函数来读取给定的输入,并根据需要填充到程序中。

​ 当我们提到输出时,这意味着要在屏幕上、打印机上或任意文件中显示一些数据。C 语言提供了一系列内置的函数来输出数据到计算机屏幕上和保存数据到文本文件或二进制文件中。

​ 当然,我们在基本的编程练习时,不需要涉及到文件的操作,只需要通过键盘、屏幕进行数据的输入与输出。在本文中,我们主要讲下scanf() 和 printf() 函数。

3.1输入

​ scanf函数的声明如下:

int scanf(const char *format, ...);

​ 使用C的输入输出函数,有一点比较让初学者头疼,就是较为繁多的%s、%d等等。不过了解了之后,还是很方便使用的。

资源分配图
#include <stdio.h>int main(void)
{int a,b,c;printf("请输入三个数字:");scanf("%d%d%d",&a,&b,&c);printf("%d,%d,%d\n",a,b,c);printf("请再输入三个数字:");scanf("%d, %d, %d",&a,&b,&c);printf("%d,%d,%d\n",a,b,c);return 0;
}

​ 执行结果如下图所示,一定要注意,scanf中的format不要有过多的修饰,比如:scanf(“please input three numbers:%d%d%d”,&a,&b,&c),因为format决定了你输入数据时的结构。如scanf("%d%d%d",&a,&b,&c),几个输入之间可以使用空格分隔,而scanf("%d, %d, %d",&a,&b,&c),必须使用’,‘分隔,且’,'前不能有空格。

资源分配图

3.2输出

​ 输出的函数printf的声明如下:

int printf(const char *format, ...);

​ 其中的参数format是字符串,包含了要被写入到标准输出 stdout 的文本。它可以包含嵌入的 format 标签,format 标签可被随后的附加参数中指定的值替换,并按需求进行格式化。format 标签属性是 %[flags][width][.precision][length]specifier,具体讲解如下:

资源分配图

​ 其余更细致的文档说明,可以参考这篇文档。

#include <stdio.h>
int main()
{char ch = 'A';char str[20] = "lizishudd.blog.csdn.net";float flt = 10.234;int no = 150;double dbl = 20.123456;printf("字符为 %c \n", ch);printf("字符串为 %s \n" , str);printf("浮点数为 %f \n", flt);printf("整数为 %d\n" , no);printf("双精度值为 %lf \n", dbl);printf("八进制值为 %o \n", no);printf("十六进制值为 %x \n", no);return 0;
}

​ 执行结果如下图所示:

资源分配图

4.数组

4.1一维数组

​ 数组由多个相同数据类型的变量组合起来的,数组的声明方式如下,其中type为变量类型。

#define arraySize = 5
//arraySize为已经定义的常量
type arrayName [ arraySize ];
//for example
int a[5];

​ 数组的初始化,可以通过定义时初始化或通过键盘输入初始化。主要代码如下:

#include <stdio.h>
#define arraySize 5int main(int argc, const char * argv[]) {//arraySize为已经定义的常量int a[arraySize];//定义时初始化//如果b[]中不限制长度,则数组的长度由{}中的元素个数觉得int b[5] = {1, 3, 5, 7, 9};printf("请输入数组中的值:");for(int i = 0; i<arraySize; i++){scanf("%d", &a[i]);}printf("数组A中的值:");//通过输入初始化数组for(int i = 0; i<arraySize; i++){printf("%d ", a[i]);}printf("\n");printf("数组B中的值:");for(int i = 0; i<sizeof(b)/sizeof(int); i++){printf("%d ", b[i]);}printf("\n");return 0;
}

​ 执行结果如下:

资源分配图

4.2二维数组

​ C 语言支持多维数组。多维数组声明的一般形式如下:

type name[size1][size2]...[sizeN];
//for example
int threeDim[5][10][4];

​ 一般我们只会用到二维数组,更高维度的数组理论上都是相同的。一个二维数组可以认为是带有x行、y列的表格,如int x[3][4],他是一个包含三行、四列的二维数组。

资源分配图

二维数组的初始化和一维数组类似,可参考下面代码:

int a[3][4] = {  {0, 1, 2, 3} ,   /*  初始化索引号为 0 的行 */{4, 5, 6, 7} ,   /*  初始化索引号为 1 的行 */{8, 9, 10, 11}   /*  初始化索引号为 2 的行 */
};
//内部嵌套的括号是可选的,下面的初始化与上面是等同的:
int a[3][4] = {0,1,2,3,4,5,6,7,8,9,10,11};
//也可以通过键盘输入来初始化
for(i = 0; i < 3; i++){printf("请输入%d行的数据:", i+1);for(j = 0; j < 4; j++){scanf("%d", &a[i][j]);}printf("\n");
}

​ 当数组作为函数的参数是,函数的定义应当如何写?

//void 参数都是可调的
//一维数组作为参数的函数定义方法如下
void f(int x[], int n){//insert code here ...
}
//二维数组作为参数的函数定义方法如下
//不需要传入行数,必须传入列数,且传入的数组的第二维度的长度必须是maxSize
void f(int x[][maxSize], int n){//insert code here ...
}

5.指针

​ 指针一直是让人恐惧的知识点,但是在数据结构中,指针是你无法逃避的。不过指针的学习既简单又有趣,需要我们去正确的面对。通过指针,可以简化一些编程任务的执行。还有一些任务,如动态内存分配,没有指针是无法执行的。

​ 对于其他类型的变量,变量里装的是数据元素的内容,而指针变量里装的是变量的地址,通过它可以找出这个变量在内存中的位置,就像一个指示方向的指针,指出某个变量的位置。

​ 对于每种变量,指针的定义方法都有相似的规则,如以下语句:

//int型变量的定义语句,int a
int *a;
char *b;
float *a;
//结构体,参考第6节的内容
TypeA *d;

​ 与其他变量的定义相对比,指针型变量的定义只是在变量名之前多一个’*’。对于指针地址、变量的解释,可以参考下图:

资源分配图

​ 指针使用的案例如下所示,更详细的用法还需要读者自行探索。

#include <stdio.h>int main(int argc, const char * argv[]) {int  var = 20;   /* 实际变量的声明 *//*指针变量的声明如果无明确的指向,赋值为NULL*/int  *ip = NULL;/* 在指针变量中存储 var 的地址 */ip = &var;printf("var 变量的地址: %p\n", &var);/* 在指针变量中存储的地址 */printf("ip 变量存储的地址: %p\n", ip);/* 使用指针访问值 */printf("*ip 变量的值: %d\n", *ip);return 0;
}

6.结构体

​ 了解结构体前,需要知道typedeftypedef可以理解为给现有的数据类型起一个新名字,如:

typedef struct {...} TypeA

​ 新定义的结构体没有名字,因此用typedef给他起个名字是有必要的。

结构体就是系统提供给程序员制作新的数据类型的一种机制,即可以用系统已有数据类型(int,char,float…)或用户定义的结构型为原料,组合成用户需要的复杂数据类型。(可以理解成面向对象编程中的类)

​ 一般而言,可以在创建结构体时定义变量,但是为了书写统一,我们先通过typedef定义新类型,在创建新的变量。

//用typedef创建新类型
typedef struct
{int a;char b;double c; 
} TypeA;
//现在可以用TypeA作为类型声明新的结构体变量
TypeA a, a1[20], *a2;

​ 可以看到,结构体定义后,可以和int、char等基本数据类型一样使用,用于定义数组、指针等。当需要访问数组中的数据时,可以通过a1[index].a来访问。示例如下所示:

#include <stdio.h>typedef struct
{int a;char b;double c;
} TypeA;int main() {//现在可以用TypeA作为类型声明新的结构体变量TypeA a = {1, 'a', 12};printf("a中的值为:%d,%c,%f\n", a.a, a.b, a.c);TypeA *a2 = &a;//需注意,a2->a或(*a2).bprintf("a2中的值为:%d,%c,%f\n", a2->a, (*a2).b, a2->c);TypeA a3[2];a3[0] = a;a3[1] = a;printf("a3[0]中的值为:%d,%c,%f\n", a3[0].a, a3[0].b, a3[0].c);printf("a3[1]中的值为:%d,%c,%f\n", a3[1].a, a3[1].b, a3[1].c);return 0;
}

​ 在数据结构中,结构体更常见的应用,是和指针结合起来构造结点(链表的结点、二叉树的结点等)。下面我们来一起看下常用结点的"构造"。

6.1链表结点

​ 链表结点有两个域:一个是数据域,用于存放数据;另一个是指针域(指针域可以有多个,如双向链表结点),用于存放下一个结点的位置,链表结点的结构型定义如下:

typedef struct Node{//这里默认是int型,如其他类型可以修改int a;//指向Node型变量的指针struct Node *next;
}Node;

注意:凡是结构型内部含有指向和自己相同类型的指针,即Node结点中有指向Node结点的指针变量,则在定义Node的语句后,需要加上Node这个结构型的名字,如typedef struct Node。读者可以自己对比下上面定义和上一小节中TypeA定义的区别。

6.2二叉树结点

​ 二叉树结点的构造,也是由链表结点引申出来的,其余类型的结点也都可以类似的进行扩展。二叉树结点的结构型如下:

typedef struct BTNode{//这里默认是int型,如其他类型可以修改int data;//指向左孩子结点的指针struct Node *lchild;//指向右孩子结点的指针struct Node *rchild;
}BTNode;

6.3创建新结点

​ 通过上面讲解,我们也基本知道了结构型结点的定义方法,定义方法还有其他的不同写法,不过我们不用关心太多,以增加记忆负担和理解难度。结构型定义好后,就要用它来制作新结点了。

​ 以二叉树结点为例,创建结点有以下两种写法:

//1
BTNode aNode;
//2
BTNode *bNode;
bNode = (BTBode *) malloc(sizeof(BTNode));

​ 其中,1理解起来比较容易;对于2,分为了两步,首先定义一个结点的指针bNode,然后通过malloc()来申请一个节点的内存空间,最后让指针bNode指向这片内存空间。

​ 其中malloc()函数很重要,需要掌握,以后所有的内存分配基本都可使用malloc()来完成。malloc()的函数声明如下:

void *malloc(size_t size)

​ 通过malloc()申请空间的通用公式如下,其中①、②处填写你所定义的结构型名称,p为指针、指向新创建的结点,sizeof()函数用于测算所需要申请的空间大小。

p = (*)malloc(sizeof()) 

​ 我们还可以通过malloc()来动态的申请数组空间,相对于上面的申请方法,可以认为动态申请了一组空间,语法如下,可以通过p[1]来取第二个元素。

int *p;
p = (int *) malloc(n * sizeof(int));

​ 使用示例如下:

#include <stdlib.h>//可以将代码放入第六节中的测试代码中//...TypeA *node;node = (TypeA *)malloc(sizeof(TypeA));node->a = 2;node->b = 'A';node->c = 13;printf("node中的值为:%d,%c,%f\n", node->a, node->b, (*node).c);//return 0;

参考资料:

1.菜鸟教程–C 语言教程

2.数据结构高分笔记


​ 又到了分隔线以下,本文到此就结束了,本文内容全部都是由博主根据自身理解与对考研资料进行的整理,仅作为参考,大佬有什么问题,可以评论区留言,如果有什么错误,还请批评指正。

​ 本专栏为数据结构知识,喜欢的话可以持续关注,如果本文对你有所帮助,还请还请点赞、评论加关注

​ 有任何疑问,可以评论区留言。


http://chatgpt.dhexx.cn/article/4SnU48GL.shtml

相关文章

面向数据编程 Data-Oriented Programming [1]

RuntimeMapMaker3D-Pro 面向数据的编程原则 0.1 简介 面向数据的编程是一种编程范式&#xff0c;旨在简化以信息为中心的软件系统的设计和实施。而不是围绕着将数据和代码结合在一起的实体&#xff08;如实例化的对象&#xff09;来设计信息系统&#xff08;例如&#xff0c;从…

ODBC API开发教程

ODBC API开发教程 作者&#xff1a;闻怡洋 未得到作者允许请勿转载 http://wyy.vchelp.net/ 目录 第 1 章 介绍... 2 第 2 章 ODBC API访问数据库... 2 2.1 ODBC简要介绍... 2 2.1.1 在没有ODBC以前... 2 2.1.2 ODBC介绍... 3 2.1.3 ODBC结构…

Microsoft Server 2008 空间存储 应用方法详解

2019独角兽企业重金招聘Python工程师标准>>> 刚接触2008的空间存储&#xff0c;资料比较少&#xff0c;在数据库操作中有很多不懂的地方&#xff0c;包括用法&#xff0c;语法等&#xff0c;经过同事的指点明白了一些&#xff0c;感谢大腿同事~这里只记录数据库操作…

ODBC 数据类型和API(VC)

目录 ODBC 数据类型API 函数 ODBC 数据类型 ODBC SQL 数据类型 展开显示 ODBC SQL 数据类型SQL类型标识SQL 92类型标识类型描述SQL_CHARCHAR(n)定长字符串,其长度为nSQL_VARCHARVARCHAR(n)变长字符串,最大长度为nSQL_LONGVARCHARLONG VARCHAR变长字符串,最大长度取决于数据源S…

Sql的decimal、float、double类型的区别

三者的区别介绍 float:浮点型&#xff0c;含字节数为4&#xff0c;32bit&#xff0c;数值范围为-3.4E38~3.4E38&#xff08;7个有效位&#xff09; double:双精度实型&#xff0c;含字节数为8&#xff0c;64bit数值范围-1.7E308~1.7E308&#xff08;15个有效位&#xff09; d…

【网络编程实践】2.3.4.2 建议关闭 Nagle 算法

Nagle算法主要是避免发送小的数据包&#xff0c;要求TCP连接上最多只能有一个未被确认的小分组&#xff0c;在该分组的确认到达之前不能发送其他的小分组。 Nagle算法的目的&#xff1a;避免发送大量的小包&#xff0c;网络上每次只能一个小包存在&#xff0c;在小包被确认之前…

Nagle算法与TCP_CORK,TCP_NODELAY,TCP_QUICKACK

1. Nagel算法 TCP/IP协议中&#xff0c;无论发送多少数据&#xff0c;总是要在数据前面加上协议头&#xff0c;同时&#xff0c;对方接收到数据&#xff0c;也需要发送ACK表示确认。为了尽可能的利用网络带宽&#xff0c;TCP总是希望尽可能的发送足够大的数据。&#xff08;一…

如何关闭和启用Nagle算法

如果各位读者在搜索如何关闭的话&#xff0c;那么我有理由相信各位对想要解决的问题已经算是比较清楚了&#xff0c;废话不多数。 什么是nagle算法&#xff0c;它是干嘛用的&#xff0c;请自行google or 百度 Step1 Open regredit 快捷键&#xff1a;winr 打开&#xff1a…

19- TCP 协议(Nagle)

前面我们所用的 unp/protocol/tools/winclient/echo_cli.cpp 程序的特别之处是它总会发送一个小分组&#xff08;TCP 段&#xff0c;只有 41 字节&#xff09;到服务器。这样的小分组在英文中称为 tinygram&#xff0c;在网络状态好的情况下&#xff0c;比如局域网中&#xff0…

TCP Nagle算法详解

转: http://bbs.chinaunix.net/thread-3767363-1-1.html 在网络拥塞控制领域&#xff0c;我们知道有一个非常有名的算法叫做Nagle算法&#xff08;Nagle algorithm&#xff09;&#xff0c;这是使用它的发明人John Nagle的名字来命名的&#xff0c;John Nagle在1984年首次用这个…

TCP之延时Nagle算法实验详解

TCP/IP协议中&#xff0c;无论发送多少数据&#xff0c;总是要在数据前面加上协议头&#xff0c;同时&#xff0c;对方接收到数据&#xff0c;也需要发送ACK表示确认。为了尽可能的利用网络带宽&#xff0c;TCP总是希望尽可能的发送足够大的数据。&#xff08;一个连接会设置MS…

Nagle Algorithm

转: http://bbs.chinaunix.NET/thread-3767363-1-1.html 在网络拥塞控制领域&#xff0c;我们知道有一个非常有名的算法叫做Nagle算法&#xff08;Nagle algorithm&#xff09;&#xff0c;这是使用它的发明人John Nagle的名字来命名的&#xff0c;John Nagle在1984年首次用这…

TCP中的Nagle算法

TCP中的Nagle算法 一. Nagel算法 TCP/IP协议中,无论发送多少数据,总是要在数据前面加上协议头,同时,对方接收到数据,也需要发送ACK表示确认.为了尽可能的利用网络带宽,TCP总是希望尽可能的发送足够大的数据.(在一个连接中会设置MSS参数,因此,TCP/IP希望每次都能够以MSS尺寸的数…

确认应答、Nagle算法和延时确认应答

目录 确认应答 延时确认应答 Nagle算法 确认应答 TCP在传输数据的时候&#xff0c;每次接受方收到来自发送方的数据包后&#xff0c;接受方对都会发送一个确认应答(ACK)报文作为回应&#xff0c;发送方收到来自接受方的确认应答(ACK)报文&#xff0c;就表明发送的数据已经被…

TCP/IP卷一:80---TCP数据流与窗口管理之(延时确认(延迟ACK)、Nagle算法)

一、延迟确认&#xff08;延迟ACK&#xff09; 在许多情况下&#xff0c;TCP并不对每个到来的数据包都返回ACK&#xff0c;利用TCP的累积ACK字段&#xff08;参见TCP报文格式https://blog.csdn.net/qq_41453285/article/details/104016416&#xff09;就能实现该功能累积确认可…

禁用 Nagle 算法

有没有发现一个很奇怪的组合&#xff0c;即 Nagle 算法和延时 ACK 的组合。这个组合为什么奇怪呢&#xff1f; 我举一个例子你来体会一下。比如&#xff0c;客户端分两次将一个请求发送出去&#xff0c;由于请求的第一部分的报文未被确认&#xff0c;Nagle 算法开始起作用&…

TCP Nagle算法及示例

TCP nagle算法是说&#xff0c;一个TCP连接只允许有一个未被确认的小数据包&#xff0c;如果有小数据包未被确认&#xff0c;其他要发送的小数据包先被缓存起来&#xff0c;等收到确认后&#xff0c; 把这些数据包再一块发送出去。注意算法中说的是小数据包&#xff0c;也就是n…

TCP-IP详解:Nagle算法

参考书籍&#xff1a;TCP/IP详解&#xff0c;卷1&#xff1a;协议 Small Packet Problem 在使用一些协议通讯的时候&#xff0c;比如Telnet&#xff0c;会有一个字节字节的发送的情景&#xff0c;每次发送一个字节的有用数据&#xff0c;就会产生41个字节长的分组&#xff0c…

TCP-Nagle:代码版本重新解释Nagle算法

开年来的第一份工作&#xff0c;就是在最新的内核上打补丁。 可没想到Nagle算法也被我冲进了去年的垃圾桶里。 在网上找了一些资料&#xff0c;理论很快被消化&#xff0c;但看了看内核的实现&#xff0c;久久没能动弹。坐了一天&#xff0c;才摸索出来点什么&#xff0c;觉得…

Nagle算法原理与实现详解

文章目录 背景Nagle算法详解算法实现实现开启与关闭Nagle算法 Nagle算法与延迟ACK参考 背景 TCP的数据流大致可以被分成两类&#xff1a; 交互式数据流 TCP交互数据流指的是&#xff1a;TCP连接中传输的所有数据的总和&#xff0c;包括控制命令&#xff08;用于管理网络中连接…