C基础总结

C第一讲 常识

1.c早起不成熟,是拿二进制和助记符(如add),后慢慢发展起来定义国际标准

2.C的编译器

​ 主要有:Clang、gcc、sublime、MSVC、Turbo c

3.基本知识:
(1) %c,%d,%lf,%p,%f,%s
//%c,%d,%lf,%p,%f
int main()
{
	//字符类型 char  %c打印字符格式数据
	char ch = 'A';//向内存申请8个bit大小的空间
	//短整型 short
	//%d 打印整数数
	//%f  打印浮点数--打印小数
    //%s 打印字符串
	float num = 52;
	printf("%f\n",num);
	printf("%lf\n",num);//一般用%lf
	int num1 = 36;
	//%p  以地址形式打印
	printf("地址是:%p\n", num1);
	//%x  打印十六进制数
	printf("%d的十六进制数是%x \n",num1,num1);
	//%o   打印八进制数
	printf("%d的八进制数是%o\n", num1,num1);

	return 0;
}
(2)类型的所占字节数

char:1字节

short:2byte

int:4 byte

long:4/8byte C语言标准规定:sizeof(long)>sizeof(int)就可以了

long long:8

float:4

double:8

	printf("%d\n", sizeof(char));
	printf("%d\n", sizeof(short));
	printf("%d\n", sizeof(int));
	printf("%d\n", sizeof(long));
	printf("%d\n", sizeof(long long));
	printf("%d\n", sizeof(float));
	printf("%d\n", sizeof(double));

加强版

	//数组名是首元素的地址
		// 1.sizeof(数组名)一数组名表示整个数组
		//2.&数组名–数组名表示整个数组
		//
		//一维数组
		int a[] = { 1,2,3,4}; //4 * 4 = 16.
		printf("%d\n", sizeof(a));//sizeof(数组名)-计算的是数组总大小-单位是字节-16
		printf("%d\n", sizeof(a + 0));//4/8~数组名这里表示收元素的值, a + 0还是首元素地址,地址的大小就是4 / 8个字节
		printf("%d\n", sizeof(*a));//4---表示首元素地址
		printf("%d\n", sizeof(a + 1));//4/8 ----数组名这里表示首元素的地址,a+1是第二个元素的地址,大小为4/8
		printf("%d\n", sizeof(a[1]));//4
		printf("%d\n", sizeof(&a));//4/8 &a取出的是数组的地址,但是数组的地址也是地址,地址的大小就是4/8
		printf("%d\n", sizeof(*&a));//4 ×  16√&a是数组的地址,数组的地址解引用访问数组,sizeof计算的就是数组的大小
		printf("%d\n", sizeof(&a + 1)); //4 /8 &a是数组的地址,&a+1虽然地址跳过了整个数组,但还是地址
		printf("%d\n", sizeof(&a[0])); //4 /8
		printf("%d\n", sizeof(&a[0] + 1));//4 /8

		//字符数组
		
		printf("%d\n", sizeof(arr));//6
		printf("%d\n", sizeof(arr + 0));//1×    4/8首元素的地址
		printf("%d\n", sizeof(*arr));//1 arr是首元素的地址,*arr就是首元素
		printf("%d\n", sizeof(arr[1]));//1
		printf(" %d\n", sizeof(&arr));//1×   4/8是数组的地址,但还是地址,地址大小就是4/8
		printf("%d\n", sizeof(&arr +1));//4  &arr+1 就是跳过整个数组后的地址,地址大小是4/8
		printf("%di\n", sizeof(&arr[0] + 1));//4 第二个元素的地址


		// 字符数组
		char arr[] = { 'a', 'b', 'c','d', 'e','f' };
		printf("%din", strlen(arr));//6× 随机值√
		printf("%d\n", strlen(arr + 0));//1× 随机值√
		printf("%d\n",strlen(*arr));//1× 程序报错,把首元素拿到是97,以97为首地址开始向后找\0,但是并不代表97可以被拿到		printf("%d\n", strlen(arr[1]));//2
		printf("%d\n",strlen(arr[1]));//error,原因同上
		printf("%d\n", strlen( &arr));//随机值
		printf("%d\n", strlen(&arr + 1));//随机值-6
		printf("%d\n",strlen( &arr[0] +1));//随机值-1
		
		char arr1[] = "abcdef";
		printf("%d\n", sizeof(arr1));//7 sizeof(arr)计算的是数组的大小,单位是字节
		printf("%d\n", sizeof(arr1 + 0));//4/8 arr+0是首元素的地址
		printf("%d\n", sizeof(*arr1));//1
		printf("%d\n", sizeof(arr1[1]));//1
		printf("%d\n", sizeof(&arr1));//4/8 &arr虽然是数组,但也是地址
		printf("%d\n", sizeof(&arr1 + 1));//4/8
		printf("%d\n", sizeof(&arr1[0] + 1)); //4/8

		printf("%d\n", strlen(arr1));//6   表示首元素地址
		printf("%d\n", strlen(arr1 + 0));//6 表示首元素地址
		printf("%d\n", strlen(*arr1));//1× 程序报错,把首元素拿到是97,以97为首地址开始向后找\0,但是并不代表97可以被拿到		printf("%d\n", strlen(arr[1]));//2
		printf("%d\n", strlen(arr1[1]));//error,原因同上
		printf("%d\n", strlen(&arr1));//6
		printf("%d\n", strlen(&arr1 + 1));//随机值
		printf("%d\n", strlen(&arr1[0] + 1));//5

		char* p = "abcdef";
		printf("%d\n", sizeof(p));//4/8-计算指针变量p的大小
		printf("%d\n", sizeof(p + 1));//4/8- p+1得到的是字符b的地址
		printf("%d\n", sizeof(*p));//1 *p就是字符串的第一个字符 'a'
		printf("%d\n", sizeof(p[0]));//1 int arr[10]; arr[0] = *(arr+0) p[0] =*(p+0)=='a'
		printf("%d\n", sizeof(&p)); //4/8
		printf("%d\n", sizeof(&p + 1));// 4/8
		printf("%d\n", sizeof(&p[0] + 1));//4/8 

