分类 C/C++ 下的文章

while(~scanf(“%d%d“,&a,&b))详解

按位取反

1. 原码、反码、补码

原码:符号位加上真值的绝对值, 即用第一位表示符号, 其余位表示值。

反码:正数的反码是其本身;负数的反码是在其原码的基础上, 符号位不变,其余各个位取反。

补码:正数的补码就是其本身;负数的补码是在原码的基础上, 符号位不变, 其余各位取反, 最后+1。 (即在反码的基础上+1)

十进制数原码反码补码
850101 01010101 01010101 0101
-851101 01011010 10101010 1011
90000 10010000 10010000 1001
-91000 10011111 01101111 0111

 

2. 取反符号:~

~ 取反运算,0 则变为 1,1 则变为 0,如

~ 1 0 0 1 1
-----------------------------
  0 1 1 0 0

 

3. 按位取反

按位取反需要涉及以上概念。要弄懂这个运算符的计算方法,首先必须明白二进制数在内存中的存放形式,二进制数在内存中是以补码的形式存放的。

下面以计算正数 9 的按位取反为例,计算步骤如下(注:前四位为符号位):

- 原码   : 0000 1001
- 算反码 : 0000 1001 (正数反码同原码)
- 算补码 : 0000 1001 (正数补码同反码)
- 补取反 : 1111 0110 (全位0变1,1变0)
- 算反码 : 1111 0101 (末位减1)
- 算原码 : 1111 1010 (其他位取反)

 

总结

  1. 所有正整数的按位取反是其本身+1的负数
  2. 所有负整数的按位取反是其本身+1的绝对值
  3. 零的按位取反是 -1(0在数学界既不是正数也不是负数)

 

scanf( ) 的返回值

对于scanf("%d%d%d",&a,&b,&c);

  1. 如果a、b 和c 都被成功读入,则scanf的返回值为3
  2. 如果 a 和 b 被成功读入,那么返回值为2
  3. 如果只有a被成功读入,那么返回值为1
  4. 如果遇到错误或遇到end of file,返回值为EOF

 

其中,EOFEnd Of File 的缩写,在 C 语言标准库中的定义为:#define EOF (-1)

可参考此篇文章:字符输入输出和输入验证 – Echo (liveout.cn)

 

总结

scanf 成功读取至少一个数时,scanf 的返回值是1或2,

1按位取反为-2, 2按位取反为-3,都会进入while循环内部。

当输入读取结束后,scanf的返回值是EOF,EOF即-1,-1按位取反为0,此时会跳出while循环。

//这个意思一样
while(~scanf("%d%d",&a,&b)) 
while(scanf("%d%d",&a,&b) != EOF)

 

--> while(~scanf(“%d%d“,&a,&b))详解按位取反1. 原码、反码、补码原码:符号位加上真值的绝对值, 即用第一位表示符号, 其余位表示值。反码:正数的反码是其本身;负数的反码是在其原码的基础上, 符号位不变,其余各个位取反。补码:正数的补码就是其本身;负数的补码是在原码的基础上, 符号位不变, 其余各位取反, 最后+1。 (即在反码的基础上+1)十进制数原码...

输入

gets()

不保留换行符

读取整行输入,直至遇到换行符,然后丢弃换行符,存储其余字符,并且在末尾添加空字符 \0


fgets()

保留换行符

从指定的流 stream 读取一行,并把它存储在 str 所指向的字符串内。当读取 (n-1) 个字符时,或者读取到换行符时,或者到达文件末尾时,它会停止,具体视情况而定。

char *fgets(char *str, int n, FILE *stream)
  • str -- 这是指向一个字符数组的指针,该数组存储了要读取的字符串。
  • n -- 这是要读取的最大字符数(包括最后的空字符)。通常是使用以 str 传递的数组长度。
  • stream -- 这是指向 FILE 对象的指针,该 FILE 对象标识了要从中读取字符的流
#include <stdio.h>

