标签 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位的数字输出格式三行 第一行 位数 第二行 用空格分开的每个数字,注意最后一个数字后...

顺序栈

表示

#define MAXSIZE 100
typedef struct {
    SElemType *base; //栈底指针(表头端)
    SelemType *top;  //栈顶指针(表尾端)
    int stacksize;   //栈可用最大容量
}SqStack;

 

初始化

Status InitStack(SqStack &S) {
    //构造一个空栈
    S.base = (SElemType*)malloc(MAXSIZE*sizeof*(SElemType));
    if (!S.base) 
        exit (OVERFLOW);  //存储分配失败
    
    S.top = S.base;       //栈顶指针等于栈底指针
    S.stacksize = MAXSIZE;
    return OK;
}

 

判断是否为空

Status StackEmpty(SqStack S) {
    if (S.top == S.base)   //栈为空标志:S.top == S.base
        return TRUE;
    else
        return FALSE;
}

 

清空

Status ClearStack(SqStack &S) {
    if (S.base)
        S.top = S.base;
    return OK;
}

 

销毁

Status Destroy(SqStack &S) {
    if (S.base){
        free S.base;
        S.stacksize = 0;
        S.base = S.top = NULL;
    }
}

 

入栈

Status Push(SqStack &S, SElemType e) {
    if (S.top - S.base == S.stacksize) //栈满
        return ERROR;
    *S.top++ = e;   //*S.top = e; S.top++;
    return Ok;
}

 

出栈

Status Pop(SqStack &S, SElemType &e) {
    if (S.top == S.base)   //栈为空
        return ERROR;
    e = *--S.top;  //--S.top; e = *S.top
    return OK;
}

 

获取栈顶元素值

Status GetTop(SqStack S, SElemType &e) {
    if (S.top == S.base)
        return ERROR;
    e = *(S.top-1);
    return OK;
}

 

 

链栈

表示

  1. 链表的头指针就是栈顶
  2. 不需要头结点
  3. 基本不存在栈满的情况
  4. 空栈相当于头指针指向空
  5. 插入和删除仅在栈顶出执行
typedef struct StackNode {
    SElemType data;
    struct StackNode *next;
}StackNode, *LinkStack;
LinkStack S;

 

初始化

void InitStack(LinkStack &S) {
    S = NULL; //空栈,栈顶指针置空
    return OK;
}

 

判断是否为空

Status StackEmpty(LinkStack S) {
    if (S == NULL)
        return TRUE;
    else
        return FALSE;
}

 

入栈

Status Push(LinkStack &S, SElemType e) {
    StackNode *p;
    p->data = e;    //将新结点数据域置为 e
    p->next = S;    //将新结点插入栈顶
    S = p;          //修改栈顶指针
    return OK;
}

 

出栈

Status Pop(LinkStatck &S, SElemType e) {
    if (S == NULL)
        return ERROR;
    e = S->data;
    p = S;
    S = S->next;
}

 

C语言实现代码

顺序栈

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

#define MAX_SIZE 5    /* 栈最大容量 */
#define Empty 0        /* 空 */
#define Full 1        /* 满 */
#define Avail -1    /* 可用 */

typedef struct sta
{
    int *top;            /* 栈顶指针 */
    int *base;        /* 栈底指针 */
    int stacksize;        /* 栈的最大容量 */
}SqStack;

SqStack InitStack (SqStack p);    // 初始化栈
SqStack Push (SqStack p);        //入栈
SqStack Pop (SqStack p);        // 出栈
void DisplyStack (SqStack p);    // 遍历栈中元素
int StackEmpty (SqStack p);    // 判断栈是否为空
int StackFull (SqStack p);    // 判断栈是否为满