4.单位

bit(b):比特位(最小的单位b)

Byte(B):字节(1Byte = 8bit)

KB: 1KB = 1024 byte

MB: 1MB = 1024 KB

GB 1GB = 1024 MB

TB: 1TB = 1024gGB

PB: 1PB = 1024TB

5.生命周期

局部变量的生命周期:进入作用域生命周期开始,出作用域生命周期结束

全局变量的生命周期:整个程序的生命周期

C第二讲 基本概念

1.常量

(1)常量

(2)由const修饰的 常量

const int n= 3;

(3)由#define定义

#define MAX 5

(4)枚举常量enum

enum Sex
{
	MALE,
	FEMALE,
	SECRET
};
	printf("%d", MALE);
	printf("%d",FEMALE);
	printf("%d",SECRET);
//该结果是:0 1 2

//大括号里面的枚举常量是不能改变的
enum Color
{
	RED,
	GREEN,
	BLUE
};
//而下面这种情变量则是则会改变的
	enum Color c = RED;
	c = GREEN;
2.字符和字符串

(1)字符:是由单引号引起的,长度是一个随机值,在后面找到结束符才结束

(2)字符串:是由双引号引起的,\0是字符串的结束标志,其值也为0,\0不计算在字符串长度内

	//"abc" ---放的有 'a','b','c' ,'\0'  \0是字符串的结束标志,其值也为0
	char arr1[] = "abc";
	char arr[] = {"abc"};
	
	char arr2[] = {'a','b','c'};
	//他两之间最后的结束标志不一定是\0 也可以是其他的(如:运行结果出来的烫),而加上0,是让它结束
	char arr3[] = {'a','b','c',0};
	printf("%s\n",arr);
	printf("%s\n", arr1);
	printf("%s\n", arr2);
	printf("%s",arr3);

	// 注意: \0不计算在字符串长度内
	printf("arrlen=%d\n", strlen(arr));
	printf("arr1len=%d\n",strlen(arr1));

	//'a','b','c'不知道后面是多少,长度是一个随机值,在后面找到结束符才结束
	printf("arr2len=%d\n",strlen(arr2));
	printf("arr3len=%d\n",strlen(arr3));

结果:

在这里插入图片描述

3.转译

(1)三字母词(现在不会有了)、\ddd、\xdd

​ 以前的语法中有三字母词,为了防止出现三字母词,出现了转译,例如

//例如,以前的 ??) 就是三字母词,为了不让它变成三字母词则出现了转译
	printf("(are you ok??)\n");
	printf("(are you ok\?\?)");
	printf("\n");

	//例如输出一个单引号,则需要转译,否则编译器会认为单引号不匹配会报错
	printf("%c",'\'');

	//注意: \t组合在一起是一个字符,\32是一个转义字符,两个八进制数字
	//注意:\ddd:表示1--3个八进制数。 则\32是八进制转为十进制: 3*8^1+2*8^0
	printf("%d\n", strlen("c:\test\32\test.c"));
	printf("%c\n",'\32');

	// \xdd ,dd表示2个十六进制数 6*16^1+9*16^0=96+9=105 97=a 105=i
	printf("%c\n",'\x69');
