精华内容
下载资源
问答
  • c语言进阶

    2021-05-27 10:31:45
    C语言进阶变量表达式宏宏风险枚举用法结构体联合体 32位系统 char 1 short 2 int 4 long 4 float 4 无符号 double 8 无符号 const * 左定值 * const 右定项 变量 表达式 --,++只能用于变量 --- sizeof 返回无...


    32位系统

    char 1
    short 2
    int 4
    long 4
    float 4  无符号
    double 8 无符号
    
    const * 左定值
    * const  右定项
    

    变量

    在这里插入图片描述
    在这里插入图片描述

    表达式

    --,++只能用于变量
    ---
    sizeof 返回无符号
    有符号和无符号运算,首先自动转成无符号
    

    在这里插入图片描述
    在这里插入图片描述

    int m=2,n=3;
    int k = m+++n;//先用m再自加
    m=3,n=3,k=5;
    
    int m=5;
    int n=3;
    int k=m+++-+-+--n;
    m=6,n=2,k=(m++)(+)(-)(+)(-)(+)(--n)=7
    

    1.常量替换
    #define MAX_CLASS 10
    
    2.类型定义
    #define INTEGER int
    
    3.宏函数(参数需要用()括起来)
    容易引发优先级低的问题
    #define MAX(x,y) (((x)>(y))?(x):(y))
    
    4.防止头文件重复包含
    #ifndef TEST_H
    #define TEST_H
    #include "xxx.h"
    #ifdef _cplusplus
    //下面的代码是用c语言进行声明和定义的
    //如果不加,那么头文件的编译方式由include此头文件的源文件决定
    extern "C"{
    #endif
    //头文件内容
    #ifdef _cplusplus
    }
    #endif
    #endif
    
    5. 内定调试宏
    _LINE_:当前代码行数
    _FILE_:当前源文件名
    _DATE_:当前日期
    _TIME_:当前时间
    

    宏风险

    1. 容易引发优先级低的问题
    参数需要用()括起来
    
    2.多次运算
    参数为函数的时候
    
    3.同一个宏名字多处定义
    
    4.宏空格
    #define func (x) (x+1)
    

    在这里插入图片描述

    宏函数运行顺序

    #define PT = 3.5;
    #define S(x) = PT * x * x;
    S(1+2) = 3.5*1+2*1+2=7.5//这才是要加括号的原因
    

    枚举

    枚举的大小和编译器,编译选项有关
    
    建议:
    1. 不要使用枚举的大小(与编译器有关)
    2. 枚举的值不要超过32位
    

    在这里插入图片描述
    在这里插入图片描述

    用法

    用于声明一组常数。当一个变量有几个固定的可能取值时,可以将这个变量定义为枚举类型

    enum Season {spring, summer, autumn, winter} s;
    s = spring; // 等价于 s = 0;
    s = 3; // 等价于 s = winter;
    

    结构体

    结构体对齐

    1. 运行速度更快
    2. 指针从基地址读取数据可能出错
    3. 结构体直接赋值可能会出错
    

    结构体大小

    //20
    typedef struct{
       int (*a[5])();
    }Foo1;
    //8
    typedef struct{
       int (*a)[5];
       char b;
    }Foo2;
    //20
    typedef struct{
       int a[5];
    }Foo3;
    //20
    typedef struct{
       int *a[5];
    }Foo4;
    
    typedef struct{
    	u8 a;
    	u8 b;
    	u8 c;
    }TEST;
    TEST = test{1,2,3};
    u16 usShort;
    u32 ulInt;
    usShort = *(U16*)&test.a;
    usShort = *(U16*)&test.b;
    ulInt = *(U32*)&test.c;
    是否出错和cpu以及编译器相关
    

    在这里插入图片描述
    解决方法

    1.自然对齐
    	(1)成员按照8,4,2,1顺序排列
    	(2)不够对齐的字段用保留字段填充
    2.预编译对齐 #pragma pack(n)
    3.不对齐结构不用非同类型指针访问,不进行类型转换
    4.尽量不对结构体进行直接赋值,使用memcpy拷贝整个结构体
    

    如何对齐

    1.以自身最大的为自身对齐值
    2.自身对齐值与指定对齐值中的小值
    

    注意:

    1.0长度的数组不占用空间
    b[0],b[]:直接通过b访问后面结构体内存
    

    联合体

    同一个内存空间存储不同的数据类型

    小端模式
    高字节在高地址,低字节在低地址
    

    联合体赋值时,短数据赋值之后,长数据的空余位数据未知

    基本用法

    typedef union
    {
    	unisigned int a;
    	unisigned int b;
    }TEST_U1;
    
    当u1.a = 0x12345678;
    u1.b = 0x12345678;
    
    typedef struct
    {
    	unisigned char a;
    	unisigned char b;
    	unisigned char c;
    	unisigned char d;
    }TEST_S3;
    
    typedef union
    {
    	unisigned int a;
    	unisigned char b;
    	unisigned short c;
    }TEST_U2;
    
    当 u2.a = 0x12345678
    u2.b = 0x78;
    u2.c = 0x5678;
    
    typedef union
    {
    	unisigned int a;
    	TEST_S3 b;
    }TEST_U3;
    

    在这里插入图片描述

    当 u3.a = 0x12345678;
    u3.b.a = 0x78;
    u3.b.d = 0x12;
    

    联合体大小

    最大字段的大小
    

    函数

    函数定义声明

    int Tesy1();
    void Test(int num,char array[]);
    函数指针
    typedef int (*PFUN)();
    PFEUN pf = Test1;
    

    函数入参

    在这里插入图片描述

    1 4 4 4
    全是指针,数组的定义其本质都是指针
    

    inline函数

    目的

    a)没有调用开销,效率高
    b)是真正的函数,编译器会监测参数类型,消除宏函数隐患
    c)太复杂或调用点太多,展开后会导致代码膨胀带来的恶化可能大于效率提升带来的益处
    
    a)只是对编译器的建议,编译器可以忽略
    b)在调用内联函数时,要保证内联函数的定义让编译器看到,即在头文件中定义内联函数,这与通常的函数定义不一样
    

    static函数

    static int Test1();
    

    目的

    a)限定作用域,只能被本文件中其他函数调用,不能被同一程序其他文件中的函数调用
    

    extern函数

    extern int Test1();
    

    目的

    a)函数和变量前,表示变量或函数的定义在其他文件中,
      提示编译器遇到此变量和函数字其他模块中寻找定义
    b)取代include "*.h"来声明函数
    c)extern "C"
       C++在编译时为解决函数多态问题,会讲函数名和参数联合起来生成一个中间的函数名,
       而c语言不会,因此会导致链接时找不到对应函数的情况。
    

    在这里插入图片描述
    链接: link.

    数组与指针

    指针

    char ch = 'c';
    char *pch = &ch;
    char *pStr = "abc";//pStr[1] = b (*pStr+2)
    
    int m;
    int *pm = &m;
    
    struct Test stTest;
    struct Test *pst = &stTest;
    
    //函数指针
    extern void TestFunc(int m);
    void (*pf)(int) = TestFunc;
    
    int *(*a[5])(int, char*);  
    =
    typedef int* (*f)(int,char*);
    f a[5];
    a是个5个元素的数组,每个元素为函数指针.
    

    函数指针

    #include <stdio.h>
    #include <stdlib.h>
     
    int* (*a[5])(int,char*);
     
    int *foo(int n, char *s)
    {
    	int *p;
     
    	p = (int *)malloc(sizeof(int));
    	*p = n + atoi(s);
     
    	return p;
    }
     
    int main(int argc, char *argv[])
    {
    	int *p;
     
    	a[0] = &foo;
    	p = (*a[0])(1, "2");
     
    	printf("%d\n", *p);//3
     
    	return 0;
    }
    

    链接: link.

    指针的大小

       int ll[6];
       //注意*ll[3] = ll[3];int数组
       //数组指针
       int (*l)[3]=&ll;
       int p[5];
       printf("%d\n",sizeof(l));
       printf("%d\n",sizeof(*l));
       printf("%d\n",sizeof(p));
       return 0;
    

    结果
    在这里插入图片描述

    指针数组的首地址长度是4;
    指针数组取地址是指针数组的大小12;
    数组则是指定的大小20;

    指针类型转换

       int a[5] = {1,3,5,7,9};
       char *p = a;
       int *t = (int *)p;
       printf("%d %d %d %d",*p,*(p+sizeof(int)),*(++t));
    

    结果
    在这里插入图片描述
    不可

    ((int*)p)++;
    

    在 C 语言中, 类型转换意味着 ``把这些二进制位看作另一种类型, 并作相应的对待"; 这是一个转换操作符, 根据定义它只能生成一个右值 (rvalue)。而右值既不能赋值, 也不能用 ++ 自增。(如果编译器支持这样的扩展, 那要么是一个错误, 要么是有意作出的非标准扩展。)

    数组

    char m[10];
    char m[] = "123";
    char m[] = {'1','2'};
    int m[3][2];
    int *k[10];
    
    //自带了/0所以是18+1
    char ac[] = "welcome\0to\0huawei\0";
    //strlen到\0结束为7
    printf("%d %d\n",sizeof(ac),strlen(ac));
    

    结果
    在这里插入图片描述

    int c[4][2];//0x100;
    (c+1) = 0x108;//步长为2 int 8
    (*(c+1)+1) = 0x10c  //8 + 4
    

    声明一个函数,返回二维数组,int,最右空间为10.

    int (*Func())[10];
    

    数组为参数时,下面的都是一样的

    char p[10];
    char p[];
    char *p;
    char p[10][2];
    char (*p)[2];
    char p[][2];
    
    char test_5[] = "123";
    sizeof(test_5) = 4//包含'\0'
    

    内存分布

    在这里插入图片描述

    printf(%s\r\n,dataList);
    1. 字符数组局部变量,返回后变量内存收回 。\?
    2. 字符数组局部变量,返回后变量内存收回。 \?
    3. 字符串常量,全局存在。abc
    4. 静态变量,作用域只在函数内,空间和全局变量一致。abc
    
    int a = 0x0506;//全局变量初始化,数据段
    char *p0 = "this is test string";;//全局变量初始化,数据段
    char *p1;//全局变量未初始化 bss段
    int main()
    {
    	iny b;//栈
    	char s[] = "abc";//栈
    	char *p2;;//栈
    	char *p3 = "123";//123在常量区,p3在栈上
    	static int c =0x0203;//全局(静态)初始化区
    	static char *str1 = "abcd";//全局(静态)初始化区
    	p2 = (char*)malloc(10);//堆
    	strcpy(p2,"5678");
    	free(p2);
    	return 0;
    }
    字符串在数据段还是在代码段由编译器决定
    
    int gy;//初始化为0
    void Foo(){
    	int x;//未知
    	int *p;
    	for(int i;i<10;i++){
    		p = &i;//出了这个大括号i无效化
    	}
       
    	printf("%d %d %d %d",gy,x,*p,i);//报错
       return;
    }
    

    BSS段:存放程序中未初始化的全局变量,不占用执行程序大小,其内容由操作系统初始化(清零)。
    数据段:存放程序中已初始化的全局变量。
    代码段:存放程序执行代码的内存区域,大小在程序运行前已经确定,并且通常属于只读。
    堆:存放进程运行中被动态分配的内存段,大小并不固定,可动态扩张或缩减,马路咯从分配的为此内存。
    栈:用户存放程序临时创建的局部变量(不包括static声明的变量)。在函数被调用时,其参数也会被压入发起调用的进程栈。

    void Test(){
    	static char *str = "abc";
    }
    
    展开全文
  • 详细讲解 —— 实现万能冒泡排序(C语言进阶

    多人点赞 热门讨论 2021-10-06 20:18:43
    C语言中的 qsort 函数 2.1 qsort 函数的参数类型 2.2 qsort 函数中的 compare 函数 2.3 使用 qsort 函数 3. 实现万能冒泡排序函数 前言 我们在学习一门编程语言时,最为基本的就应该是排序的功能了,但是一旦要排序...

    前言

    我们在学习一门编程语言时,最为基本的就应该是排序的功能了,但是一旦要排序的类型发生变化(整型排序 ——> 字符串排序),我们就要重写一个类型的排序,这样子比较麻烦。

    那么可不可以写一个通用的万能排序函数呢?

    答案是肯定的,今天我们就来写一个万能的排序函数

    1. 一般的整型冒泡排序

    #include<stdio.h>
    
    //冒泡排顺序函数
    void bubble_sort(int arr[], int sz)
    {
    	int i = 0;
    	//跑多少趟
    	for (i = 0; i < sz - 1; i++)
    	{
    		int j = 0;
    		//比较的对数
    		for (j = 0; j < sz - 1 - i; j++)
    		{
    			//交换
    			if (arr[j] > arr[j + 1])
    			{
    				int tem = arr[j];
    				arr[j] = arr[j + 1];
    				arr[j + 1] = tem;
    			}
    		}
    	}
    }
    //打印arr数组
    void Print(int arr[], int sz)
    {
    	int i = 0;
    	for (i = 0; i < sz; i++)
    	{
    		printf("%d ", arr[i]);
    	}
    }
    int main()
    {
    	int arr[10] = { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 };
    	int sz = sizeof(arr) / sizeof(arr[0]);  //数组的元素个数
    	//冒泡排序
    	bubble_sort(arr, sz);
    	//打印arr数组
    	Print(arr, sz);
    	return 0;
    }
    

    在这里插入图片描述
    这个排序只能针对整型,不能排序其他类型。

    2. C语言中的 qsort 函数

    当我们要了解一个C语言函数,可以上 msdn 上搜索这个函数是怎么使用的。

    C语言中的 qsort 函数为万能排序函数
    通过了解 qsort 函数(万能排序函数),然后自己写一个万能排序函数

    2.1 qsort 函数的参数类型

    在这里插入图片描述

    void qsort(void* base,
    	size_t num, 
    	size_t width, 
    	int(__cdecl* compare)(const void* elem1, const void* elem2));
    
    
    void* base —— 表示要排序数对的第一个元素地址地址
    num —— 表示排序的个数
    witch —— 表示每一个要排序元素的大小
    
    int(__cdecl* compare)(const void* elem1, const void* elem2)) —— 函数指针
    compare —— 函数名
    elem1 —— 函数的第一个参数
    elem2 —— 函数的第二个参数
    int —— 返回类型为整型
    
    

    2.2 qsort 函数中的 compare 函数

    qsort 中的 compare 函数是由使用者来创建的。
    那这个函数要怎样创建呢?

    在这里插入图片描述
    从上面这个图片中可以看到 compare 函数的返回值是什么。
    当函数第一个参数小于第二个参数时,返回一个小于零的整数
    当函数第一个参数大于第二个参数时,返回一个大于零的整数
    当函数第一个参数等于第二个参数时,返回一个等于零的整数

    2.3 使用 qsort 函数

    void —— 无具体指针类型,
    能够接收任意类型的地址,
    缺点不能进行运算,不能加减整数,不能解引用。

    qsort 函数中就是用 void 来接收的,那要怎样使用这个 void 类型呢?
    使用强制转换之后,就可以使用 void 类型了。

    排序整型

    #include<stdio.h>
    #include<stdlib.h>
    
    //打印
    void Print(int arr[], int sz)
    {
    	int i = 0;
    	for (i = 0; i < sz; i++)
    	{
    		printf("%d ", arr[i]);
    	}
    }
    
    //自定义 qsort 函数中 cmp_int 函数
    int cmp_int(const void* e1, const void* e2)
    {
    	return *(int*)e1 - *(int*)e2;
    	//e1为void*类型 —— 强制转换为int*类型
    }
    
    int main()
    {
    	int arr[10] = { 9,8,7,6,5,4,3,2,1,0 };
    	//排序
    	qsort(arr, sizeof(arr) / sizeof(arr[0]), sizeof(int), cmp_int);
    	// arr —— 为int要排序元素的地址
    	// sizeof(arr) / sizeof(arr[0] —— 有多少个元素要排序
    	// sizeof(int) —— 排序类型的大小
    	// cmp_int —— 使用者自己创建的函数
    
    	//打印
    	Print(arr, sizeof(arr) / sizeof(arr[0]));
    }
    

    在这里插入图片描述
    排序结构体

    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    
    //结构体
    struct people
    {
    	char number[20];
    	int age;
    };
    
    //qsort中的比较函数 —— 年龄比较
    int cmp_by_age(const void* e1, const void* e2)
    {
    	return ((struct people*)e1)->age - ((struct people*)e2)->age;
    	//((struct people*)e1 —— e1强制转换为(struct people*)类型
    }
    
    //打印
    void Print1(struct people* p1, int sz)
    {
    	int i = 0;
    	for (i = 0; i < sz; i++)
    	{
    		printf("%10s %4d\n", (p1+i)->number, (p1+i)->age  );
    	}
    }
    
    //qsort中的比较函数 —— 名字比较
    int cmp_by_numble(const void* e1, const void* e2)
    {
    	return strcmp(((struct people*)e1)->number , ((struct people*)e2)->number);
    	// strcmp 可以比较两个字符串的大小
    	//((struct people*)e1 —— e1强制转换为(struct people*)类型
    }
    
    
    int main()
    {
    	struct people p1[3] = { {"zhangsan", 30}, {"lisi", 20}, {"wangwu", 15} };
    	int sz = sizeof(p1) / sizeof(p1[0]);                 //sz要比较大小的元素个数
    	qsort(p1, sz, sizeof(struct people), cmp_by_age);    //比较年龄 —— 升序
    	Print1(p1, sz);                                      //打印
    	printf("=================================\n");
    	qsort(p1, sz, sizeof(struct people), cmp_by_numble); //比较名字 —— 升序
    	Print1(p1, sz);                                      //打印
    	return 0;
    }
    

    在这里插入图片描述

    3. 实现万能冒泡排序函数

    #include<stdio.h>
    
    //交换
    void swap_num(char* bulf1, char* bulf2, int width)
    {
    	int i = 0;
    	for (i = 0; i < width; i++)
    	{
    	    //交换字节 —— 每次循环交换一个字节
    		char tem = *(bulf1+i);
    		*(bulf1+i) = *(bulf2+i);
    		*(bulf2+i) = tem;
    		//如果widch大于1
    		//第一次循环交换一个字节,第二次交换下一个字节
    	}
    }
    
    //万能的冒泡排序
    void bubble_sort(void* p1, size_t count, size_t width, int(*cmp)(const void* e1, const void* e2))
    {
    	int i = 0;
    	//趟数
    	for (i = 0; i < count - 1; i++)
    	{
    		int j = 0;
    		//每趟的对数
    		for (j = 0; j < count - i - 1; j++)
    		{
    			if(cmp((char*)p1 + j * width, (char*)p1 + (j + 1) * width) > 0)
    			//当函数返回的值大于零时,才执行交换 ———— 升序
    			//(char*)p1 + j * width 表示:
    			//—— 第一次循环找到第一个元素地址,第二次循环找到第二个元素地址,...
    			//(char*)p1 + (j + 1) * width 表示:
    			//—— 第一次循环找到第二个元素地址,第二次循环找到第三个元素地址,...
    			
    				//交换函数
    				swap_num((char*)p1 + j*width, (char*)p1 + (j+1)*width, width);
    		}
    	}
    }
    

    解析:
    以整型为例:

    if(cmp((char*)p1 + j * width, (char*)p1 + (j + 1) * width) > 0)
    

    在这里插入图片描述

    void swap_num(char* bulf1, char* bulf2, int width)
    {
    	int i = 0;
    	for (i = 0; i < width; i++)
    	{
    	    //交换字节 —— 每次循环交换一个字节
    		char tem = *(bulf1+i);
    		*(bulf1+i) = *(bulf2+i);
    		*(bulf2+i) = tem;
    		//如果widch大于1
    		//第一次循环交换一个字节,第二次交换下一个字节
    	}
    }
    

    在这里插入图片描述

    展开全文
  • 一、说明 这次的通讯录为文件保存的版本, 需求说明: 1、增加保存功能,可以存放到文件中。 2、增加读取功能,读取之前保存的通讯录文件。...今天写代码遇到一个BUG,无论怎么更改代码都报错, ...

    一、说明

    这次的通讯录为文件保存的版本,

    需求说明:

    1、增加保存功能,可以存放到文件中。

    2、增加读取功能,读取之前保存的通讯录文件。

    小提示:

    今天写代码遇到一个BUG,无论怎么更改代码都报错,

    后来才调试出:如果你要在A函数中调用B函数,即使在头文件中声明了,但是在函数文件中,一定要先定义B。因为程序是从上至下一行一行读取的,编译不会通过,但是报的错会很奇怪,如报scanf的错,这样很难通过编译器找到错因。所以写函数一定要分先后。 

    二、更改代码段 

    首先是保存功能:

    void SaveContact(struct Contact* ps)
    {
    	FILE* pfWrite;
    	pfWrite = fopen("C:\\Users\\asus\\Desktop\\contact.dat", "wb");
    	if (pfWrite == NULL)
    	{
    		printf("%s\n", strerror(errno));
    		return;
    	}
    	//打开成功
    	//写通讯录中的数据到文件中
    	int i = 0;
    	for (i = 0; i < ps->size; i++)
    	{
    		fwrite(&(ps->data[i]), sizeof(PeoInfo), 1, pfWrite);
    	}
    	//关闭文件
    	fclose(pfWrite);
    	pfWrite = NULL;
    }

     这个函数创建了一个文件指针,指向要保存的数据的地址文件。

    然后进行指针判空操作,

    如果指针存在,则进行一个for循环,

    将当前存放的通讯录中的数据一条一条地通过fwrite函数写进文件里。

    fwrite函数:写文件函数。

    4个参数,

    第一个是要读取的数据元素的地址,

    第二个是读取一个元素的大小,

    第三个是读取元素的数量,

    第四个是要写到哪个文件里去,指向那个文件的指针。

    这样就完成了保存文件操作。

     

    那么读取通讯录呢?

    对于读取通讯录,我们有两个问题:

    1、怎么读

    2、扩容问题

    首先解决第一个问题。

    读文件要用到的函数是:

    fread();

    同样是4个参数,

    不过操作不一样了。

    第一个是被写的数据元素的地址,

    第二个是写的一个元素的大小,

    第三个是写元素的数量,

    第四个是要读哪个文件,指向那个文件的指针。

    综上,文件读写函数分别是:

    读文件函数,fread,意思是要把文件里的内容读出来,写到变量中去;

    写文件函数,fwrite,意思是要把变量中的数据写进文件里去。

    这里的读写均是针对文件。

     

    所以,我们先读这个文件里的数据,存放到临时结构体变量tmp中:

    PeoInfo tmp = { 0 };
    	FILE* PfRead = fopen("C:\\Users\\asus\\Desktop\\contact.dat", "rb");
    	if (PfRead == NULL)
    	{
    		printf("LoadContact::%s\n", strerror(errno));
    		return;
    	}
    	//读取文件,存放到通讯录中
    read(&tmp, sizeof(PeoInfo), 1, PfRead);

    而fread具有返回类型,是size_t,意思是读取了几个元素;

    如果没有读满一个元素,就返回0.

    这里我们可以很好的运用这个返回值来解决第二个问题:扩容问题。

    首先,我们定义一开始只动态开辟3个元素的内存,

    那么前三个好放,我们只需要

    ps->data[ps->size] = tmp;
    		ps->size++;

    但是当放满三个后,需要扩容,我们就在前面加上一个扩容函数。

    最后,用返回类型来控制while循环的次数即可:

    void LoadContact(Contact* ps)
    {
    	PeoInfo tmp = { 0 };
    	FILE* PfRead = fopen("C:\\Users\\asus\\Desktop\\contact.dat", "rb");
    	if (PfRead == NULL)
    	{
    		printf("LoadContact::%s\n", strerror(errno));
    		return;
    	}
    	//读取文件,存放到通讯录中
    	while (fread(&tmp, sizeof(PeoInfo), 1, PfRead))
    	{
    		CheckCapacity(ps);
    		ps->data[ps->size] = tmp;
    		ps->size++;
    	}
    	//关闭文件
    	fclose(PfRead);
    	PfRead = NULL;
    }

    而这个函数,我们可以写到初始化函数中:

    void InitContact(struct Contact* ps)
    {
    	ps->data = (struct PeoInfo*)malloc(3 * sizeof(struct PeoInfo));
    	if (ps->data == NULL)
    	{
    		return;
    	}
    	ps->size = 0;
    	ps->capacity = DEFAULT_SZ;
    	//把文件中已经存放的通讯录中的信息加载到通讯录中
    	LoadContact(ps);
    }

    这样一份文件版的通讯录就写完了。

    三、GitHub地址

    https://github.com/kukeoo/Contact.git

    展开全文
  • 1.公务员面试现场打分。有7位考官,从键盘输入若干组成绩,每组7个分数(百分制),去掉一个最高分和一个最低分,输出每组的平均成绩。 输入描述:一行,输入7个整数(0~100),代表7个成绩,用空格分隔。...

    目录

    1.公务员面试现场打分。有7位考官,从键盘输入若干组成绩,每组7个分数(百分制),去掉一个最高分和一个最低分,输出每组的平均成绩。

    2.描述有一个有序数字序列,从小到大排序,将一个新输入的数插入到序列中,保证插入新数后,序列仍然是升序。

    3.下面代码的输出结果为

    4.模拟实现atoi《剑指OFFER》

    5.找单身狗:一个数组中只有两个数字是出现一次,其他所有数字都出现了两次。

    6.交换奇偶位

    写一个宏,可以将一个整数的二进制位的奇数位和偶数位交换。

    7.offsetof宏

    写一个宏计算结构体中某变量相对于首地址的偏移,并给出说明


    1.公务员面试现场打分。有7位考官,从键盘输入若干组成绩,每组7个分数(百分制),去掉一个最高分和一个最低分,输出每组的平均成绩。

    输入描述:一行,输入7个整数(0~100),代表7个成绩,用空格分隔。

    输出描述:一行,输出去掉最高分和最低分的平均成绩,小数点后保留2位,每行输出后换行。

    #define _CRT_SECURE_NO_WARNINGS 1
    #include<stdio.h>
    int main()
    {
        int i = 0;
        int sum = 0;
        int min = 100;//假设最小值是100
        int max = 0;//假设最大值是0
        int score = 0;
        for(i=0; i<7; i++)
        {
            scanf("%d ", &score);
            sum += score;
            if(score > max)
                max = score;
            if(score < min)
                min = score;
        }
        printf("%.2f\n", (sum-min-max)/5.0);
        return 0;
    }
    

    2.描述有一个有序数字序列,从小到大排序,将一个新输入的数插入到序列中,保证插入新数后,序列仍然是升序。

    输入描述:

    第一行输入一个整数(0≤N≤50)。

    第二行输入N个升序排列的整数,输入用空格分隔的N个整数。

    第三行输入想要进行插入的一个整数。

    输出描述:

    输出为一行,N+1个有序排列的整数。

    #define _CRT_SECURE_NO_WARNINGS 1
    #include<stdio.h>
    int main()
    {
    	int n = 0;
    	scanf("%d",&n);
    	int i = 0;
    	int arr[51] = { 0 };
    	for (i = 0; i < n; i++)
    	{
    		scanf("%d",&arr[i]);
    	}
    	int m = 0;
    	scanf("%d",&m);
    	for (i = n - 1; i >= 0; i--)
    	{
    		if (arr[i] > m)
    			arr[i + 1] = arr[i];
    		else
    		{
    			break;
    		}
    	}
    	arr[i + 1] = m;
    	for (int i = 0; i <= n; i++)
    	{
    		printf("  %d",arr[i]);
    	}
    	return 0;
    }

    3.下面代码的输出结果为

    int main()
    {
      unsigned char puc[4];
      struct tagPIM
      {
        unsigned char ucPim1;
        unsigned char ucData0 : 1;
        unsigned char ucData1 : 2;
        unsigned char ucData2 : 3;
      }*pstPimData;
      pstPimData = (struct tagPIM*)puc;
      memset(puc,0,4);
      pstPimData->ucPim1 = 2; 
      pstPimData->ucData0 = 3;
      pstPimData->ucData1 = 4;
      pstPimData->ucData2 = 5;
      printf("%02x %02x %02x %02x\n",puc[0], puc[1], puc[2], puc[3]);
      return 0;
    }

    4.模拟实现atoi《剑指OFFER》

    //<剑指offer>
    #include <assert.h>
    #include <ctype.h>
    #include <limits.h>
    enum State
    {
    	INVALID,//0
    	VALID   //1
    };
    state 记录的是my_atoi 返回的值是合法转化的值,还是非法的状态
    //
    enum State state = INVALID;
    
    
    int my_atoi(const char* s)
    {
    	int flag = 1;
    	//assert(NULL != s);
    	// 
    	//空指针
    	if (NULL == s)
    	{
    		return 0;
    	}
    	//空字符
    	if (*s == '\0')
    	{
    		return 0;
    	}
    	//跳过空白字符
    	while (isspace(*s))
    	{
    		s++;
    	}
    	//+/-
    	if (*s == '+')
    	{
    		flag = 1;
    		s++;
    	}
    	else if (*s == '-')
    	{
    		flag = -1;
    		s++;
    	}
    	//处理数字字符的转换
    	long long n = 0;
    	while (isdigit(*s))
    	{
    		n = n * 10 + flag*(*s - '0');
    		if (n > INT_MAX || n < INT_MIN)
    		{
    			return 0;
    		}
    		s++;
    	}
    	if (*s == '\0')
    	{
    		state = VALID;
    		return (int)n;
    	}
    	else
    	{
    		//state = VALID;
    		//非数字字符的情况
    		return (int)n;
    	}
    }
    int main()
    {
    	//1. 空指针
    	//2. 空字符串
    	//3. 遇到了非数字字符
    	//4. 超出范围
    	
    	//const char* p = "-123111111111111111111111111111111111111";
    	//"0"
    	//int ret = my_atoi(p);
    	const char* p = "     -123a";
    	int ret = my_atoi(p);
    
    
    	if (state == VALID)
    		printf("正常的转换:%d\n", ret);
    	else
    		printf("非法的转换:%d\n", ret);
    
    
    	return 0;
    }

    5.找单身狗:一个数组中只有两个数字是出现一次,其他所有数字都出现了两次。

    编写一个函数找出这两个只出现一次的数字。

    思路:

    //1^2^3^4^5^6^1^2^3^4^5 = 5^6 = 3!=0
    //1 3 1 3 5
    //2 4 2 4 6
    //1.分组
    //2.分组的要点:5和6必须在不同的组
    //找出这两个只出现一次的数字 

    void Find(int arr[], int sz,int*x,int*y)
    {
    	int ret = 0;
    	int i = 0;
    	for (i = 0; i < sz; i++)
    	{
    		ret = arr[i]^ret;
    	}
    	//2.计算ret哪一位为1
    	int pos = 0;
    	for (i = 0; i < 32; i++)
    	{
    		if (((ret >> i) & 1) == 1)
    		{
    			pos = i;
    			break;
    		}
    	}
    	//把从低位向高的第pos位为1,为0的放在另一个组
    	int num1 = 0;
    	int num2 = 0;
    	for (i = 0; i < sz; i++)
    	{
    		if (((arr[i] >> pos) & 1) == 1)
    		{
    			num1 = num1^arr[i];
    		}
    		else
    		{
    			num2 = num2^arr[i];
    		}
    	}
    	*x = num1;
    	*y = num2;
    }
    int main()
    {
    	int arr[] = { 1, 2, 3, 4, 5, 7, 4, 3, 2, 1 };
    	int sz = sizeof(arr) / sizeof(arr[0]);
    	int x = 0;
    	int y = 0;
    	//1.要把所有数字异或
    	Find(arr, sz,&x,&y);
    	printf("%d %d", x, y);
    	return 0;
    }

    6.交换奇偶位

    写一个宏,可以将一个整数的二进制位的奇数位和偶数位交换。

    #define _CRT_SECURE_NO_WARNINGS 1
    #include<stdio.h>
    #define SWAP(N)((N & 0xaaaaaaaa) >> 1)+((N & 0x55555555)<< 1)
    int main()
    {
    	//10
    	//00000000 00000000 00000000 00001010
    	int num = 10;
    	int ret = SWAP(num);
    	//int ret = ((num & 0xaaaaaaaa) >> 1)+((num & 0x55555555)<<1);
    	printf("%d",ret);
    	return 0;
    }

    7.offsetof宏

    写一个宏计算结构体中某变量相对于首地址的偏移,并给出说明

    #define _CRT_SECURE_NO_WARNINGS 1
    #include<stdio.h>
    #include<stddef.h>
    struct A
    {
    	int a;
    	short b;
    	int c;
    	char d;
    };
    #define OFFSETOF(struct_name,mem_name) (int)&(((struct_name*)0)->mem_name)
    int main()
    {
    	printf("%d\n", OFFSETOF(struct A, a));
    	printf("%d\n", OFFSETOF(struct A, b));
    	printf("%d\n", OFFSETOF(struct A, c));
    	printf("%d\n", OFFSETOF(struct A, d));
    }
    

    展开全文
  • 20211月翁恺c语言进阶

    2021-01-27 08:38:20
    答案 BBDDD BBDDC CAAAB CAABA
  • 一、说明 这次的通讯录为动态增长的版本, 需求说明: 默认可以存放3个人的信息, 当发现当前通讯录满的时候,我们进行扩容,每次增加2个空间。...首先,我们应该在通讯录这个结构体中增加一个成员变量——...
  • C语言进阶之旅(2)

    2021-04-10 23:45:05
    C语言进阶————>2 0-100素数 最大公因数 素数 定义:素数只能被1和他本身整除 #include<stdio.h> int main() { int i = 0; int j = 0; for(i=0;i<=200;i++) { for(j=2;j<=i;j++)//素数...
  • 1.判断下列程序输出什么? int main() { char arr1[] = "abcdef"; char arr2[] = "abcdef"; ... char *p1 = "abcdef";... //判断输出结果 arr1和arr2保存的是字符串的首元素地址,两块独立的内存空间 ...
  • C语言进阶——数据在内存中的存储(一)

    多人点赞 热门讨论 2021-05-24 15:00:55
    在学习一定的C语言初阶知识后,我们知道以下的基本数据类型: char 字符数据类型 short 短整型 int 整形 long 长整型 long long 更长的整形 float 单精度浮点数 double 双精度浮点数 数据类型的意义 1.使用这个...
  • C语言的编程过程中经常会用到宏定义,然而如果你只是使用宏定义做一些常量的定义,那么你不是OUT了就是C语言小白。下面我们一起来看一下在编程过程中,宏定义都有哪些作用。 常量定义 可以作为功能代码的开关 ...
  • 6-1?拆分实数的整数与小数部分?(15?分)本题要求实现一个拆分实数的整数与小数部分的简单函数。函数接口定义:void splitfloat( float x, int *intpart, float *fracpart );其中x是被拆分的实数(0≤x<...
  • C语言指针进阶一、字符指针 指针的初阶我们可以参看这篇博客C语言初阶——指针 ,这篇博客主要有四个重要结论,也是初阶指针的重要概念: 1. 指针是地址,指针变量是一个变量,用来存放内存单元的地址,通过指针能...
  • C语言进阶学习笔记 文章目录一:核心概念1.1 堆栈1.2全局变量和局部变量 一:核心概念 1.1 堆栈 栈,是硬件,表现为一种数据结构,**先进后出** 计算机系统中:栈一般包含2方面信息: 1:函数的返回值和参数 2:...
  • C语言进阶书籍

    2021-04-03 10:35:09
    自取地址 提取码:zero (小写) 《我的第一本编程书》,《C和指针》,《C指针编程之道》,《C专家编程》 分别对应入门,进阶,秃顶。。。。 注意:电子书仅用于学习使用,如有侵权行为,请联系我删除。 ...
  • C语言进阶:动态内存管理

    多人点赞 热门讨论 2021-09-28 20:38:13
    文章目录动态内存管理动态内存分配的意义动态内存函数的介绍开辟释放函数 `malloc` & `free`函数声明函数用法内存开辟函数 `calloc`函数声明函数用法内存调整函数 `realloc`函数声明函数用法常见的动态内存错误1...
  • C语言进阶:指针进阶续

    多人点赞 热门讨论 2021-09-05 16:47:33
    文章目录指针进阶续回调函数回调函数定义快速排序 `qsort``qsort`函数逻辑小结`qsort`实现冒泡排序`qsort`...续前文《C语言进阶:指针进阶》 回调函数 回调函数定义 回调函数:通过函数指针调用的函数,或者说使用函
  • 指针进阶 我们在初级指针章节已经接触过了指针,我们知道了指针的概念: 1. 指针就是个变量,用来存放地址,地址唯一标识一块内存空间。 2. 指针的大小是固定的4/8个字节(32位平台/64位平台)。 3. 指针是有...
  • C语言进阶与试题剖析.ppt》由会员分享,可在线阅读,更多相关《C语言进阶与试题剖析.ppt(15页珍藏版)》请在人人文库网上搜索。1、C语言进阶与试题剖析,期末大作业 微型学生成绩管理系统,设某班有n位同学,每位同学...
  • C语言进阶:指针进阶

    多人点赞 热门讨论 2021-08-30 17:34:28
    文章目录指针进阶字符指针字符指针的作用字符指针的特点指针数组指针数组的定义指针数组的使用数组指针数组指针的定义&数组名和数组名数组指针的使用反面用例正面用例Example类型辨别方法数组传参和指针传参一维...
  • C语言进阶】玩转指针——指针的高阶玩法!

    万次阅读 多人点赞 2021-10-05 20:13:53
    文章目录前言一、字符指针二、指针数组1.引入库2.读入数据总结 前言 指针的主题,我们在初级阶段的《指针》章节已经接触过了,我们知道了指针的概念: 1.指针就是个变量,用来存放地址,地址唯一标识一块内存空间...
  • C语言进阶》之简单圣诞树

    千次阅读 多人点赞 2021-12-16 17:13:19
    C语言打印圣诞树(简单版)
  • 文章目录1. 重定向1.1 重定向文件输出1.2 重定向文件输入1.3 结构体存取2. 读文件和写文件3. 打开文件和关闭文件4. 综合大题5....1. 重定向 1.1 重定向文件输出 把运行出来的内容直接保存在文件中 ./a.out >...
  • C语言进阶:自定义类型

    千次阅读 多人点赞 2021-09-23 17:35:36
    文章目录自定义类型结构体结构体的声明匿名形式声明Example结构体自引用Example 1Example 2注意结构体变量的...C语言本身具有的内置类型如int, float, double...,同时也提供可自定义的自定义类型或构造类型如结构体,
  • C语言进阶之旅(11)指针进阶上 精华篇

    多人点赞 热门讨论 2021-06-02 21:57:02
    写个感想吧,不知不觉又过了一个月,学C语言已经过了俩个月,博客也有一搭没一搭大更新着,虽然不知道写的文章对别人是否有帮助,或许有吧,比较还有人给我点赞呢哈哈哈,OK我会继续输入(听课看书写作业)输出的(写...
  • C语言进阶】C语言实现通讯录(简易版)

    千次阅读 多人点赞 2021-09-03 14:04:07
    前言: 我们需要用C语言模拟一个通讯录可以用来存储1000个人的信息 每个人的信息包括: 姓名、电话、性别、住址、年龄 功能包括: 新增联系人 查找联系人 删除联系人 修改联系人 查看所有联系人 以名字排序所有联系...
  • C语言进阶:文件操作

    多人点赞 热门讨论 2021-10-02 10:51:09
    但没有它C语言又不完整。所以本次我们研究一下C语言的文件操作。 文件的定义 将数据存储到外存(写入文件),每次程序结束后可以避免数据丢失,可以在程序运行时将数据加载到内存中,这是文件存在的意义。 在程序...
  • C语言是一门很简单的语言,但是并没有多少人敢说自己完全懂这个语言。今天,我们来仔细了解一下结构体和联合,看看它是否还是那个为我们所熟知的语言。
  • 本章重点 重点介绍字符和字符串的库函数 strlen 函数原型 size_t strlen ( const char * str ); size_t 是 unsigned int 头文件是#include <string.h>...功能:计算字符串的长度,读到'\0'结束 ...
  • 本文主要介绍了在C语言中,如何使用宏定义一个带返回值的宏函数!
  • 故事背景,你要穿越丹麦海滩汇报敌军情况,那里危机四伏,应为那里埋了许多地雷, 文章目录思维导图菜单==是否要执行任务初始化雷区打印雷区埋雷排雷 思维导图 菜单==是否要执行任务 void menu() ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 32,912
精华内容 13,164
关键字:

c语言进阶

c语言 订阅
友情链接: ATT70XX选型.rar