int main()
{
    SqStack p;
    char ch;

    p.stacksize = MAX_SIZE;
    p = InitStack (p);    /* 初始化栈 */

    //入栈
    printf("你想要添加元素吗到栈吗? (Y/N)\n");
    scanf(" %c", &ch);
    while (ch == 'Y' || ch == 'y')
    {
        p = Push (p);    /* 入栈 */
        DisplyStack (p);/* 打印栈中元素 */
        printf("你想要添加元素吗到栈吗?(Y/N)\n");
        scanf(" %c", &ch);
    }

    //出栈
    printf("你想出栈吗?(Y/N)\n");
    scanf(" %c", &ch);
    while (ch == 'Y' || ch == 'y')
    {
        p = Pop (p);
        DisplyStack (p);
        printf("你想出栈吗?(Y/N)\n");
        scanf(" %c", &ch);
    }
    return 0;
}

//初始化
SqStack InitStack (SqStack p)
{
    p.base = (int *)malloc(p.stacksize * sizeof(int));
    if (p.base == NULL)
    {
        printf("初始化栈失败\n");
        exit(0);
    }
    p.top = p.base;
    p.stacksize = MAX_SIZE;

    return p;
}

//入栈
SqStack Push (SqStack p)
{
    int data;
    if (StackFull(p) == Full)
    {
        printf("栈空间已满,无法入栈");
        return p;
    }
    printf("输入数字:");
    scanf("%d", &data);
    *p.top = data;
    p.top++;      //*p.top++ = data

    return p;
}

//出栈
SqStack Pop (SqStack p)
{
    int data;
    if (StackEmpty(p) == Empty)
    {
        printf("栈为空栈,无法出栈 ");
        return p;
    }
   // p.top--;
   // printf("出栈元素为:%d\n", *p.top);
     data = *--p.top;
     printf("出栈元素为:%d\n",data);
    return p;
}

//判断栈是否为空
int StackEmpty (SqStack p)
{
    if (p.top == p.base)
    {
        return Empty;
    }
    else
    {
        return Avail;
    }
}

//判断栈是否为满
int StackFull (SqStack p)
{
    if (p.top - p.base == p.stacksize)
    {
        return Full;
    }
    else
    {
        return Avail;
    }
}

//遍历栈中元素,从栈顶到栈底
void DisplyStack (SqStack p)
{
    if (StackEmpty(p) == Empty)
    {
        printf("栈为空栈,无法遍历\n");
        return;
    }
    printf("栈中元素为:\n");
    printf("顶端      [");
    while (p.top != p.base)
    {
        //p.top--;
        //printf("%d",*p.top);
        printf("%d", *--p.top);
    }
    printf("]       底端\n");
}

 

链栈

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

typedef struct lineStack {
    int data;
    struct StackNode *next;
}StackNode, *LineStack;

LineStack push(LineStack S, int a);  //入栈
LineStack pop(LineStack S);            //出栈

int main() {
    LineStack S = NULL;
    S = push(S, 1);
    S = push(S, 2);
    S = push(S, 3);
    S= push(S, 4);
    S = pop(S);
    S = pop(S);
    S= pop(S);
    S = pop(S);
    S = pop(S);
    return 0;
}


//入栈
LineStack push(LineStack S, int a) {
    //创建存储新元素的节点
    StackNode* line = (LineStack)malloc(sizeof(StackNode*));
    line->data = a;
    //新节点与头节点建立逻辑关系
    line->next = S;
    //更新头指针的指向
    S = line;
    return S;
}

//出栈
LineStack pop(LineStack S) {
    if (S) {
        //声明一个新指针指向栈顶节点
        StackNode* p = S;
        //更新头指针
        S = S->next;
        printf("出栈元素:%d ", p->data);
        if (S) {
            printf("新栈顶元素:%d\n", S->data);
        }
        else {
            printf("栈已空\n");
        }
        free(p);
    }
    else {
        printf("栈内没有元素(空栈)");
        return S;
    }
    return S;
}

 

 

--> 顺序栈表示#define MAXSIZE 100typedef struct { SElemType *base; //栈底指针(表头端) SelemType *top; //栈顶指针(表尾端) int stacksize; //栈可用最大容量}SqStack; 初始化Status InitStack(SqStack &S) { //构造一个空...