4.注释

C语言的注释风格/* */不支持嵌套

C++ 可以嵌套

5.位运算

左移、右移、位操作(与或非)0假1真

移位操作符:(1)<<:左移乘以2

​ (2)>>:右移除以2,右移操作符移动的是二进制位

int main()
{
	int a = -16;
	/*
		1.算数右移(一般是算数右移)
			右边丢弃,左边补原符号位
		2.逻辑右移
			右边丢弃,左边补0
		整数的二进制表示有:原码、、
							反码(符号位不变,其余按位取反)
							补码(反码+1)
		存储到内存的是补码
		如:a=-1
		原码:	1000 0000 0000 0000 0000 0000 0000 0001
		反码:  1111 1111 1111 1111 1111 1111 1111 1110
		补码:  1111 1111 1111 1111 1111 1111 1111 1111
				 f    f		f	f	  f		f	f	f				
				 1101
				 1110

	*/
	int b = a >> 1;
	printf("b=%d\n", b);

	/*
	2.左移操作符:左边丢弃,右边补0

	*/
	int c = -1;
	int d = c << 1;
	printf("d=%d",d);
	return 0;

按位与:有0 则0

按位或:有1则1,两0为0

按位异或:对应的二进制位相同,则为0;对应的二进制位相异,则为1

逻辑操作符:|| 、&&
int mytest()
{
	int i = 0;
	int a = 0, b = 2, c = 3, d = 4;
	//a 为0 ,为假,与上右边的都为假,故++b,d++不执行
	i = a++ && ++b && d++;
	printf(" a=%d\n b=%d\n c=%d\n d=%d\n",a,b,c,d);
	//所以结果是:1 2 3 4
	return 0;
}
int mytest1()
{
	int i = 0;
	int a = 1, b = 2, c = 3, d = 4;
	//a 为1 ,为真,与上右边的真都是真,故++b,d++执行
	i = a++ && ++b && d++;
	printf(" a=%d\n b=%d\n c=%d\n d=%d\n", a, b, c, d);
	//所以结果是:2 3 3 5
	return 0;
}
int mytest2()
{
	int i = 0;
	int a = 0, b = 2, c = 3, d = 4;
	//a 为0 ,为假,或上右边的++b为真,故d++不执行
	i = a++ || ++b || d++;
	printf(" a=%d\n b=%d\n c=%d\n d=%d\n", a, b, c, d);
	//所以结果是:1 3 3 4
	return 0;
}

int mytest3()
{
	int i = 0;
	int a = 1, b = 2, c = 3, d = 4;
	//a 为1 ,为真,只要有一个是真都是真,故++b,d++不执行
	i = a++ || ++b || d++;
	printf(" a=%d\n b=%d\n c=%d\n d=%d\n", a, b, c, d);
	//所以结果是:2 2 3 4
	return 0;
}
6.原码、反码、补码
int conv()
{
//只要是整数,内存中的存储都是二进制的补码
//正数:原码、反码、补码 都相同

//负数的:原码、反码、补码
//原码---》反码:原码符号位不变,其他位按位取反
//反码---》补码:反码+1得到补码

//补码--》反码:补码-1得到反码  
//反码--》原码:符号位不变,其他位按位取反

// ~取反
	int a = 0;//int 占4个 字节 = 32b
	// 1表示负数 ,0 表示整数
//0000 0000 0000 0000 0000 0000 0000 0000 
//~按位取反:1111 1111 1111 1111 1111 1111 1111 1111
//       -1:1111 1111 1111 1111 1111 1111 1111 1110
//符号位不变
//其他按位取反: 1000 0000 0000 0000 0000 0000 0000 0001
	int b = ~a;
	printf("%d", b);
	return 0;
}

//应用:
int compuwei()
{
	int a = -16;
	/*
		1.算数右移(一般是算数右移)
			右边丢弃,左边补原符号位
		2.逻辑右移
			右边丢弃,左边补0
		整数的二进制表示有:原码、、
							反码(符号位不变,其余按位取反)
							补码(反码+1)
		存储到内存的是补码
		如:a=-1
		原码:	1000 0000 0000 0000 0000 0000 0000 0001
		反码:  1111 1111 1111 1111 1111 1111 1111 1110
		补码:  1111 1111 1111 1111 1111 1111 1111 1111
				 f    f		f	f	  f		f	f	f
				 1101
				 1110

	*/
	int b = a >> 1;
	printf("b=%d\n", b);

	/*
	2.左移操作符:左边丢弃,右边补0

	*/
	int c = -1;
	int d = c << 1;
	printf("d=%d", d);
	return 0;
}

/*
交换两个数,不申请其他空间
思路:按位异或

*/
int change()
{

	//只能解决部分问题,使用加减法可能会造成溢出
	int a = 3;
	int b = 5;
	printf("before:a=%d,b=%d\n",a,b);

	a = a + b;//a=8
	b = a - b;//b=8-5=3
	a = a - b;//a=8-3=5
	printf("cahnge:a=%d,b=%d",a,b);
	return 0;

}

int change2()
{
	int a = 3;

	int b = 5;
	/*
		a=a^b;
		a = 011 
		b = 101
		a = 110

		b=a^b
		a=110
		b=101
		b=011

		a = a^b
		a=110
		b=011
		a=101

	*/
	printf("before:a=%d,b=%d\n",a,b);
	a = a ^ b;  
	b = a ^ b;
	a = a ^ b;
	printf("after:a=%d,b=%d",a,b);
	return 0;
}
/*
	求二进制中1的个数
*/
int count()
{
	int num,count=0;
	printf("please enter number:");
	scanf("%d", &num);
	int i;
	for (i = 0; i < 32; i++)
	{
		/*
		往右依次移动i位,第一次:如果最低位是1,与上1则是1,否则不是;
		第二次:向右移动1位
		0000 0000 0000 0000 0000 0000 0000 1000
		 0000 0000 0000 0000 0000 0000 0000 100
		  0000 0000 0000 0000 0000 0000 0000 10
		   0000 0000 0000 0000 0000 0000 0000 1
		*/
		if (1 == ((num >> i) & 1))
		{
			count++;
		}
	}
	return count;
}

整形提升
int demo()
{
	/*
		整形提升
		char a = 3;
		3是一个整型数,应该是32位
		a = 00000000 00000000 00000000 00000011
		b = 00000000 00000000 00000000 01111111
		c = 00000000 00000000 00000000 10000010

		而此时char是1个字节8个bit位,因此要发上截取
		a = 00000011
		b = 01111111
		c = 10000010


	char b = 127;
	char c = a + b;

	*/
	char a = 3;
	
	char b = 127;
	char c = a + b;
	//而打印出的是%d是原码
	/*
		则补码高位全符号位
		补码:11111111 11111111 11111111 10000010
		反码:11111111 11111111 11111111 10000001(补码减去1)
		原码:10000000 00000000 00000000 01111110(结果为-126)


	*/
	printf("%d\n",c);
	return 0;

}



//例子二
int demo1()
{
	char c = 1;
	printf("%u\n",sizeof(c));//1个字节
	printf("%u\n",sizeof(+c));//4个字节
	printf("%u\n",sizeof(!c));//1个字节
	return 0;
}
7.i++ 和 ++i
int test1()
{

	//++i 和 i++ 的区别
	int a = 10;
	int b = a++; //先试用在++  b=10,把a先试用了,然后a再+1
	printf("a=%d  b=%d", a, b);//a=11,b=10;
	int c = ++a;
	printf("a=%d ,b=%d", a, c);//a=12,b=12
	return 0;
}
8.static

(1)static修饰局部变量,局部变量生命周期变长,改变了其生命周期

(2)static 修饰全局变量,让静态变量只能在自己所在的源文件内部使用,出了源文件就没办法再使用,改变了其作用域

(3)不同的函数是有外部链接属性的(可以用extern引入),如果有static修饰则变成内部连接属性(不可引用)

int main()
{
	 int i = 0;
	while (i < 5)
	{
		test2();
		i++;
	}
	return 0;
}

int test2()
{
	//static 修饰局部变量,局部生命周期变长
	static int a = 1;
	a++;
	printf("%d \n", a);
	return 0;
}

//有static 修饰,结果是:2,3,4,5,6
//没有static修饰,结果是:2,2,2,2,2

9.指针大小在32位平台下4个字节,64位是8个字节

10.for ,while,do…while…

(1)for(表达式1;表达式2;表达式3) 先判断,后执行

​ 表达式1为初始化部分;表达式2为判断部分;表达式3为调整部分

for循环中的continue和break

​ continue:遇到continue会不执行本次循环中在continue后面的语句

​ break:遇到break则终止本次程序

​ for循环的初始化、调整、判断都可以省略,但是

(2)while先判断后执行

(3)do…while…先执行后判断

/*
当i=0时,j=0,1,2,3,4,5,6,7,8,9
最后j = 10
当i=1时,j=10;10<10不成立。所以结果只有十次
*/
int test3()
{

	int i = 0;
	int j = 0;
	for (; i < 10; i++)
	{
		for (; j < 10; j++)         //当i=0时,j=0,1,2,3,4,5,6,7,8,9
		{							//最后j = 10,
			printf("j=%d\t", j);
			printf("i=%d\n", i);
		}
	}
	return 0;
}

//循环多少次?
//答案,循环0次
//k=0;是赋值语句,0为假,一次也不执行
int test()
{
	int i = 0;
	int k = 0;
	for (i = 0, k = 0; k = 0; i++, k++)
	{
		k++;
		printf("i=%d,k=%d",i,k);
	}	
	return 0;
}


int test1()
{

	int i = 1;
	while (i <= 10)
	{
		if (i == 5)
		{
			continue;
		}
		printf("%d\n", i);
		i++;
	}
	return 0;
}

int test2()
{
	int i = 0;
	for (i = 1; i <= 10; i++)
	{
		if (i == 5)
		{
			break;
		}
		printf("%d", i);
	}
	return 0;

}

int test4()
{
	int i = 0;
	do
	{
		i++;
		printf("i=%d \n", i);
	} while (i < 10);
}


//结果是:1234+死循环 闪光表
int test5()
{
	int i = 0;
	do
	{
		if (i == 5)
		{
			continue;
		}
		printf("%d\n",i);
		i++;
	} while (i <= 10);

	return 0;
}

//计算n的阶乘
int test6()
{
	int i;
	int num;
	int   result = 1;
	printf("请输入num=:");
	scanf("%d", &num);
	for (i = 1; i <= num; i++)
	{
		result *= i;

	}
	printf("%d! = %d", num, result);
	return 0;
}

//计算n个数的阶乘
int test7()
{
	int j;
	int num;
	int   result = 1;
	int sum = 0;


	for (num = 1; num <= 3; num++)
	{
		result = 1;
		for (j = 1; j <= num; j++)
		{
			result *= j;
		}
		sum += result;

	}

	printf("sum=%d",sum);
	return 0;
}

//3.在一个有序数组中查找具体的某个数字n。编写int binsearch(int x, int v, int n);功能︰在v[0]<=v[1]<=v[2]<= ...<=v[n-1]的数组中查找x.
int binsearch()
{
	int a[] = { 0,3,4,5,6,9,18,27,36,55 };
	int key = a[6];
	int number;
	number = sizeof(a) / sizeof(a[0]);
	int left = 0;
	int right = number;
	while (left < right)
	{
		int mid = (left + right) / 2;
		if (a[mid] > key)
		{
			right = mid - 1;
		}
		else if (a[mid] < key)
		{
			left = mid + 1;
		}
		else
		{
			printf("找到了,下标是:%d", mid);
			break;
		}
	}

	return 0;
}

int test8()
{
	char arr1[] = "welcome to Guilin";
	char arr2[] = "#################";

	int left = 0;
// int right = sizeof(arr1) / sizeof(arr1[0])  - 2; 减去2是因为字符"abc" 其实是有 4 个字符,因为还有一个'\0' 故 -1 是字符长度 再-1是下标
	int right = strlen(arr1)-1;//数组的长度是strlen(arr1),下标是strlen(arr1)-1;
	while (left <= right)
	{
		arr2[left] = arr1[left];
		arr2[right] = arr1[right];
		printf("%s\n",arr2);
		Sleep(1000);//停止1s
		system("cls");
		left++;
		right--;
	}

}

C第三讲(递归、指针)

1.递归

​ 思想:大事化小

​ 递归常见错误:栈溢出

​ 栈区:局部变量、函数形参

​ 堆区:动态开辟内存 malloc

​ 静态区:全局变量,static修饰

(1)求数组的长度
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
//递归的方式
int my_strlen(char* str)
{
	int count = 0;
	if (*str != '\0')
		return 1 + my_strlen(str + 1);
}
//非递归的方式
int my_strlen1(char* str)
{
	char arr[] = "hello";
	int len = strlen(arr);//arr是数组,数组传参,才过去的不是整个数组,而是第一个元素的地址
	printf("len=%d", len);
	return 0;
}
int my_strlen2(char* str)
{
	int count = 0;
	while (*str != '\0')
	{
		count++;
		str++;
	}
	return count;
}
int main()
{
	char arr[] = "hello";
	my_strlen1(arr);
	printf("\n");
	my_strlen1(arr);
	printf("\n");
	int ret=my_strlen2(arr);
	printf("len=%d",ret);
	

	
	return 0;
}
(2)阶乘的计算
//计算n的阶乘
int fac1()
{
	int i;
	int num;
	int   result = 1;
	printf("请输入num=:");
	scanf("%d", &num);
	for (i = 1; i <= num; i++)
	{
		result *= i;

	}
	printf("%d! = %d", num, result);
	return 0;
}

//阶乘的递归
int fac(int n)
{
	if (n < 1)
		return 1;
	return n * fac(n - 1);
}

int main()
{
	int ret = fac(3);
	printf("ret=%d", ret);
	return 0;
}
(3)斐波那契数列
//斐波那契数列 fin(n+1)= fib(n)+fib(n-1)
//1 1 2 3 5 8
int fib(int n)
{
	
	int ret = 0;
	if (n <= 2)
		return 1;
	return fib(n - 1) + fib(n - 2);

}

//高效的斐波那契数
int Fiber(int n)
{

	int a = 1;
	int b = 1;
	int c = 0;
	while (n > 2)
	{
		c = a + b;
		a = b;
		b = c;
		n--;
	}
	return c;
}

int main()
{
	int ret=Fiber(50);
	printf("ret=%d",ret);
	return 0;
}

(4)qsort排序

//qsort排整型
/*
	第一个参数:待排序数组的首元素地址
	第二个参数:待排序元素的个数
	第三个参数:待排序数组的每个元素的大小,字节数
	第四个参数:是函数指针,比较两个元素所用函数的地址,这个函数使用者自己实现
				函数指针的两个参数是:待比较的两个元素的地址
*/
int cmp_int(const void* e1, const void* e2)
{
	return  *(int*)e1 - *(int*)e2;
}

//浮点型排序
int cmp_float(const void* e1, const void* e2)
{
	
	return (int)(*(float*)e1 - *(float*)e2);
}
int main()
{
	int arr[10] = {9,99,8,7,6,12,5,8,3,1};
	float arr1[10] = {3.6,5.7,6.3,3.2,5.4,9.9,78,23,6.6,8.7};
	int sz = sizeof(arr) / sizeof(arr[0]);
	qsort(arr1,sz,sizeof(arr[0]),cmp_float);
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%f\t",arr1[i]);
	}
}