int main()
{
   FILE *fp;
   char str[60];

   /* 打开用于读取的文件 */
   fp = fopen("file.txt" , "r");
   if(fp == NULL) {
      perror("打开文件时发生错误");
      return(-1);
   }
   if( fgets (str, 60, fp)!=NULL ) {
      /* 向标准输出 stdout 写入内容 */
      puts(str);
   }
   fclose(fp);
   
   return(0);
}


输出

put

显示字符串时会自动在末尾添加换行符

fputs

末尾不会添加换行符


1. 统计长度

strlen():

int a;
char str[n];
a = strlen(str);


2. 拼接字符串

strcat()

src 所指向的字符串追加到 dest 所指向的字符串的结尾

char *strcat(char *dest, const char *src)
  • dest -- 指向目标数组,该数组包含了一个 C 字符串,且足够容纳追加后的字符串。
  • src -- 指向要追加的字符串,该字符串不会覆盖目标字符串。

该函数返回一个指向最终的目标字符串 dest 的指针

char src[50], dest[50];
strcpy(src,  "This is source");
strcpy(dest, "This is destination");
strcat(dest, src);

最终的目标字符串: This is destinationThis is source|


strncat()

src 所指向的字符串追加到 dest 所指向的字符串的结尾,直到 n 字符长度为止。

char *strncat(char *dest, const char *src, size_t n)
  • dest -- 指向目标数组,该数组包含了一个 C 字符串,且足够容纳追加后的字符串,包括额外的空字符。
  • src -- 要追加的字符串。
  • n -- 要追加的最大字符数。

该函数返回一个指向最终的目标字符串 dest 的指针。

 char src[50], dest[50];
strcpy(src,  "This is source");
strcpy(dest, "This is destination");
strncat(dest, src, 15);

最终的目标字符串: This is destinationThis is source|


3. 比较字符串

strcmp()

int strcmp(const char *str1, const char *str2)
  • str1 -- 要进行比较的第一个字符串。
  • str2 -- 要进行比较的第二个字符串。

该函数返回值如下:

  • 如果返回值< 0,则表示 str1 小于 str2。
  • 如果返回值 > 0,则表示 str1 大于 str2。
  • 如果返回值 = 0,则表示 str1 等于 str2。


strncmp()

int strncmp(const char *str1, const char *str2, size_t n)
  • str1 -- 要进行比较的第一个字符串。
  • str2 -- 要进行比较的第二个字符串。
  • n -- 要比较的最大字符数。

该函数返回值如下:

  • 如果返回值 < 0,则表示 str1 小于 str2。
  • 如果返回值 > 0,则表示 str1 大于 str2。
  • 如果返回值 = 0,则表示 str1 等于 str2。


4. 复制

strcpy

src 所指向的字符串复制到 dest

char *strcpy(char *dest, const char *src)
  • dest -- 指向用于存储复制内容的目标数组。
  • src -- 要复制的字符串。

该函数返回一个指向最终的目标字符串 dest 的指针。

   char src[40];
   char dest[100];
   strcpy(src, "This is runoob.com");
   strcpy(dest, src);


strncpy

src 所指向的字符串复制到 dest,最多复制 n 个字符。当 src 的长度小于 n 时,dest 的剩余部分将用空字节填充

char *strncpy(char *dest, const char *src, size_t n)
  • dest -- 指向用于存储复制内容的目标数组。
  • src -- 要复制的字符串。
  • n -- 要从源中复制的字符数。

该函数返回最终复制的字符串。

 

