C/C++不常用知识点总结

一、C/C++不常用的知识点总结

  1.1 逗号表达式
int a;
a = (3, 4);  //========>  a = 4; 取逗号后面的一个元素
a = 3, 4;    //========>  a = 3; ‘=’优先级高于‘,’
// 逗号运算符的优先级较低

试分析下面代码中的z,x,y的值是多少?

int main()
{
	int x, y, z;   
	x=y=1;
	z=x++,y++,++y;     // ‘=’优先级高于‘,’,z = x = 1;
	printf("%d,%d,%d\n", x, y, z);
	return 0;
}
// x=2, y=3, z=1

试分析下面代码中的z,x,y的值是多少?

int main()
{
	int x, y, z, m=0;
	x = y = 1;
	m = (z = x++, y++, ++y);    //m = (1, 1, 3) ====>m = 3
	m = (++y, y++, z = x++);    //m = (4, 4, 2)
	m = (++y, z = x++, y++);    //m = (6, 3, 6)
	printf("%d,%d,%d, %d\n", x, y, z, m); // x = 4, y = 7, z= 3, m=6;
	return 0;
}
   1.2 scanf_s()和printf()的返回值

    scanf_s()返回正确输入元素的个数,printf()返回输出字符的个数。

#include<stdio.h>

int main()
{
	int x, y, z, u;
	u = printf("Input two integers:\n");  // u = 20, (汉字占两个字符)
	z = scanf("%d %d", &x, &y);           // 正确输入两个整数时,会返回2
	puts("printf的返回值:");
	printf("%d\n", u);

	puts("scanf_s的返回值:");
	printf("%d\n", z);

	return 0;
}

scanf_s()函数与scanf()函数的区别:
  (1) scanf_s(“%s”, s, 6)的最后一个参数为输入缓冲区的大小,表示最多读取6-1个字符, s[5]要放’\0’,也即scanf_s()函数会检查边界,不会出现内存访问越界的情况。
  (2) scanf()在读取时不检查边界,所以可能会造成内存访问越界,例如分配了4字节的空间但是读入了6字节数据,具体见如下代码所示。

char s[4];
scanf("%s", s);   // 输入:abcdef
// 输入:abcdef 时, def部分会被写到别的空间上去。
   1.3 scanf()+while()示例
// 提示用户输入一个数字,用户输入字符怎么办?
#include<iostream>
#include<cstdio>
using namespace std;

int main()
{
	int num;
	char ch;
	printf("Please enter an integer:\n");
	while (scanf("%d", &num) != 1)          // 未正确输入一个整数,则继续执行。
	{
		while ((ch = getchar()) != '\n')   // 清空缓冲区中的字符
		{
			putchar(ch);
		}
		printf(" is not an intger.\nPlease enter an intger value, such"
				"as 25, -1, 3. : _\b");
	}
	printf("%d\n", num);
	return 0;
    
}
   1.4 浮点型也可以这样初始化

      float m = .2, n = .8e5, k = 100.; //后面加上空格之后就无法正常编译

   1.5 用#define定义一个函数
#include<stdio.h>
#define SQUARE(x) x*x
int main()
{
	int a = 5;
	printf("SQUARE(a): %d\n", SQUARE(a));    
	printf("SQUARE(a+1): %d\n", SQUARE(a + 1)); //想一下为什么输出值是11
	return 0;
	// SQUARE(a + 1)等价于==>a+1*a+1=5+1*5+1=11
}

二、数组

   2.1 数组的定义初始化
数组的定义:
	int arr[5];           char ch[3];
初始化:
	a[5] = {1,2,3,4,5};   ch[3] = “abc”;
定义时初始化:
	int a[5] = {1,2,3,4,5};  char ch[3] = “abc”;
	int a[]  = {1,2,3,4,5};   char ch[]  = “abc”;
注意:
	int char ch = "hdfkakfafd";   编译器会自动在末尾添上'\0',但是在计算字符串的长度时,并不会计算’\0’;
	int str[3] = {'a', 'b', 'c'}; 则不会在末尾添加'\0'
   2.2 用sizeof()求出数组长度

      eg:利用sizeof()对数组赋初值