第四讲 文件

(1)文件
文件的类型:

​ 根据数据的形式,数据文件被称为文本文件或者二进制文件。

​ 数据在内存中以二进制的形式存在,如果不加转换的输出到外存,就是二进制文件。

文件缓冲区:

​ 系统自动在内存中为程序中每一个正在使用的文件开辟一块“文件缓冲区”

输出数据:

​ 从内存向磁盘输出数据会先送达内存中的缓冲区,装满缓冲区后才一起送到磁盘上

读入数据:

​ 从磁盘文件中读取数据输入到内存缓冲区,当充满缓冲区,然后再从缓冲区逐个地将数据送到程序数据区。

缓冲区的大小根据C编译系统决定

文件指针:每个被使用的文件都在内存中开辟了一个相应的文件信息区,用来存放文件的相关信息

文件的读写:

	//绝对路径
	FILE* pf = fopen("D:\\input\\inputcombinetextinputformat\\a.txt","w");
	if (pf == NULL)
	{
		printf("%s\n",strerror(errno));
	}
	fputc('b', pf);
	fputc('i', pf);
	fputc('t', pf);
	
	fclose(pf);
	pf = NULL;

第五讲C习题day01

1.在VS2013下,这个结构体所占的空间大小是(12)字节

//1.在VS2013下,这个结构体所占的空间大小是()字节
typedef struct {
	int a; //0-3
	int b;//4
	//偏移到5
	short c;//5不是2的倍数 ,5浪费掉,偏移从6-7
	short d;//8-9   
	//故,一共10的字节,但是由于要是最大类型的整数倍,因此要浪费掉两个,变成12
}Siz;