--> 输入gets()不保留换行符读取整行输入,直至遇到换行符,然后丢弃换行符,存储其余字符,并且在末尾添加空字符 \0fgets()保留换行符从指定的流 stream 读取一行,并把它存储在 str 所指向的字符串内。当读取 (n-1) 个字符时,或者读取到换行符时,或者到达文件末尾时,它会停止,具体视情况而定。char *fgets(char *str, int n, FILE *stream...

1. 单字符I/O:getchar() 和 putchar()

getchar() & putchar 每次只处理一个字符

头文件 stdio.h 中包含这两个,他们被定义为供预处理器使用的宏

2. 缓冲区

老式系统,无缓冲区,输入 hello 时,显示为 hheelloo。即正在等待的程序可立即使用输入的字符

 缓冲输入和无缓冲

好坏

缓冲区好处:

  1. 若干字符作为一个块进行传输比逐个发送节约时

    1. 用户打错可直接修改

无缓冲区好处:游戏指令

缓冲分类

缓冲分为:

  1. 完全缓冲I/O:缓冲区填满时刷新缓冲区
  2. 行缓冲I/O:出现换行符时刷新缓冲区

无缓冲

ANSI C 和 后续的 C标准都规定输入是缓冲的:一些计算机不允许无缓冲输入

conino.h:包含无缓冲输入函数

getchae();回显无缓冲输入(回显输入意味着用户输入字符直接显示在屏幕上)

getch():无回显无缓冲输入 (无回显输入意味着击键后对应的字符不显示)

3. 结束键盘输入

3.1 文件、流和键盘输入

文件

文件:存储器中存储信息的区域。通常文件保存在某种永久存储器中

I/O:C存在对文件进行操作的库函数。从较低层面上,C 可以使用主机操作系统基本文件工具直接处理文件,这些直接调用操作系统的函数被称为底层 I/O。

由于计算机系统各不相同(差异),不能为普通的底层I/O函数创建标准库,但从较高层面上,C 还可以通过标准I/O包来处理文件。

这里的差异有多种。例如,不同系统存储文件的方式不同。有些系统把文件内容和文件相关信息分开存储;另一些系统在文件中创建一份文件描述。

在处理文件方面,有些使用单个换行符标记行末尾,其他系统可能使用回车符和换行符组合来表示行末尾。如果使用标准I/O包则不用考虑这些差异。

C程序处理的是流而不是文件。Java也是的(个人觉得)

流 是一个实际输入或输出映射的理想化数据流。这意味着不同属性和不同种类的输入,由属性更统一的流来表示。于是打开文件过程就是把流与文件关联,读写都通过流来完成.

重点:理解 C 把输入和输出设备视为存储设备上的普通文件,尤其是把键盘和显示设备视为每个C程序自动打开的文件。

stdin流表示键盘输入,stdout流表示屏幕输出,getchar()、putchar()、printf()、scanf() 函数都是标准I/O包的成员,处理这两个流。

综上所述:可以用处理文件的方式处理键盘输入。C的输入函数内置了文件结尾检测器。既然可以把键盘输入视为文件,那么也应该能使用文件结尾检测器结束键盘输入。

3.2 文件结尾

计算机操作系统要以某种方式判断文件的开始和结束。检测文件结尾的一种方法是,在文件末尾放一个特殊的字符标记文件结尾。

如今。这些操作系统可以使用内嵌的Ctrl+Z字符来标记结尾。曾经是操作系统使用的唯一标记,不过现在有其他选择,例如记录文件的大小。

带文件结尾标记的文件

操作系统使用的另一种方法是存储文件大小的信息。如果文件有三千字节,则读到三千字节时到达末尾。MS-DOS及其相关系统使用此方法处理二进制文件,,因为这种方法可以在文件中存储所有字符,包括 Ctrl+Z。新版的DOS也使用这种方法处理文本文件。UNIX 使用这种方法处理所有文件。

但是无论操作系统实际使用哪种方法,在C语言中,用 getchar()/scanf() 读取文件检测到文件结尾时将返回一个特殊的值,即EOF(end of file)。

EOF定义在 stdio.h 文件中 #define EOF (-1)

为-1原因:字符集在 0——255。-1不对应任何字符。

一些系统也许把EOF定义为其他,但是定义的值一定与输入字符所产生的返回值不同。

如何在程序中使用EOF? 把 getchar() 值和EOF比较。如果两值不同,就说明没有到达文件结尾。即如下表达式

while ( (ch = getchar()) != EOF)

4. 重定向和文件

输入和输出设计函数、数据和设备。如果输入函数和输入数据不变,仅改变程序查找数据的位置,如何完成?

程序可以通过两种方法使用文件

  1. 显式使用特定的函数打开文件、关闭文件、读取我文件、写入文件
  2. 设计能与键盘交互的程序,通过不同渠道重定向输入至文件和从文件输出。即把stdin流重新赋给文件,继续使用getchar() 函数从输入流中获取数据

--> 1. 单字符I/O:getchar() 和 putchar()getchar() & putchar 每次只处理一个字符头文件 stdio.h 中包含这两个,他们被定义为供预处理器使用的宏2. 缓冲区老式系统,无缓冲区,输入 hello 时,显示为 hheelloo。即正在等待的程序可立即使用输入的字符好坏缓冲区好处:若干字符作为一个块进行传输比逐个发送节约时用户打错可直接修改无缓冲...

C语言练习题(简单入门题)

前言

这篇文章是一些关于C语言的简单入门题,相关刷题网站为:https://www.dotcpp.com/


1. 数字的处理与判断

题目描述

给出一个不多于5位的整数,要求 1、求出它是几位数 2、分别输出每一位数字 3、按逆序输出各位数字,例如原数为321,应输出123

输入格式

一个不大于5位的数字

输出格式

三行 第一行 位数 第二行 用空格分开的每个数字,注意最后一个数字后没有空格 第三行 按逆序输出这个数

样例

输入:
12345

输出:
5
1 2 3 4 5
54321

代码

#include<stdio.h>

int main()
{

	int a[4],t,n,count=0,i=0;
	scanf("%d",&t);
	n=t;
	while(t)
	{
		a[count]=t%10;
		t/=10;
		count++;
	}
	printf("%d\n",count);
	for(i=count-1;i>0;i--)
	{
		printf("%d ",a[i]);
	}
	printf("%d\n",a[0]);
	
	while(n)
	{
		printf("%d",n%10);
		n=n/10;
	 } 
	return 0;
}


2. 字符串分类统计

题目描述

输入一行字符,分别统计出其中英文字母、数字、空格和其他字符的个数。

输入格式

一行字符,长度不超过200

输出格式

统计值

样例

输入:
aklsjflj123 sadf918u324 asdf91u32oasdf/.';123

输出:
23 16 2 4

代码

#include<stdio.h>
int main()
{
	int a=0,b=0,c=0,d=0;//a 英文,b 数字,c 空格, d 其他字符 
	char x;
	while((x=getchar())!='\n')
	{
		if(x>='a'&&x<='z'||x>='A'&&x<='Z')
		a++;
		else if(x>='1'&&x<='9')
		b++;
		else if(x==' ')
		c++;
		else d++;
	}
	printf("%d %d %d %d",a,b,c,d);
	return 0;
}


3. 筛选N以内的素数

题目描述

用简单素数筛选法求N以内的素数。

输入格式

N

输出格式

2~N的素数

样例

输入:
100

输出:
2
3
5
7
11
13
17
19
23
29
31
37
41
43
47
53
59
61
67
71
73
79
83
89
97

代码

#include <stdio.h>
int main()
{
	int i,j,n;
	scanf("%d",&n);
	for(i=2; i<n; i++)
	{
		for(j=2; j<i; j++)
		{
			if(i%j == 0)
			{
				break;
			}
		}
		
		if(j==i) //说明i只有1和j可整除
		{
			printf("%d\n",i);
		}
	
	}
	return 0;
}


4. 矩阵对角线求和

题目描述

求一个3×3矩阵对角线元素之和。

输入格式

矩阵

输出格式

主对角线 副对角线 元素和

样例

输入:
1 2 3
1 1 1
3 2 1

输出:
3 7

代码

//要点:1. sum初始化为0,否则得出第一个答案不对。
//2. for循环中给i和j赋值,不然换行时直接结束输入

#include <stdio.h>
int main()
{
	int i=0,j=0;
	int a[3][3];
	int sum1=0,sum2=0;
	for(i=0; i<3; i++)
	{
		for(j=0; j<3; j++)
		{
			scanf("%d",&a[i][j]);
		}
	}
	for(i=0; i<3; i++)
	{
		sum1 += a[i][i];
	}
	
	sum2 = a[0][2]+a[1][1]+a[2][0];
	
	printf("%d %d",sum1,sum2);
}

5.最大公约数与最小公倍数

题目描述

输入两个正整数m和n,求其最大公约数和最小公倍数。

输入格式

两个整数

输出格式

最大公约数,最小公倍数

样例

输入:5 7

输出:1 35

代码

//  辗转相除法求最大公因数:两个正整数a和b(a>b),它们的最大公约数等于a除以b的余数c和b之间的最大公约数。比如10和25,25除以10商2余5,那么10和25的最大公约数,等同于10和5的最大公约数。
//  最小公倍数:两数相乘的积除以这两个数的最大公约数

#include <stdio.h>
int main()
{
	int a,b,c,d,t,m;
	scanf("%d %d",&a,&b);
	if(a<b) 
	{
		t=a;
		a=b;
		b=t;
	}
	c = a%b;
	d = a*b;
	while(c != 0)
	{
		a = b;
		b = c;
		c = a%b;
	}
	m = d/b;
	printf("%d %d",b,m);
}


6.迭代法求平方根

题目描述

用迭代法求 平方根

公式:求a的平方根的迭代公式为: X[n+1]=(X[n]+a/X[n])/2 要求前后两次求出的差的绝对值少于0.00001。 输出保留3位小数

输入格式

X

输出格式

X的平方根

样例

输入:4

输出:2.000

代码

#include <stdio.h>
#include <math.h>
int main()
{
	int a;
	double x1,x2=1.0;
	scanf("%d",&a);
	do{
		x1 = x2;
		x2 = (x1+a/x1)/2;
	}while(fabs(x1-x2)>=0.0001);  //求浮点数x的绝对值
	printf("%0.3lf",x2);
	return 0;
}


7. 排序

7.1冒泡排序

题目描述

用冒泡法对10个整数从小到大排序。

输入格式

输入10个无序的数字

输出格式

排序好的10个整数

样例

输入:4 85 3 234 45 345 345 122 30 12

输出:
3
4
12
30
45
85
122
234
345
345

代码

#include <stdio.h>
int main()
{
	int t,i=0,j=0;
	int arr[10];
	for(i=0; i<10; i++) 
	{ 
		scanf("%d",&arr[i]);
	}
	for(i=0; i<10; i++)
	{
		for(j=0; j<9-i; j++)   //10个数,总共需要进行10-1次
		{	 // //10-1个数排完,第一个数一定已经归位
             //每次会将最大(升序)或最小(降序)放到最后面
				if(arr[j]>arr[j+1])  ////每次冒泡,进行交换
			{
				t = arr[j];
				arr[j] = arr[j+1];
				arr[j+1] = t;
			}
		}
	}
	for(j=0; j<10; j++)
		{
			printf("%d\n",arr[j]);
		}
	return 0;
}


 

7.2选择排序

题目描述

用选择法对n个整数从小到大排序。

输入格式

选择输入数字字数n,输入n个无序的数字

输出格式

排序好的n个整数

样例

输入:
10
4 85 3 234 45 345 345 122 30 12

输出:
3
4
12
30
45
85
122
234
345
345

代码

#include <stdio.h>
int main(void)
{
    int a[1001];
    int n,i,j,t;
    scanf("%d",&n);//n为要排序的数的个数
    //输入需要排序的数
    for(i=0;i<n;++i)
        scanf("%d",a+i);
    //接下来进行排序
    for(i=0;i<n-1;++i)//因为每次需要和a[i]后面的数进行比较,所以到a[n-2](倒数第2个元素)就行
    {
        for(j=i+1;j<n;++j)//j从i后一个开始,a[i]与a[j]进行比较
        {
            if(a[i]>a[j])//a[i]为当前值,若是比后面的a[j]大,进行交换
            {
                t=a[i];
                a[i]=a[j];
                a[j]=t;
            }
        }//每排序一次,就会将a[i](包括a[i])之后的最小值放在a[i]的位置
    }
	for(j=0;j<n;++j)
    printf("%d\n",a[j]);

    return 0;
}


 

--> C语言练习题(简单入门题)前言这篇文章是一些关于C语言的简单入门题,相关刷题网站为:https://www.dotcpp.com/1. 数字的处理与判断题目描述给出一个不多于5位的整数,要求 1、求出它是几位数 2、分别输出每一位数字 3、按逆序输出各位数字,例如原数为321,应输出123输入格式一个不大于5位的数字输出格式三行 第一行 位数 第二行 用空格分开的每个数字,注意最后一个数字后...

实现功能

1.录入(添加)学生信息:学号、姓名、平时成绩和考试成绩,总评成绩。
2.查询学生成绩:输入要查询的学生的学号,查询该学生的信息并显示。
3.显示学生成绩单:按学号顺序显示学生成绩单。
4.删除学生信息:输入要删除的学生的学号,,删除该学生的信息。
5.修改学生信息:输入要修改的学生的学号,显示该学生的原有信息,用户输入修改后的信息。

 

知识点

1.C语言的量声明和定义,以及变量初始化和生命周期与可见性
2.C语言指针的定义,初始化
3.C语言内存的申请和释放
4.C语言循环结构、选择结构、分支结构
5.C语言结构体
6.C语言数据结构之链表
7.C语言函数声明、实现、调用
8.C语言函数的参数、返回值
9.C语言文件打开、操作(读写)、关闭

代码

//宏定义区
#define _CRT_SECURE_NO_DEPRECATE  //防止VS警告

//头文件区
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>

//全局变量区
//学生结构体
typedef struct tagStudent
{
    char Num[10];//学号
    char Name[20];//姓名
    double Regular_Score;//平时成绩
    double Final_Score;//期末成绩
    double Total_Score;//总评成绩
}Student;

//学生链表结点
typedef struct tagNode
{
    Student Stu;//数据域:学生信息
    struct tagNode *pNext;//指针域:指向下一个学生结点
}Node;

//定义链表的第一个学生,即学生单链表的头结点
Node *g_pHead = NULL;

//全局函数定义区
// 打印功能菜单
void Print_Menu();
//1录入学生信息
void Enter_Students();
//2查询学生信息
Node* Inquire_Students();
//3显示学生信息
void Display_Students();
//4删除学生信息
void Deleting_Students();
//5修改学生信息
void Amend_Students();

//程序的主函数——程序入口
int main(int argc, char *argv[])
{
    while (1)//死循环
    {
        //清屏
        system("CLS");

        //打印功能菜单
        Print_Menu();

        char  ch;
        //控制台无回显获取信息
        ch = _getch();

        //switch分支选择结构
        switch (ch)
        {
        case'1': //1录入学生信息
            Enter_Students();
        break;

        case'2': //2查询学生信息
        {
            Node *pNode = Inquire_Students();
            if (pNode != NULL)
            {
                printf("%s\t %s\t %0.2lf \t%0.2lf \t%0.2lf\t\n",
                    pNode->Stu.Num,   //学号
                    pNode->Stu.Name, //姓名
                    pNode->Stu.Regular_Score,//平时成绩
                    pNode->Stu.Final_Score,  //期末成绩
                    pNode->Stu.Total_Score); //总评成绩
            }
            else
            {
                printf("未找到学生信息,请确认学生信息!\n");
            }
        break;
        }

        case'3': //3显示学生信息
            Display_Students();
        break;

        case'4': //4删除学生信息
            Deleting_Students();
        break;

        case'5': //5修改学生信息
            Amend_Students();
        break;

        case'0': //退出程序系统
            printf("欢迎再次使用!\n");
            return 0;
        break;

        default: //程序的健壮性,友好提示
            printf("您输入的选择有错误,请重新选择功能!\n");
        break;
        }
    system("PAUSE");
    }
    return 0;
}

//全局函数实现区
// 打印功能菜单
void Print_Menu()
{
    //清屏
    system("CLS");
    printf("=================================================\n");
    printf("===============欢迎使用高校学生管理系统==========\n");
    printf("=================================================\n");
    printf("===================请选择对应功能================\n");
    printf("=================================================\n");
    printf("=\t\t1、录入学生信息\t\t\t=\n");
    printf("=\t\t2、查询学生信息\t\t\t=\n");
    printf("=\t\t3、显示学生信息\t\t\t=\n");
    printf("=\t\t4、删除学生信息\t\t\t=\n");
    printf("=\t\t5、修改学生信息\t\t\t=\n");
    printf("=\t\t0、退出程序系统\t\t\t=\n");
    printf("=================================================\n");

    return;
}

//1录入学生信息
void Enter_Students()
{
    //清屏
    system("CLS");
    printf("=================================================\n");
    printf("===============欢迎使用高校学生管理系统==========\n");
    printf("=================================================\n");
    printf("===================录入学生信息功能================\n");
    printf("=================================================\n");
    printf("\n请依次输入学生信息:\n\n|学号 \t|姓名   |平时成绩|  |期末成绩|  |总评成绩|\n");

    //定义单链表的一个结点:当前结点
    Node *p;

    //将头结点给当前结点
    p = g_pHead;

    //在插入新结点前找到尾结点,
    while (g_pHead != NULL && p->pNext != NULL)
    {
        p = p->pNext;
    }

    //为新的学生元素分配一个空间
    //mallac  void*  泛类型   强制类型转换
    Node* pNewNode = (Node*)malloc(sizeof(Node));
    pNewNode->pNext = NULL;

    //将新节点插入尾结点或者作为头结点
    if (g_pHead == NULL)
    {
        g_pHead = pNewNode;
        p = g_pHead;
    }
    else
    {
        //p的下一个节点为pNewNode
        p->pNext = pNewNode;
    }

    //输入新的学生数据信息
    scanf("%s %s %lf %lf %lf", pNewNode->Stu.Num,        //学号  数组名就是数组首地址
        pNewNode->Stu.Name,                  //姓名
        &pNewNode->Stu.Regular_Score,    //平时成绩
        &pNewNode->Stu.Final_Score,      //期末成绩
        &pNewNode->Stu.Total_Score); //总评成绩

    printf("\n学生信息录入系统成功!\n");

    return;
}

//2查询学生信息
Node *Inquire_Students()
{
    //清屏
    system("CLS");
    printf("=================================================\n");
    printf("===============欢迎使用高校学生管理系统==========\n");
    printf("=================================================\n");
    printf("===================查询学生信息功能================\n");
    printf("=================================================\n");
    char Num[10]; //学号

    printf("\n请输入需要查询学生的学号:\n");

    scanf("%s",Num);

    Node  *p = g_pHead;
    printf("\n学号\t姓名\t平时成绩\t期末成绩\t总评成绩\t\n");

    //遍历链表
    while (p != NULL)
    {
        /*if (p->Stu.Num == Num) 字符数组不能比较
        需要字符比较      调用函数stricmp 以大小写不敏感方式比较两个串
        用法:int  stricmp( char  *str1,  char  *str2);
        返回值大于0,则str1>str2
        返回值小于0,则str1<str2
        返回值等于0,则str1=str2*/
        int  ptr = _stricmp(p->Stu.Num , Num);
        //如果找到学生信息
        if (ptr  ==  0)
        {
            return  p;
        }
        //否则继续找,直到遍历完链表退出while
        p = p->pNext;
    }

    //遍历完没有找到学生信息
    if (p == NULL)
    {
        return  NULL;
    }

    return  NULL;
}

//3显示学生信息
void Display_Students()
{
    //清屏
    system("CLS");
    printf("=================================================\n");
    printf("===============欢迎使用高校学生管理系统==========\n");
    printf("=================================================\n");
    printf("===================显示学生信息功能================\n");
    printf("=================================================\n");

    Node  *p = g_pHead;
    printf("学号\t| 姓名\t| 平时成绩\t| 期末成绩\t| 总评成绩\t|\n");

    //如果链表里没有学生信息
    if (p == NULL)
    {
        printf("未找到学生信息,请先录入学生信息!\n\n");
        return;
    }

    //如果链表里有学生信息,则遍历链表
    while (p != NULL)
    {
        printf("%s\t|  %s\t|  %0.2lf \t| %0.2lf \t| %0.2lf\t|\n",
                    p->Stu.Num,                  //学号
                    p->Stu.Name,                 //姓名
                    p->Stu.Regular_Score,    //平时成绩
                    p->Stu.Final_Score,      //期末成绩
                    p->Stu.Total_Score); //总评成绩);

        p = p->pNext;
    }
    printf("=================================================\n");
    return;
}

//4删除学生信息
void Deleting_Students()
{
    //清屏
    system("CLS");
    printf("=================================================\n");
    printf("===============欢迎使用高校学生管理系统==========\n");
    printf("=================================================\n");
    printf("===================删除学生信息功能================\n");
    printf("=================================================\n");
    char Num[10];  //学号

    printf("\n请输入需要删除学生的学号:\n");

    scanf("%s", Num);

    Node  *p = g_pHead;

    //定义一个临时变量结点
    Node  *p2 = NULL;

    //如果要删除的学生信息是链表的头结点
    int  ptr = _stricmp(g_pHead->Stu.Num , Num);
    if (ptr  ==  0)
    {
        p2 = g_pHead;
        g_pHead = g_pHead->pNext;
        //释放内存,删除信息
        free(p2);
        printf("删除学生信息成功!");
        return;
    }

    //删除的学生信息不是头结点
    while (p->pNext  !=  NULL)
    {
        int  ptr = _stricmp(p->pNext->Stu.Num, Num);
        if (ptr  ==  0)
        {
            p2 = p->pNext;
            p->pNext = p->pNext->pNext;
            //释放内存,删除信息
            free(p2);
            printf("删除学生信息成功!");
            return;
        }
        if (ptr != 0)
        {
            printf("学生信息不正确,请确认学生信息!");
        }
        //遍历链表
        p = p->pNext;
    }
    //遍历完没有找到学生信息
    if (p == NULL)
    {
        printf("未找到学生信息,请确认学生信息!\n\n");
    }
    return;
}

//5修改学生信息
void Amend_Students()
{
    //清屏
    system("CLS");
    printf("=================================================\n");
    printf("===============欢迎使用高校学生管理系统==========\n");
    printf("=================================================\n");
    printf("===================修改学生信息功能================\n");
    printf("=================================================\n");

    char Num[10];  //学号

    printf("\n请输入需要修改学生的学号:");

    scanf("%s", Num);

    Node  *p = g_pHead;

    //遍历链表
    while (p != NULL)
    {
        int  ptr = _stricmp(p->Stu.Num, Num);
        if (ptr  ==  0)
        {
            //显示要修改学生信息
            printf("=================================================\n");
            printf("%s\t|  %s\t|  %0.2lf \t| %0.2lf \t| %0.2lf\t|\n",
                p->Stu.Num,                  //学号
                p->Stu.Name,                 //姓名
                p->Stu.Regular_Score,    //平时成绩
                p->Stu.Final_Score,      //期末成绩
                p->Stu.Total_Score); //总评成绩);
            printf("=================================================\n");
            printf("请修改学生信息\n\n");
            printf("学号\t姓名\t平时成绩\t期末成绩\t总评成绩\t\n");
            scanf("%s %s %lf %lf %lf",
                p->Stu.Num,                  //学号
                p->Stu.Name,                 //姓名
                &p->Stu.Regular_Score,   //平时成绩
                &p->Stu.Final_Score,     //期末成绩
                &p->Stu.Total_Score);    //总评成绩
            printf("修改学生信息成功!\n");
            break;
        }
        //遍历链表
        p = p->pNext;
    }
    //遍历完没有找到学生信息
    if (p == NULL)
    {
        printf("未找到学生信息,请确认学生信息!\n\n");
    }
    return;
}

--> 实现功能1.录入(添加)学生信息:学号、姓名、平时成绩和考试成绩,总评成绩。2.查询学生成绩:输入要查询的学生的学号,查询该学生的信息并显示。3.显示学生成绩单:按学号顺序显示学生成绩单。4.删除学生信息:输入要删除的学生的学号,,删除该学生的信息。5.修改学生信息:输入要修改的学生的学号,显示该学生的原有信息,用户输入修改后的信息。 知识点1.C语言的量声明和定义,以及变量初始化和生命周期...