#include<stdio.h>
int main()
{
	int arr[4] = {0, 0, 0, 0};
	printf("请输入%d个数:\n", (sizeof(arr) / sizeof(int)));  //计算数组的长度
	for (int i = 0; i < (sizeof(arr) / sizeof(int)); i++)    
	{
		scanf_s("%d", &arr[i]);
	}
	putchar('\n');
	puts("输出:");
	for (int i = 0; i < (sizeof(arr) / sizeof(int)); i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}
   2.3 变长数组

      变长数组需要引入头文件<stdlib.h>—>malloc()/calloc()
      利用malloc()和calloc()创建一维边长数组

// 利用malloc()和calloc()创建一维边长数组
#include<stdio.h>
#include<stdlib.h>
int main()
{
	int* arry = NULL;   // 初始化数组指针
	int arr_len;        // 数组长度
	int i;
	printf("请输入数组的长度:\n");
	scanf_s("%d", &arr_len);
	printf_s("%d\n", arr_len * sizeof(int));
	arry = (int*)malloc(arr_len * sizeof(int));  // array指向长度为arr_len的整型数组首地址
	//arry = (int*)calloc(arr_len , sizeof(int));
	if (arry == NULL)
	{
		printf("分配内存失败\n");
	}
	else {
			printf("请输入%d个数:\n", arr_len);
			for (i = 0; i < arr_len; i++)
			{
				scanf_s("%d", &arry[i]);
			}
				putchar('\n');
				puts("输出:");
			for (i = 0; i < arr_len; i++)
			{
				printf_s("%d\t", *(arry+i));
			}
		}
	free(arry);
	return 0;
}

      利用malloc()和calloc()创建二维边长数组

// 实质还是一维数组
#include<stdio.h>
#include<stdlib.h>
int main(){
    int  row, col;
    scanf("%d %d", &row, &col);
    int *arr = (int *)malloc(row*col*sizeof(int));   // arrr指向长度为row*col的整型数组首地址, 实质为一维数组
    if (arr){
        for (int i=0; i<row; i++){
            for (int j=0; j<col; j++){
                //scanf("%d", arr + i*col +j);
                *(arr +i*col +j) = i*col +j;
            }
        }
        // 输出  
        for (int i=0; i<row; i++){
            for (int j=0; j<col; j++){
                //scanf("%d", arr + i*col +j);
                printf("%d\t", *(arr + i*col +j));
            }
            puts("");
        }
    }
    else puts("分配内存失败!");
    free(arr);

    return 0;
}
// 利用二级指针和一级指针开辟二维数组
#include<stdio.h>
#include<stdlib.h>
int main()
{
	int *adr_l = NULL, **adr_r = NULL;
	int row, col, i = 0, j = 0;

	printf("Please input the length of row and col:");
	scanf("%d %d",&row,&col);

	//adr_l = (int *)calloc(len_l, sizeof(int));
	adr_r = (int **)calloc(row, sizeof(int));  // 指向行的
	for(i = 0; i < row; i++)
	{
		adr_r[i] = (int *)calloc(col,sizeof(int)); // 指向列
	}
	for(i = 0; i < row; i++)
	{
		for(j = 0; j < col; j++)
		{
			adr_r[i][j] += (j + 1);
			printf("%2d",adr_r[i][j]);
		}
		printf("\n");
	}

	for(i = 0; i < row; i++)
	{
		free(adr_r[i]);

	}   free(adr_r);

    return 0;
}
// 二级指针为指向指针的指针, 一级指针存放的是变量的地址,而二级指针则是存放的一级指针的地址。
// calloc()创建的数组时,会将数组元素初始化为0。
// malloc()创建数组时,则是随机初始化元素。
   2.3 十大经典排序

      冒泡排序

// 对数组值操作
#include<stdio.h>
int main()
{
	int arr[] = { 1, 23, 0, -1, 90, 9, 34, 7 };
	int temp;
	for (int i = 0; i < (sizeof(arr) / sizeof(int)); i++)
	{
		printf("%d\t", arr[i]);
	}
	putchar('\n');
	for (int i=0; i<(sizeof(arr)/sizeof(int)); i++)
	{
		for (int j=i+1; j < (sizeof(arr) / sizeof(int)); j++)
		{
			if (arr[i] > arr[j])
			{
				temp = arr[i];
				arr[i] = arr[j];
				arr[j] = temp;
			}
		}
		printf("%d\t", arr[i]);
	}
}

      选择排序

// 找到最小值索引,对数组索引操作
#include<stdio.h>
int main()
{
	int arr[] = { 1, 23, 0, -1, 90, 9, 34, 7 };
	int temp, minindex;
	for (int i = 0; i < (sizeof(arr) / sizeof(int)); i++)
	{
		printf("%d\t", arr[i]);
	}
	putchar('\n');
	for (int i=0; i<(sizeof(arr)/sizeof(int)); i++)
	{	
		minindex = i;
		for (int j=i+1; j < (sizeof(arr) / sizeof(int)); j++)
		{
			if (arr[j] < arr[minindex])
			{
				minindex = j;
			}
		}
		temp = arr[i];
		arr[i] = arr[minindex];
		arr[minindex] = temp;
		printf("%d\t", arr[i]);
	}	
}

      插入排序

#include<stdio.h>
int main()
{
	int arr[] = { 1, 23, 0, -1, 90, 9, 34, 7 };
	int current, pre_index;   // current 表示当前值,pre_index表示当前值前面值的索引
	int i, j;
	// 排序前
	for (i = 0; i < (sizeof(arr) / sizeof(int)); i++)
	{
		printf("%d\t", arr[i]);
	}
	putchar('\n');
	// 插入排序
	for (i = 1; i < (sizeof(arr) / sizeof(int)); i++)
	{
		pre_index = i - 1;   // 当前值前一个值的索引
		current = arr[i];    // 当前值
		while (arr[pre_index] > current && pre_index >= 0)   // 当数组中前一个值大于当前值或pre_index>=0就继续往找
		{
			arr[pre_index + 1] = arr[pre_index];  // 将数组前面所有大于当前值的位置顺次往后移动一位
			pre_index--;      // 继续往前找
		}
		arr[pre_index + 1] = current; // 将当前值插入到pre_index+1位置处
	}
	// 插入排序后
	for (int i = 0; i < (sizeof(arr) / sizeof(int)); i++)
	{
		printf("%d\t", arr[i]);
	}
	putchar('\n');
	return 0;
}
   2.4 找出数组中重复数字

题目描述:
在一个长度为n的数组nums里的所有数字都在0~n-1范围内。数组的某些数字是重复的,但是不知道有几个数字重复,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。
示例:
输入:
[2, 3, 1, 0, 2, 5, 3]
输出:2 3

// 利用数组元素与下标之间的映射关系
#include<stdio.h>
int main()
{
	int nums[] = {2, 3, 1, 0, 2, 5, 3};     // 输入数组
    int re_nums[100], temp = 0, len=0;      // re_nums[]存放重复元素的数组, temp为临时变量, len统计重复元素的个数
	// 打印输入数组
    for (int i=0; i<sizeof(nums)/sizeof(int); i++){
        printf("%d ", nums[i]);
    }
    putchar('\n' );

	// 输入数组的范围为0~n-1, 可利用数组元素与下标之间的映射关系查找重复元素
    for (int i=0; i<(sizeof(nums)/sizeof(int)); i++){  // 遍历输入数组中的元素
        while (nums[i] != i) {                // 当前索引与索引对应的元素值不相等时,执行。
            if (nums[nums[i]]  != nums[i]){   // 如果以nums[i]为索引的元素(nums[nums[i]])不等于时,执行。
                temp = nums[nums[i]];         
                nums[nums[i]] = nums[i];      // 将arr[i]放置到以arr[i]为索引的位置处
                nums[i]  = temp;              // 将nums[nums[i]]的值放置在以i为索引的位置处
            }else {                           // 找到重复元素
				re_nums[len++] = nums[i];     // 将重复元素放置到相应数组中
				 break;                       // 找到重复元素后必须跳出while()循环,否则会一直执行rec_nums[len++] = nums[i];
			}
        }
		printf("%d ", nums[i]);
    }
	// 输出重复元素
	putchar('\n');
    for (int i = 0; i<len; i++) {
        printf("%d ", re_nums[i]);
    }

    return 0;
}

三、指针

   3.1 指针的定义和初始化

      指针也是变量,它是用来存储地址的变量,指针变量本身也有地址。

//指针的定义:
 int *p;
 
//初始化:
int a = 3;  p = &a;

//同时也可以在定义时声明:
int *p = &a;  
 
//指针数组:
int *p[3]    //指针数组,[]的优先级高于*
int (*p)[3]  //指向列为3的二维数组指针
   3.2 指针与二维数组的关系
#include<stdio.h>
int main()
{
	int a[4][2]={{2,4},{6,8},{1,3},{5,7}};   
	int(*p)[2];            
	p = a;                 
	printf("  a     = %p,  a+1  = %p\n",a, a+1);
	printf("  p     = %p,  p+1  = %p\n", p, p + 1);
	printf("a[0]    = %p,a[0]+1 = %p\n",a[0], a[0]+1);
	printf("p[0]    = %p,p[0]+1 = %p\n", p[0], p[0] + 1);
	printf("  *a    = %p,  *a+1 = %p\n",*a, *a+1);
	printf("  *p    = %p,  *p+1 = %p\n", *p, *p + 1);
	printf("a[0][0] = %d\n", a[0][0]);
	printf("  *a[0] = %d\n", *a[0]);
	printf("  **a   = %d\n", **a);
	printf("a[2][1] = %d\n", a[2][1]);
	printf("*(*(a+2)+1) = %d,\n",*(*(a+2)+1) );
	
	return 0;
}
   3.3 两数之和

题目:
给定一个整数组nums和一个目标target,请在该数组中找出和为目标值的那两个整数,并返回他们的数组下标。假设每个输入的数组只对应一个target,且数组中的同一个元素不能用两次。
示例:
给定nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回元素下标[0, 1]

// 两重循环解决-暴力解法
#include<stdio.h>
#include<stdlib.h>
int main()
{
	int nums[] = { 2, 7, 11, 15 };
	int target = 9;
	int i, j;
	int* ans = NULL;
	for (i = 0; i < sizeof(nums) / sizeof(int); i++)
	{
		printf("%d\t", nums[i]);
	}
	putchar('\n');
	for (i = 0; i < (sizeof(nums) / sizeof(int) - 1); i++)
	{
		for (j = i + 1; j < (sizeof(nums) / sizeof(int)); j++)
		{
			if (target == nums[i] + nums[j])
			{
				ans = (int*)malloc(sizeof(int) * 2);
				ans[0] = i;
				ans[1] = j;
			}
		}
	}
	for (i = 0; i < 2; i++)
	{
		printf("%d\t", ans[i]);
	}
	free(ans);
}

     用函数对核心功能进行封装:

#include<stdio.h>
#include<stdlib.h>
int* twoSum(int* nums, int numsSize, int target, int* returnSize);

int main()
{
	int nums[] = { 2, 7, 11, 15 };
	int target = 9;
	int i;
	int* ans = NULL;
	int returnSize = 0 ;
	for (i = 0; i < sizeof(nums) / sizeof(int); i++)
	{
		printf("%d\t", nums[i]);
	}
	putchar('\n');
	ans = twoSum(nums, sizeof(nums) / sizeof(int), target, &returnSize);
	for (i = 0; i < returnSize; i++)
	{
		printf("%d\t", ans[i]);
	}
	free(ans);
}

int* twoSum(int* nums, int numsSize, int target, int* returnSize) 
{
	int i, j;
	for (i = 0; i < numsSize - 1; i++)
	{
		for (j = i + 1; j < numsSize; j++)
		{
			if (target == (*(nums + i) + *(nums + j)))
			{
				int* ans = (int*)malloc(sizeof(int) * 2);
				ans[0] = i, ans[1] = j;
				*returnSize = 2;
				return ans;
			}
		}
	}
	*returnSize = 0;
	return NULL;
}

备注:在写for循环时,尽量不要有函数,如有函数,该函数会被执行多次。如:

int main(){
	char s[]="dfafa";
	for (int i=0; i<strlen(s); i++){  // strlen()函数利用循环求解字符串的长度,而for循环每次都会执行strlen(s)==>浪费时间
		printf("%c", s[i]);
	}
	return 0;
}

四、参考链接

  1、十大经典排序方法
  2、创建二维可变长数组
  3、两数之和
  4、数组中重复数字

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值