int main()
{
	printf("%d",sizeof(Siz));
	return 0;
}
//结果是12

2.在VS2013下,这个结构体所占的空间大小是(16,12)字节

typedef struct  
{
	int a; //0-3
	short b;//4-5
	int c;//8-11
	char d;//12
}A; 
//0-12共13 ,故一共占16
typedef struct  
{
	int a;//0-3
	short b;//4-5
	char c;//6
	int d;//8-11

}B;
//12
int main()
{
	printf("%d ,%d",sizeof(A),sizeof(B));
	return 0;
}

3.在VS2013下,这个结构体所占的空间大小是(12,12,16)字节

int main(int argc, char* argv[])
{
	struct tagTest1 {
		short a; //0-1
		char d; //2
		long b; //4-7
		long c;//8-11
	};
	//12
	struct tagTest2 {
		long b; //0-3
		short c; //4-5
		char d; //6
		long a;//8-11
	};
	//12
	struct tagTest3 {
		short c;//0-1
		long b;//2-5× 4-7
		char d;//6× 8
		long a;//8-11× 12-15
	};
	//12错误× 16

	struct tagTest1 stT1;
	struct tagTest2 stT2;
	struct tagTest3 stT3;
	printf("%d,%d,%d",sizeof(stT1), sizeof(stT2), sizeof(stT3));
	return 0;
}

