C程序设计基础上机实践课期末考试复习

25 篇文章 0 订阅
3 篇文章 0 订阅

输入与输出

  • 格式控制符说明
    %c读取一个单一的字符
    %hd、%d、%ld读取一个十进制整数,并分别赋值给 short、int、long 类型
    %ho、%o、%lo读取一个八进制整数(可带前缀也可不带),并分别赋值给 short、int、long 类型
    %hx、%x、%lx读取一个十六进制整数(可带前缀也可不带),并分别赋值给 short、int、long 类型
    %hu、%u、%lu读取一个无符号整数,并分别赋值给 unsigned short、unsigned int、unsigned long 类型
    %f、%lf读取一个十进制形式的小数,并分别赋值给 float、double 类型
    %e、%le读取一个指数形式的小数,并分别赋值给 float、double 类型
    %g、%lg既可以读取一个十进制形式的小数,也可以读取一个指数形式的小数,并分别赋值给 float、double 类型
    %s读取一个字符串(以空白符为结束)

C 输入

scanf

函数介绍:scanf("%type", &ptr)

  • 在VS中,scanf将被视为不安全的函数,应当使用scanf_s

  • 不能读取带空格的字符串,当读到空格时,停止读入。

  • 返回值为成功读取的变量个数

  • sscanf(s, "<#format#>", <#address#>);从字符串读取

getchar()

单个字符输入

gets

函数介绍:gets(str)

  • 可以读取带空格的字符串。
  • 有长度限制的读取字符串:fgets(str, 10, stdin)

C++ 特有输入

cin >>

遇到空格,Tab,回车结束输入。

⚠️⚠️⚠️特别注意:cin流将内容存放在缓冲区中,\n没有被擦除。因此,如果后面跟了getline(),一定要cin.ignore()!!!

cin.getline(str, len, end_str)

  • end_str()默认为\0
  • 其中的stristream流中的char[],假如输入的是string 类型的数据,需要str.c_str()处理。

getline(cin, str)

  • 其中的strstring流。

C 输出

printf

格式输出

  • %a.bsa为占的字符长度,b为输出字符串的长度。+右对齐,-左对齐。

  • sprintf(s, "<#format#>", <#veriable#>);输出到字符串

变量与运算

数据类型

(unsigned) char, short, int, long, long long int , bool, float, double,long double, long long double, enum, bool, pointer, array, struct, union

整型变量

char, short, int, long int, long long int , bool

  • char类型变量本质上是以ASC- II码的形式存放,也就是说,是一个整数。⚠️注意:char类型需要使用单引号对,双引号对是char[]类型。
  • 八进制:0__;十六进制:0x__。但是int类型的变量都是以十进制为准的,因此假如给变量赋的值是形如0__0x__(输入的无效)的话,最终就会发生进制转换。
  • bool类型需要#include <stdbool.h>,不是0的都是1.

浮点型变量

  • ⚠️注意强制类型转换导致的精度缺失/float自动转成double的情况!!!
  • 浮点计算结果可能会不准确。
  • 一切强制类型转换都用的是去尾法,但是输出流控制可以实现四舍五入。

枚举类型enum

数据类型的最值

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

int main()
{
    printf("%d\n",CHAR_MAX);
    printf("%d\n",CHAR_MIN);
    printf("%d\n",INT_MAX);
    printf("%d\n",INT_MIN);

    return 0;
}

运算

实例——输出各位数

void num(int x)
{
    int i, j;
    for (i = 0; i < 8; ++i) //计算x位数
        if (x / int(pow(10, i)) == 0)
            break;
    
    for (j = 0; j < i; ++j) //提取各位数字(逆序提取)
    {
        cout << x % 10 << endl;
        x /= 10;
    }
}

math.h中的公式

  • floor(x)
  • ceil(x)
  • fabs(x)
  • log(x)
  • log10(x)
  • exp(x)
  • sqrt(x)
  • pow(x, y)
  • 这些函数都是以double类型进行运算,因此最好加上int()

位运算符

  • ~:按位取反
  • &:按位取与
  • |:按位取或
  • ^:按位异或
  • <<:左移补0/1
  • >>:右移补0/1

位运算符实例1——x中的第p位开始的n个bit求反

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

int main()
{
    unsigned int x,p,n;
    scanf("%u %u %u",&x,&p,&n);
    printf("%u",x^(~(~0<<n)<<(p-n+1)));
    return 0;
}

选择、循环结构

选择结构

if

switch

switch (<#expression#>) {
        case <#constant#>:
            <#statements#>
            break;
            
        default:
            break;
    }

switch实例

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

int main()
    {
        int day;
        scanf("%d",&day);
        switch(day)
        {
            case 1:printf("Monday");
            break;
            case 2:printf("Tuesday");
            break;
            case 3:printf("Wednesday");
            break;
            case 4:printf("Thursday");
            break;
            case 5:printf("Friday");
            break;
            case 6:printf("Saturday");
            break;
            case 7:printf("Sunday");
            break;
            default:break;
        }
    return 0;
    }

循环结构

for

  • ⚠️注意检查起始值和结束值,最重要的是,到底是++还是--

while

  • ⚠️注意检查跳出循环的条件!

break

  • 跳出当前所在的循环

continue

  • 中段当前的循环操作,继续下一个循环

实例——辗转相除法求最大公因数

#include <iostream>
using namespace std;

int main()
{
	int a, b;
	int x1, x2, x0 = 1;
	cin >> a >> b;
	if (a < b)
		swap(a, b);//确保大的数位于左侧被除
	x1 = a;
	x2 = b;
	while (x0 > 0)
	{
		x0 = x1 % x2;
		x1 = x2;
		x2 = x0;
	} //辗转相除,推荐函数递归
	cout << "最大公约数是: " << x1 << endl;
	return 0;
}

实例——求子集

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

// 本质上,子集中元素的有无是该全集中元素个数的二进制加法计数

int main()
{
    int n=0,i=0,j=0,count;
    scanf("%d",&n);

    for(;i<(int)pow(2,n);i++)
    {
        printf("{");
        count=0;   //初始化为0
        for(j=0;j<n;j++)
        {
            if(i&(int)pow(2,j))   
            {
                if(count==0)   //0为无,1为有,有就进入判断
                printf("%d",j);
            else
                printf(",%d",j);
                count++;    //count计数用,每成功打印一个数加1
            }
        }
        printf("}\n");
    }
    return 0;
}

函数

函数指针

函数指针的例子

#include<stdio.h>

int add(int m, int n)
{
	return m+n;
}

int sub(int m, int n)
{
	return m-n;
}

main(int argc, char *argv[])
{
	int (*p)(int m, int n); //定义了一个函数指针,其中p代表的是存放函数的首地址
	int a=70;
	int b=13;
	p=add; //p指向函数add
	printf("%d\n", p(a,b));
	p=sub; //p指向函数sub
	printf("%d\n", (*p)(a,b));

函数递归

int recursion(int x)
{
    if (<#case#>)
    {
        <#easy-solution#>
    }
    else
        return <#recursion#>
}

递归实例1——阶乘

int jc(int x)
{
    if (x == 1)
        return 1;
    else
        return x * jc(x - 1);
}

递归实例2——斐波那契数列

int fi(int x)
{
    if (x == 1)
        return 0;
    else if (x == 2)
        return 1;
    else
        return fi(x - 1) + fi(x - 2);
}

递归实例3——辗转相除法求最大公因数

#include <iostream>

using namespace std;

int GDB(int a, int b);

int main()
{
	int a, b;
	cin >> a >> b;
	cout << GDB(a, b) << endl;
	return 0;
}

int GDB(int a, int b) //a = q * b + r
{
	if (b == 0)
		return a;
	else
		return GDB(b, a % b);
}

数组与指针

整型数组

  • ⚠️注意下标的对应关系,不要越界!!!

  • 未知长度的数组的输入

  • int i = 0, temp;
    while (cin >> temp)
    	{
    		data[i++] = temp;
    		if (cin.get() == '\n')
    			break;
    	}
    

数组传递函数

int function(int array[], int len);
  • 如果对数组没有值的修改,应该使用const

二维数组

arr[i][j]

  • i代表的是行,j代表的是列。

  • 二维数组的函数参数传递

int function(int array[][N]);

数组的操作

添加元素到指定位置
void arr_append(int arr[], int len, int target, int target_i)
{
    int i;
    for (i = len - 1; i > target_i; --i)
        arr[i] = arr[i - 1]; //前一个覆盖后一个
    arr[target_i] = target; //加入
}
删除指定元素
void del(int arr[], int len, int target)
{
    int i, j;
    for (i = 0; i < len; ++i)
    {
        if (arr[i] == target) //线性查找元素
        {
            for (j = i; j < len - 1; ++j)
                arr[j] = arr[j + 1]; //后一个覆盖前一个
            break;
        }
    }
}
实例1——求最长平台
#include <iostream>
using namespace std;
constexpr auto N = 100;

int main()
{
	int no_use;
	int data[N]{}, temp, i = 0, k = 0, j = 0, max;
	int num[N]{}, num_temp = 0;
	cin >> no_use;
	while (cin >> temp)
	{
		data[i++] = temp;
		if (cin.get() == '\n')
			break;
	} //输入
    
	for (j = 0; j <= i; j++)
	{
		temp = data[j];
		k = j;
		while (k <= i)
		{
			if (data[k] == temp)
			{
				num_temp++;
				k++;
			}
			else
				break;
		}
		num[j] = num_temp;
		num_temp = 0;
	} //记录出现的个数
	max = num[0];
	for (i = 0; i < j; i++)
	{
		if (num[i] > max)
			max = num[i];
	} //比较最大的
	cout << max << endl;
	return 0;
}

实例1——求最长平台

#include <iostream>
#include <string.h>
using namespace std;
constexpr auto N = 100;

int min(int x, int y)
{
	if (x < y)
		return x;
	else
		return y;
}

int main()
{
	char num_1[N], num_2[N];
	cin >> num_1 >> num_2;
	int length_1 = strlen(num_1);
	int length_2 = strlen(num_2);
	int length_min = min(length_1, length_2);
	int num_ans[N]{};
	int num_last;
	int i, j;
	num_ans[0] = ((int(num_1[length_1 - 1]) - '0') + (int(num_2[length_2 - 1]) - '0')) % 10;
	num_last = ((int(num_1[length_1 - 1]) - '0') + int((num_2[length_2 - 1])) - '0') / 10;
    // 将之前输入的字符串转化为每一位的数字
    
	for (i = 1; i < length_min; i++)
	{
		num_ans[i] = (num_last + (int(num_1[length_1 - i - 1]) - '0') + (int(num_2[length_2 - i - 1])) - '0') % 10;
		num_last = (num_last + (int(num_1[length_1 - i - 1]) - '0') + (int(num_2[length_2 - i - 1])) - '0') / 10;
	}
    // 计算两数位数相同的那部分的加法结果并将进位记录下来
    
	if (length_1 >= length_2)
	{
		for (j = i; j < length_1; j++)
		{
			num_ans[j] = ((num_last + int(num_1[length_1 - j - 1])) - '0') % 10;
			num_last = ((num_last + int(num_1[length_1 - j - 1])) - '0') / 10;
		}
	}
	else
	{
		for (j = i; j < length_2; j++)
		{
			num_ans[j] = ((num_last + int(num_2[length_2 - j - 1])) - '0') % 10;
			num_last = ((num_last + int(num_2[length_2 - j - 1])) - '0') / 10;
		}
	}
    // 多出来的那部分数字记录进去,并且记录进位
    
	if (num_last != 0)
	{
		num_ans[j] = num_last;
		for (int k = j; k >= 0; k--)
			cout << num_ans[k];
	}
	else
	{
		for (int k = j - 1; k >= 0; k--)
			cout << num_ans[k];
	}
	return 0;
}

排序算法

选择排序
void sort(int arr[], int len)
{
    int i, j;
    for (i = 0; i < len; ++i)
    {
        // 初始化最小值
        int min = arr[i], min_i = i;
        //寻找未排序的最小元素
        for (j = i; j < len; ++j)
        {
            if (arr[j] < min)
            {
                min = arr[j];
                min_i = j;
            }
        }
        //将最小元素移到头部
        swap(arr[i], arr[min_i]);
    }
}
冒泡排序
void sort(int arr[], int len)
{
    int i, j;
    for (i = len - 1; i >= 0; --i) //很容易出错的地方!设置了泡泡最终的去处是数组的末尾。
        for (j = 0; j < i; ++j) //泡泡的一位位浮起
            if (arr[j] > arr[j + 1])
                swap(arr[j], arr[j + 1]);
}

查找算法

线性查找
int search(const int arr[], int len, int target)
{
    int i;
    for (i = 0; i < len; ++i)
        if (arr[i] == target)
            return i;
    return -1;
}
二分查找
int search(const int arr[], int len, int target)
{
    int first = 0, last = len - 1, mid;
    while (last != first)
    {
        mid = (first + last) / 2; //初始化mid
        if (arr[mid] > target)
            last = mid - 1; //修改尾部(-1去除mid本身)
        else if (arr[mid] < target)
            first = mid + 1; //修改头部(+1去除mid本身)
        else
            return mid; //找到了
    }
    return -1;
}

字符数组char[]

字符串处理函数(#include <string.h>)

  • strcpy(str1, const str2)

  • strlen(const str)

  • strcat(str1, const str2)

  • strcmp(const str1, const str2)

  • \0到底存在不存在非常重要,否则将会非法读取内存空间!

  • strncpy, strncat, strncmp增加了一个unsigned int参数来限制长度

C++字符串string

考试按自己想来的用吧,慢点再更新。

指针与数组

⚠️注意:指针一定要记得初始化!!!

指针的运算

  • + -:每次加/减一个数据类型所占空间
  • * /:非法运算符
  • ==:同一元素
  • > < >= <=:判断在内存空间的位置前后。假使两侧的元素不位于同一个数组中,这没有实际意义!
  • ++ --:注意运算先后顺序a = *(p++) <=> a = *p++ <=> a = *p; p++a = (*p)++ <=> a = *p; *p += 1

整型指针

  • 初始化:int* p = NULL
  • 赋值:*p = num / p = &num
  • 提取值:*p

字符串指针

  • 初始化:char* str = NULL
  • 赋值:str = st / strcmp(str, “<#input_string>”)
  • 提取整个字符串:str
  • 提取字符串中的字符:*str

一维数组指针

  • 初始化:int* p = num
  • 数组元素的表示:*(p + i) <=> p[i](此处的[]的功能自带了寻址的作用)

指向指针的指针

**p

二维数组指针

  • 初始化:int (*p)[j] = num
  • num[i][j]的表示方法
    • p[i][j]
    • *(p[i] + j)
    • *(*(p + i) + j)
    • *(p + i)[j]

指针数组

  • 初始化:<#type#> *p[N];

  • 应用实例——字符串字典序排序

    #include <stdio.h>
    int main()
    {
        char  *ptr[N] = {"Pascal","Basic","Fortran",
                     "Java","Visual C"};
        for (i=0; i<N-1; i++) 
        {
             for (j = i+1; j<N; j++)
             {
                  if (strcmp(ptr[j], ptr[i]) < 0)
                  {
                     temp = ptr[i];              
                       ptr[i] = ptr[j];
                       ptr[j] = temp;
                  }
             } 
        }  
    }
    

命令行参数

int main(int argc, const char * argv[])

动态内存分配

ptr = (*<#type_of_ptr#>) malloc(<#size#>);

ptr = (*<#type_of_ptr#>) calloc(<#num#>, <#size#>);

注意不要忘记释放堆内存,以免内存泄漏:free(ptr);

注意在ptr内存释放之后接地,以免产生野指针:ptr = NULL;

结构化数据

结构体struct

  • 结构体的声明与定义1
struct _struct
{
    <#type#> <#name#>;
} struct1, struct2;
  • 结构体的定义2
struct _struct struct1; // Definition in C
_struct struct1; // Definition in C++
  • 访问结构体元素

structure_variable_name.element_name

  • 结构体变量的操作
    • 同一个结构体类型/不同结构体的相同数据类型可以相互赋值
  • 结构体函数传参
  • 结构体组

结构体指针

  • 定义结构体指针:point *ptr
  • 访问成员:(*ptr).xxx或者ptr->xxx
  • ptr++所增加的量是该结构体所有成员所占的空间总和

链表

  • 节点类型定义

    struct Node
    {
        //data members
        int entry; //节点值
        Node *next; //(指针)
    }
    
  • 节点的使用

    int main()
    {
        Node *head; //创建新的链表头
    
        head = (Node *) malloc(sizeof(Node)); //为头分配空间
        head -> entry = X; //为结点赋值
        printf("%d,",head -> entry);
    
        head->next = (Node *) malloc(sizeof(Node));
        head->next->entry = Y;
        printf("%d,",head->next->entry);
    }
    

共用体 unions

  • 定义

    union _union
    {
        <#datatype#> <#dataname#>
    }
    
  • 使用与struct差不多,但是每次只能使用一个成员

C文件管理

FILE *fp; //初始化定义文件指针
fp = *fopen(<#filename#>, <#mode#>); //返回文件指针,若失败返回NULL。macOS下查询文件目录使用的是pwd指令。

//读取/输出单个字符,fscanf和fprintf也可以
int getc(FILE *fp);
int putc(int c, FILE *fp);

//读取或者输出字符串
char *fgets(char *line, int maxline/*最大字符数量*/, FILE *fp);
int fputs(char *line, FILE *fp);

//⚠️关闭文件指针,一定要记住!!!!!!!
int fclose(FILE *fp);
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值