3.以下代码的结果是

int sum(int a)
{
	int c = 0;
	static int b = 3;// 
	c += 1;//c=1,
	b += 2;//b=5,7
	return (a + b + c);//2+5+1=8,
}
int main()
{
	int i;
	int a = 2;
	int result;
	for (i = 0; i < 5; i++)
	{
		result = sum(a);
		printf("%d\n", result);
	}
}
//result:8,10,12,14,16

4.指针逆序

void  reverse(char* a)
{
	int len = strlen(a);
	char* left = a;
	char* right = a + len - 1;
	while (left<right)
	{
		char temp = *left;
		*left = *right;
		*right = temp;
		left++;
		right--;
	}
}

int main()
{
	char arr[255];
	gets(arr);
	reverse(arr);
	printf("%s", arr);
	return 0;
}

5.求2,22,222,2222…之和

int main()
{
	int a;
	int n;
	int sum=0;
	int i;
	scanf("%d,%d",&a,&n);
	int ret=0;
	for (i = 0; i < n; i++)
	{
		ret = ret * 10 + a;
		sum += ret;
	}
	printf("%d",sum);
	return 0;
}

6.打印水仙花数

#include<math.h>
//水仙花数
int main()
{
	int i = 0;
	for (i = 0; i <= 100000; i++)
	{
		int n = 1;
		int sum = 0;
		int temp = i;
		while (temp /= 10)
		{
			n++;
		}
		temp = i;
		while (temp)
		{
			sum += pow(temp%10,n);
			temp /= 10;
		}
		if (i == sum)
		{
			printf("%d  ", i);
		}
		
	}
	return 0;
}


7.打印*

//6      *
//5     ***
//4    *****
//3   *******
//2  *********
//1 ***********
//0*************
//1 ***********
//2  *********
//3   *******   
//4    *****
//5     ***
    
int main()
{
	int line;
	printf("please enter line:");
	scanf("%d",&line);
	int i;
	for (i = 0; i < line; i++)
	{
		int j;
		for (j = 0; j < line - i - 1; j++)
		{
			printf(" ");
		}
		for (j=0;j<i*2+1;j++)
		{
			printf("*");
		}
		printf("\n");
	}
	for (i = 0; i < line; i++)
	{
		int k;
	
		for (k=0;k<=i;k++)
		{
			printf(" ");
		}
		for (k = 0; k < 2*(line-1-i)-1; k++)
		{
			printf("*");
		}
		printf("\n");
	} 

	return 0;
}


7.下列输出的结果是:li

struct stu {
	int num;
	char name[10];
	int age;
};

void fun(struct stu* p)
{

	printf("%s\n",(*p).name);
}

int main()
{
	struct  stu student[3] = {
		{001,"zhang",18},
		{002,"li",19},
		{003,"wang",20}
	};
	fun(student + 1);//student指向首地址,+1指向下一个,故对第二个信息进行解引用操作,拿出其姓名
	return 0;
}
//结果是:li

8.喝汽水问题,一瓶汽水1块,两个空汽水瓶换一瓶汽水

int main()
{

	int money = 0;
	int total = 0;//能喝多少瓶
	int empty = 0;//空瓶子
	printf("请输入钱数:");
	scanf("%d",&money);
	//买回来的汽水喝掉
	total = money;//可以喝掉money瓶
	empty = money;//空瓶子有money个
	//换回来的汽水
	while (empty>=2)//当空瓶子数量>2时
	{
		total += empty / 2;
		empty = empty / 2 + empty % 2;
			 
	}
	printf("可以喝:%d 瓶",total);
	return 0;
}

9.实现一个函数,使得所有基数为位于数组的前半部分

//实现一个函数,使得所有基数为位于数组的前半部分
void print(int arr[],int sz)
{
	int i;
	for (i = 0; i < sz; i++)
	{
		printf("%d\t",arr[i]);
	}

}

void move(int arr[], int sz)
{
	
	int left = 0;
	int right = sz - 1;
	int i = 0;
	while (left<right)
	{
		//从左边找一个偶数
		while ((left<right)&&(arr[left]%2==1))//数组全是基数,则走到数组最后还是基数,但是不加left<right,就会一直加,然后越界
		{
			left++;//当不能除尽说明是基数
		}
		//从右边找一个基数
		while ((left < right) && (arr[right]%2==0))
		{
			right--;
		}
		if(left<right)
		{		
			int temp = arr[left];
			arr[left] = arr[right];
			arr[right] = temp;
		}
	}
}
int main()
{
	int arr[] = {1,3,5,7,9,9,7,5,3,1};
	int sz = sizeof(arr) / sizeof(arr[0]);
	move(arr,sz);
	print(arr,sz);
	return 0;
}

5位运动员参加了10米台跳水比赛,有人让他们预测比赛结果:
A选手说:B第二,我第三;
B选手说:我第二,E第四;

C选手说:我第一,D第二;

D选手说:C最后,我第三;

E选手说:我第四,A第一;

比赛结束后,每位选手都说对了一半,请编程确定比赛的名次。

int main()
{
	int  a=0, b=0, c=0, d=0, e=0;
	for (a = 1; a <= 5; a++)
	{
		for (b = 1; b <= 5; b++)
		{
			for (c = 1; c <= 5; c++)
			{
				for (d = 1; d <= 5; d++)
				{
					for (e = 1; e <= 5; e++)
					{
						if (
							((b == 2) + (a == 3) == 1) &&
							((b == 2) + (e == 4) == 1) &&
							((c == 1) + (d == 2) == 1) &&
							((c == 5) + (d == 3) == 1) &&
							((e == 4) + (a == 1) == 1)
							)
						{
							if (a * b * c * d * e == 120)
							{
								printf("%d %d %d %d %d",a,b,c,d,e);
							}
						}

						
					}
				}
			}
		}
	}
	return  0;
}

11.关于下列代码描述正确的是:©

char* p=“hello word”;
A.把字符串hello word存放在p变量中
B.把字待串hello word的第一个字符存存放在p变量中
c.把字符串hello word的第一个字符的地址存放在p变量中
D.*p等价于hello word ×等价于h

12.下列结果是:(4,1)

int main()
{

	int a[5] = {5,4,3,2,1};
	int* ptr = (int*)(&a + 1);//数组的地址+1,是加了整个数组
	printf("%d %d", *(a + 1), *(ptr - 1));//4,1
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
链表是一种常用的数据结构,用于存储一系列元素。C语言中,链表是通过指针来实现的,每个节点包含数据和指向下一个节点的指针。 以下是链表的基础知识总结: 1. 链表的定义: ```c struct Node { int data; struct Node* next; }; ``` 其中,data 表示节点存储的数据,next 表示指向下一个节点的指针。 2. 链表的操作: - 创建节点: ```c struct Node* createNode(int data) { struct Node* node = (struct Node*) malloc(sizeof(struct Node)); node->data = data; node->next = NULL; return node; } ``` - 插入节点: ```c void insertNode(struct Node* head, int data) { struct Node* node = createNode(data); node->next = head->next; head->next = node; } ``` 其中,head 表示链表头节点。 - 删除节点: ```c void deleteNode(struct Node* head, int data) { struct Node* p = head->next; struct Node* q = head; while (p != NULL) { if (p->data == data) { q->next = p->next; free(p); break; } q = p; p = p->next; } } ``` - 遍历链表: ```c void traverseList(struct Node* head) { struct Node* p = head->next; while (p != NULL) { printf("%d ", p->data); p = p->next; } printf("\n"); } ``` - 销毁链表: ```c void destroyList(struct Node* head) { struct Node* p = head->next; while (p != NULL) { struct Node* q = p; p = p->next; free(q); } head->next = NULL; } ``` 3. 链表的优缺点: 链表的优点是插入和删除操作的时间复杂度为 O(1),而数组的时间复杂度为 O(n)。但是,链表的缺点是无法随机访问元素,需要遍历整个链表才能找到要查找的元素。此外,链表需要额外的空间来存储指向下一个节点的指针。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值