C语言——基础查漏补缺(三):谭浩强红书刷题笔记大杂烩

相关文章:
C语言——基础查漏补缺(一):超长文帮你理清一些概念
C语言——基础查漏补缺(二):《C程序设计试题汇编》应试概念总结
C语言——基础查漏补缺(四):利用《挑战程序设计竞赛(第二版)》前两章学习经典算法

△注:谭浩强红书的第一轮复习略看了前两章(正文概念和课后习题。正文例题没略看),所以第二轮开始前,需要将前两章内容逐行审查,不熟练文字概念补充总结即可。
△注1:谭浩强红书是指谭浩强C语言和配套的学习辅导两本书(后者去年写了未完的blog,内容粘贴至本文,那篇就不要了)。
△注2:谭浩强红书的第一轮搞定后,开始谭浩强绿书(试题汇编),同时看对应章节的校本教材的编程题并总结(校本教材概念部分可先跳过,之后酌情处理,但概念题需要做和总结),这两本书总结至同一篇blog(前年写的C语言查漏补缺二)。

这篇文章是考研复试前的复习笔记,简单修改后分享给需要的人。以上删除线是我碎碎念的计划。

第一章 C语言简介

这章主要是概念题,自行总结。

第二章 算法简介

1,☆闰年的定义:

  • 能被4整除,但不能被100整除的年份;
  • 能被400整除的年份。

2,△易错题
在这里插入图片描述
错误代码:

#include

int main(){
     
    float res = 0;
    int i, flag = -1;
    for(i = 1;i <= 100;++i){
     
        flag = flag * (-1);
        res = res + (flag * (1 / i));
   	}
    printf("%f\n", res);
    return 0;
}

上述结果输出为1.000000,并且经检查,for中所有res都等于1.000000
原因:res = res + (flag * (1 / i));中的1i都是int型,所以1/i也是int,并且i>1时它为0.

更正:将i定义为float即可,这样1 / iflag * (1 / i)都会被处理为float

3,☆质数筛法(留白)

// 埃氏筛法,输入n,输出不大于n的素数个数
#include

#define maxn 1000005

int IsPrime[maxn];
int n;

int main(){
     
    int count = 0;
    scanf("%d", &n);
    IsPrime[0] = 0;
    IsPrime[1] = 0;
    for(int i = 2;i <= n;i++)IsPrime[i] = 1;
    for(int i = 2;i * i <= n;i++)
        if(IsPrime[i]){
     
            for(int j = 2 * i;j <= n;j += i)
                IsPrime[j] = 0;
        }
    for(int i = 2;i <= n;i++)
        if(IsPrime[i])count++;
    printf("%d\n", count);
    return 0;
}
// 区间筛法,输入a和b,输出[a, b)内素数个数
#include

#define maxa 1000000000005
#define maxb 1000000000005
#define maxl 1000005

int IsPrimeMin[maxl], IsPrime[maxl];

long long max(long long a, long long b){
     
    return (a > b) ? a : b;
}

int main(){
     
    long long a, b;
    int count = 0;
    scanf("%lld %lld", &a, &b)
    for(int i = 0;i < b - a;i++)
        IsPrime[i] = 1;	// 代表i+a是素数
    for(int i = 2;(long long)i * i < b;i++)
        IsPrimeMin[i] = 1;
    for(int i = 2;(long long)i * i < b;i++)
        if(IsPrimeMin[i]){
     
            for(int j = 2 * i;(long long)j * j < b;j += i)
                IsPrimeMin[j] = 0;
            for(long long j = max((a + i - 1) / i, 2LL) * i;j < b;j += i)
                IsPrime[j-a] = 0;
        }
    for(int i = 0;i < b - a;i++)
        if(IsPrime[i])count++;
    printf("%d\n", count);
    return 0;
}

4,算法5特性
有穷性、确定性(步骤无歧义)、有效性(比如除以0是无效的)、可以没输入、必须有输出;

5,△课后有文字描述题预留总结

第三章 顺序程序设计

概念和例题

1,scanf对应double的是%lfprintf对应double的可以是%f或者%lf
△△△非常易错:
C语言——基础查漏补缺(三):谭浩强红书刷题笔记大杂烩_第1张图片
利用上述公式进行华氏度到摄氏度的转换,阅读下列错误代码,找出错误:

#include

int main(){
     
    double c, f;
    scanf("%lf", &f);
    c = 5 / 9 * (f - 32);
    printf("%lf\n", c);
    return 0;
}

错误:c = 5 / 9 * (f - 32);,错因:59都是int,5/9是0,则参与运算的时候5/9会先被转化为(double)(0.0),0乘任何数都得0.
多嘴一句:f-32也是double型,因为f是double型。

更正:c = 5.0 / 9 * (f - 32);,当然为了好看,可以将9也变成9.0.

2,常量、常变量、符号常量
C语言——基础查漏补缺(三):谭浩强红书刷题笔记大杂烩_第2张图片
3,合法标识符
C语言——基础查漏补缺(三):谭浩强红书刷题笔记大杂烩_第3张图片
4,算术类型、纯量类型、组合类型

C语言——基础查漏补缺(三):谭浩强红书刷题笔记大杂烩_第4张图片
5,整型常量和浮点型常量

在这里插入图片描述
C语言——基础查漏补缺(三):谭浩强红书刷题笔记大杂烩_第5张图片
可以强制指定浮点型常量的类型
C语言——基础查漏补缺(三):谭浩强红书刷题笔记大杂烩_第6张图片
6,赋值表达式例题

  • 基础例题:
    在这里插入图片描述
  • 错误例子
    C语言——基础查漏补缺(三):谭浩强红书刷题笔记大杂烩_第7张图片
  • 综合例题
    在这里插入图片描述
    ⚠️注意:赋值运算符是从右向左结合:
    在这里插入图片描述
    7,
    在这里插入图片描述
    8,留意八进制和十六进制输出

C语言——基础查漏补缺(三):谭浩强红书刷题笔记大杂烩_第8张图片
9,留意实型三种输出方法

在这里插入图片描述
对于%g,系统自动选择按照%f或者%e输出,选择长度较短的方式,不输出无意义的0.但注意,上述选择了用%e输出时,指数部分为e+013,其中有一个0,这不是无意义的0,而是因为%e指数部分固定为5列。

10,留意scanf中长型和短型占位符

在这里插入图片描述
11,△△△一个scanf的样例(自己独立判断a,b,c分别什么值)

在这里插入图片描述C语言——基础查漏补缺(三):谭浩强红书刷题笔记大杂烩_第9张图片

课后习题总结

1,pow(a, b)的功能是返回 a b a^b ab的值;
2,charint输出

char c1 = 197;
printf("%d\n", c1);

分析上述输出结果,首先197用二进制表示是11000101,由于char是8位,所以c1被赋值为11000101,但是注意这个是c1的补码。而这个二进制第一位的1会被判定为负号,所以这个二进制会被判定为负数的补码,其原码为10111011,第一位是符号位,这个数字是-59.所以输出为-59.

3,intchar输出

int i = 330;
char c = i;
printf("%d\n", c);

分析输出结果,首先330是101001010,将它赋值给c,c是char型,只有8位,所以c被赋值为01001010,注意这个01001010是c的补码,不过由于首位符号位为0,代表c是正数,所以原码也就是它了。01001010的原码也是01001010 ,这是十进制的74,所以上述程序输出结果为74.

第四章 选择结构程序设计

概念和例题

1,条件表达式少见用法:
在这里插入图片描述
2,警惕switch语句,可能看上去会,实际敲的时候敲错,所以保险起见随便敲一个看看自己是否能敲对;

3,⚠️判断b*b-4*a*c是否等于0的方法(不大于1e-6即可)

#include
int main(){
     
	...
	if(fabs(b*b-4*a*c)<=1e-6)	// 不大于1e-6即可
		...
	...
}

4,逻辑与优先级高于逻辑或

a || b && c等价于a || (b && c),但省略括号会有警告:
'&&' within '||' [-Wlogical-op-parentheses]
所以最好乖乖加上括号。

5,除以0的报错
Floating point exception: 8
有一次报了这个错误,最终发现代码中有整数除以0的情况。
据说如果%操作出现对0取余,也会出现这样的报错。

课后习题总结

在这里插入图片描述

第五章 循环结构程序设计

概念和例题

1,forgetchar联动例子

for(i=0;(c=getchar())!='\n',i+=c);

上述语句的作用是将输入的字符的ASCII码相加,直到输入换行符。

for(;(c=getchar())!='\n';)
	printf("%c", c);

上述语句的作用是每输入一个字符就立刻输出这个字符,直到输入换行符。

2,利用公式近似求π
在这里插入图片描述

#include

int main(){
     
    int sign = 1;
    double a = 0.0;
    for(double i=1;1/i>=1e-6;i+=2){
     
        a += (sign * 1 / i);
        sign *= -1;
    }
    printf("%10.8f\n", a * 4);
    return 0;
}

结果

3.14159065

课后习题总结

1,☆☆☆(背)辗转相除法
输入n和m,输出n和m的最大公约数和最小公倍数:
核心算法在内层的while

#include

int main(){
     
    int m, n, p, r;
    int temp;
    while(scanf("%d %d", &n, &m)==2){
     
        if(n<=m){
     
            temp = m;
            m = n;
            n = temp;
        }
        p = m * n;
        r = 1;  // 余数变量,初始化随便赋值一个非零数

        // r=0时的m就时最大公约数,不过注意循环结束时m的值储存在n
        // 原始m*n的值除以最大公约数就是最小公倍数
        while(r!=0){
     
            r = n % m;
            n = m;
            m = r;
        }
        printf("最大公约数:%d\n", n);
        printf("最小公倍数:%d\n", p / n);
    }

    return 0;
}

输入输出样例:

4 3
最大公约数:1
最小公倍数:12
3 6
最大公约数:3
最小公倍数:6

2,处理手动输入的字符,直到回车结束(回车不处理)

while((c=getchar())!='\n')

3,☆求平方根的迭代公式
x n + 1 = 1 2 ( x n + a x n ) x_{n+1}=\frac{1}{2}(x_n+\frac{a}{x_n}) xn+1=21(xn+xna)
要求前后两次求出的x的差的绝对值 ∣ x n + 1 − x n ∣ |x_{n+1}-x_n| xn+1xn小于 1 0 − 5 10^{-5} 105,则此时的a的平方根近似为 x n + 1 x_{n+1} xn+1
初始化 x 0 x_0 x0 a 2 \frac{a}{2} 2a即可。

代码略,记住算法就会写了。

tip:math.h中的fabs(x)可以求x的绝对值

4,☆☆☆牛顿迭代法
C语言——基础查漏补缺(三):谭浩强红书刷题笔记大杂烩_第10张图片
图片来自谭浩强C语言学习辅导。

注意上图求的是 f ( x ) = 0 f(x)=0 f(x)=0的近似解,也就是接近x轴的交点。

将这个算法记住即可,编程不难,注意实型变量的赋值即可(比如:实型=整型/整型,这句就是错的,会导致实型变量损失巨量精度)。

5,简单问题程序化的例子(怕忘)
在这里插入图片描述C语言——基础查漏补缺(三):谭浩强红书刷题笔记大杂烩_第11张图片

⚠️注意:

  • 循环时添加if语句使得三人的对手不会重复
  • 最内层的if加入题目的所有限制信息

第六章 数组

概念和例题

1,数组的长度必须是常量而不是变量,但有种情况除外(忘了就看C语言总结一);
2,可以用整型数组存放字符型数据,因为字符型数据是按照整数形式(ASCII)存放的。但这样做十分浪费空间;
3,☆☆☆字符数组有些东西容易忘掉,自行看C语言总结一;
4,strcpystrncpy对比
重点注意注释中对printf结果的描述;
⚠️注:简记就是strcpy会复制\0strncpy是指定几位就复制几位,不会自动复制\0

#include
#include

int main(){
     
    char str1[] = "1234567890";
    char str2[] = "china";
    int l1 = strlen(str1);
    int l2 = strlen(str2);
    int l3;
    strcpy(str1, str2);
    printf("%s\n", str1);
    l3 = strlen(str1);
    printf("%d %d %d\n", l1, l2, l3);   // 输出10,5,5
    return 0;
}
#include
#include

int main(){
     
    char str1[] = "1234567890";
    char str2[] = "china";
    int l1 = strlen(str1);
    int l2 = strlen(str2);
    int l3;
    strncpy(str1, str2, 5);
    printf("%s\n", str1);
    l3 = strlen(str1);
    printf("%d %d %d\n", l1, l2, l3);   // 输出10,5,10
    return 0;
}

课后习题总结

1,质数筛法
简单版:C语言——基础查漏补缺(三):谭浩强红书刷题笔记大杂烩_第12张图片

复杂版:
简单版会导致一些数字重复被筛掉,徒增不必要的时间复杂度。复杂版见此文:复杂版质数筛,算法写在了文中代码注释里。

2,输出杨辉三角(以空间换便利)
C语言——基础查漏补缺(三):谭浩强红书刷题笔记大杂烩_第13张图片
这道题有两种办法,一种空间复杂度小但麻烦——用一个数组依次从左至右从上至下存储杨辉三角中的元素,n行杨辉三角占用 n ( n + 1 ) / 2 n(n+1)/2 n(n+1)/2个存储空间;一种空间复杂度较大但简单——直接用一个二维数组(矩阵)存储杨辉三角,占用 n 2 n^2 n2的空间,虽然这样会浪费约一半的存储空间,但编程方便。

书上给的代码:
C语言——基础查漏补缺(三):谭浩强红书刷题笔记大杂烩_第14张图片
先将对角线和第一列元素初始化为1,然后再为其他元素赋值。

总之记住,要用矩阵存储杨辉三角,用较小的浪费空间的代价换取编程的方便是值得的。

杨辉三角是 ( a + b ) n (a+b)^n (a+b)n展开后各项的系数

3,☆☆魔方阵
输入奇数 n n n,输出 1 ∼ n 2 1\sim n^2 1n2组成的魔方阵(魔方阵就是行、列、对角线之和都相等)。

书上已经将算法讲清楚了:
C语言——基础查漏补缺(三):谭浩强红书刷题笔记大杂烩_第15张图片

巧记

  • 每一个数在上一个数行数减一、列数加一(1放在一行中间)
  • 如果位置被占,就放在上一个数的下面
    (如果越界就循环找位置)

第七章 函数

概念和例题

1,Hanoi汉诺塔递归

#include

// 将n号圆盘从a移动到b
void move(int n, char a, char b){
     
    printf("move %d from %c to %c\n", n, a, b);
}

// 将n个从a借助b移动到c
void Hanoi(int n, char a, char b, char c){
     
    if(n>0){
     
        Hanoi(n-1, a, c, b);
        move(n, a, c);
        Hanoi(n-1, b, a, c);
    }
}

int main(){
     
    int n;
    char a = 'a', b = 'b', c = 'c';
    while(scanf("%d", &n)==1){
     
        Hanoi(n, a, b, c);
    }
    return 0;
}

课后习题总结

1,加强版质数筛法
(留白)
2,⚠️⚠️⚠️scanf输入多个字符串
(关键知识:以回车、空格或tab作为分隔)

	char a[100], b[100];
    int i = 0;
    scanf("%s%s", a, b);

如果输入

how are

和输入

how     are

是一样的,a被赋值为how,b被赋值为are(多余的部分是'\0'

⚠️看一个错误的想法:

	char a[100], b[100];
    int i = 0;
    scanf("%s\n%s", a, b);

输入

how are\nyou

以为a赋值为how are,b赋值为you,实际上a和b的值和上一个例子一样。
☆☆☆原因:
scanf输入多个字符时,是用空格、回车或者tab作为分隔,所以输入how are\nyou时,第一个空格就会成为分隔(这样回车就是结束符,回车后的you直接被忽略),尽管scanf中试图指定\n为分隔,但这么做系统不会鸟你。

补充:读程练习:

	char a[100], b[100], c[100], d[100];
    scanf("%s%s", a, b);
    scanf("%s%s", c, d);
    printf("%s\n%s\n%s\n%s\n", a, b, c, d);

输入

how are you you\n

输出

how
are
you
you

且注意,直到输入最后一个\n后,才会一下输出所有结果,因为scanf视其为结束符。

3,☆☆☆你可能以为简单的题——输入一行字符,输出这行字符中最长的单词(假设连续的字母都是单词)

⚠️注释讲了重要错误

#include

void func(char a[]){
     
    int start, i, maxlen = 0, tempstart, 
     templen = 0, flag = 0;
    i = 0;
    while(a[i]!='\0'){
     
        if((a[i]<='z'&&a[i]>='a')
        ||(a[i]<='Z'&&a[i]>='A')){
     
            if(flag==1){
     
                ++templen;
            }
            else{
     
                ++templen;
                flag = 1;
                tempstart = i;
            }
        }
        else{
     
            if(flag==1){
     
                flag = 0;
                if(templen>maxlen){
     
                    maxlen = templen;
                    // templen = 0; // 重要错因:这句错放到这里,导致templen只会在比maxlen大的时候才清零
                    start = tempstart;
                }
                templen = 0;
            }
        }
        ++i;
    }
    if(flag==1){
         // 如果字符串是字母结尾,不加这一段的话会忽略掉最后一个单词
        if(templen>maxlen){
     
            maxlen = templen;
            start = tempstart;
        }
    }
    while(maxlen-->0){
     
        printf("%c", a[start++]);
    }
    printf("\n");
}

int main(){
     
    char a[100], i;
    gets(a);
    func(a);
    return 0;
}

4,☆☆☆你以为很简单系列——整数转化为字符串
要求:输入整数,长度未知,以字符串输出。
记住用递归会非常简单

void func(int a){
     
    if(a/10!=0){
     
        func(a/10);
    }
    printf("%c", (a % 10) + '0');
}

第八章 指针

概念补漏

自行学习
(无聊的概念有点多,特别注意指针和数组、指针和多维数组、int (*)[4]类型指针、指针和字符串、函数的指针、指针数组和多重指针)

概念和例题

1,☆☆☆二维数组名≠指针的指针
用户CodeBlove的解释

2,☆☆指针变量控制数组
下列代码试图实现:输入10个数,并输出这10个数。
判断下列代码能否正确实现这个功能。
C语言——基础查漏补缺(三):谭浩强红书刷题笔记大杂烩_第16张图片
3,之后的题暂时跳过,原因是这一章例题部分都是概念题,没有算法题,且很多指针的用法很少见,看得太早怕忘且不实用。

课后习题总结

1,编写函数,交换两个字符串,要求形参以指针形式出现
△注意和交换两个数字不太一样

void swap(char * a, char * b){
     
    char p[100];
    strcpy(p, a);
    strcpy(a, b);
    strcpy(b, p);
}

2,写一个函数,操作长度n的整型数组,实现下图功能:
C语言——基础查漏补缺(三):谭浩强红书刷题笔记大杂烩_第17张图片
很简单,但要求用指针操作,所以以此题为例子

#include

void reverse(int * a, int start, int end){
     
    // int * temp = NULL;  // 不建议这样做
    int temp;
    int * p = a + start;
    int * q = a + end;
    while(p<q){
     
        temp = *p;
        *p = *q;
        *q = temp;
        ++p;
        --q;
    }
}

void func(int * a, int n, int m){
     
    reverse(a, 0, n-m-1);
    reverse(a, n-m, n-1);
    reverse(a, 0, n-1); // 不慎犯错:n-1写成n,造成错误abort trap
}

int main(){
     
    int a[10];
    for(int i=0;i<10;++i){
     
        scanf("%d", a+i);
    }
    func(a, 10, 3);
    for(int i=0;i<10;++i){
     
        printf("%d ", *(a+i));
    }
    printf("\n");
    return 0;
}

3,输入n,n个人围一圈,123123123…这样报数,报到3的人退出,求最后退出的人是几号,输出之。

#include

int next(int * a,int n, int i){
     
    i = (i + 1) % n;
    while(*(a+i)==-1){
     
        i = (i + 1) % n;
    }
    return i;
}

int func(int * a, int n){
     
    int i, lasti = -1, count = 0;
    for(i=0;i!=lasti;i=next(a, n, i)){
     
        ++count;
        if(count==3){
     
            *(a + i) = -1;
            count = 0;
        }
        lasti = i;
    }
    return i + 1;   // 注意是i+1,因为从1开始计数
}

int main(){
     
    int n, a[100];
    scanf("%d", &n);
    printf("%d\n", func(a, n));
    return 0;
}

4,☆数组名为实参,指针为形参新用法
注意下面代码的func函数,其中直接对指针a和b进行操作,而不会影响到func外实参的值。

#include
#include

// 将字符数组a从第m位开始复制到b中
void func(char * a, int n, int m, char * b){
     
    for(int i=1;i<=m-1;++i)
        ++a;
    while(*a!='\0'){
     
        *b = *a;
        ++b;
        ++a;
    }
    *b = '\0';
}

int main(){
     
    char a[100], b[100];
    int n, m;
    scanf("%s", a);
    n = strlen(a);
    scanf("%d", &m);
    func(a, n, m, b);
    puts(b);
}

5,☆☆☆用指针控制矩阵转置(学习没用过的指针操作)
C语言——基础查漏补缺(三):谭浩强红书刷题笔记大杂烩_第18张图片
注意到它直接用指针指向a[0][0],然后进行操作。可以看出二维数组可以视为按行存储的。

6,△程序纠错题
检查下列代码的错误
(输入5*5矩阵,最大元素和中心交换,并输出。要求用指针控制)

#include

void change(int * p){
        // p指向a[0][0]
    int temp, max, maxi, maxj, i, j;
    int * q = p;
    max = *p;
    maxi = 0;
    maxj = 0;
    for(i=0;i<5;++i){
     
        for(j=0;j<5;++j){
     
            if(*(q+5*i+j)>max){
     
                maxi = i;
                maxj = j;
                max = *(q+5*i+j);
            }
        }
    }
    q = p + 5 * i + j;
    temp = *q;
    *q = *p;
    *p = temp;
}

int main(){
     
    int a[5][5], i, j;
    int * p = &a[0][0];
    for(i=0;i<5;++i){
     
        for(j=0;j<5;++j)
            scanf("%d", *(a+i)+j);
    }
    change(p);
    for(i=0;i<5;++i){
     
        for(j=0;j<5;++j){
     
            printf("%d ", *(*(a+i)+j));
        }
        printf("\n");
    }
    return 0;
}

答案:

change函数倒数第五行的i和j分别改成maxi和maxj。

⚠️接下来对比指向数组的指针和指针数组
7.1,☆☆☆指向数组的指针
通过读程学会指向一位数组的指针char (*p)[6]的用法:
(题目是输入十个等长字符串,对其进行冒泡排序)
(复习时这道题需要自己敲一遍)

C语言——基础查漏补缺(三):谭浩强红书刷题笔记大杂烩_第19张图片C语言——基础查漏补缺(三):谭浩强红书刷题笔记大杂烩_第20张图片
说明:p是指向一维字符数组的指针,字符数组的长度为6;str[10][6]是二维数组,由10个长度为6的一维数组组成;可以将str赋值给p,这样p+i就指向str二维数组中第i行,*(p+i)或者p[i]指向str中第i行第1个元素,即str[i][0]。⚠️且注意str本身也是指向长度为6的一维字符数组的指针,它指向的是str[10][6]的第1行,所以同理str+i指向第i行,*(str+i)或者str[i]指向str中第i行第1个元素,即str[i][0]

7.2,☆☆☆指针数组
(题目是输入十个不等长字符串,对其进行冒泡排序)
(复习时这道题需要自己敲一遍)
在这里插入图片描述
说明:char * p[10]p[i]自己就是一个char *型指针.

8,课后13-21涉及函数指针等其他少见用法
(留白)

其他章节

结构体

1,对某一成员初始化
C语言——基础查漏补缺(三):谭浩强红书刷题笔记大杂烩_第21张图片

2,判断两个字符串是否相等:
只需看strcmp(a,b)==0是否成立。

3,同类型的结构体变量可以直接相互赋值
在这里插入图片描述
4,结构体数组使用样例,忘了则看:
C语言——基础查漏补缺(三):谭浩强红书刷题笔记大杂烩_第22张图片
(上述代码不完整)上述代码作用是将学生按照成绩排序,可见结构体变量之间可以直接相互赋值(图中倒数第二行)

5,指向结构体数组的指针使用样例,忘了则看:
C语言——基础查漏补缺(三):谭浩强红书刷题笔记大杂烩_第23张图片

☆☆☆共用体(没用过)

1,概念和基本用法
C语言——基础查漏补缺(三):谭浩强红书刷题笔记大杂烩_第24张图片
C语言——基础查漏补缺(三):谭浩强红书刷题笔记大杂烩_第25张图片

2,所占内存在这里插入图片描述
⚠️共用体在有些书中也称为“联合”

3,使用实例:
C语言——基础查漏补缺(三):谭浩强红书刷题笔记大杂烩_第26张图片
4,△判断正误:
C语言——基础查漏补缺(三):谭浩强红书刷题笔记大杂烩_第27张图片
答案:

是错的,因为初始化表中只能有一个常量

以下两种方式都是对的:
在这里插入图片描述
这是对共用体中的i初始化为16;

在这里插入图片描述
这是指定对共用体中的ch初始化为'j'

5,对共用体变量多次赋值,最后一次起作用。

C语言——基础查漏补缺(三):谭浩强红书刷题笔记大杂烩_第28张图片
后一次覆盖前一次,最终共用体变量的存储单元中存放的是40.

6,同类型共用体变量之间可以相互赋值:
在这里插入图片描述
7,作函数参数:
指向共用体变量的指针可以作函数参数;
C99规定共用体变量也可作函数参数。

8,用途:
如果需要对同一段空间安排不同的用途,那么就可以使用共用体。

9,☆应用实例

C语言——基础查漏补缺(三):谭浩强红书刷题笔记大杂烩_第29张图片
这是学校的成员表,如果是学生,则第五列存放班级;如果是教师,则第五列存放职位。

假设只有两个人,则定义结构体如下:
C语言——基础查漏补缺(三):谭浩强红书刷题笔记大杂烩_第30张图片
第五列用共用体表示即可。
这样,初始化时用如下方法即可:
C语言——基础查漏补缺(三):谭浩强红书刷题笔记大杂烩_第31张图片

☆枚举类型(少见)

见C语言查漏补缺一

typedef

见C语言查漏补缺一

链表的题

1,用链表实现约瑟夫环问题

// ch9课后6 输入n,n人围一圈,报数,报到3的退出,
// 输出最后一人的序号,用链表实现
#include
#include  // malloc和free

typedef struct node{
     
    int no;
    struct node * next;
} * linklist, node;

int num(linklist head){
     
    node * pre, * p, * q;
    int count = 0;
    if(head->next==head)
        return head->no;
    count = 2;
    p = head->next;
    pre = head;
    while(p->next!=p){
     
        pre = p;
        p = p->next;
        ++count;
        if(count==3){
     
            q = p;
            p = p->next;
            pre->next = p;
            free(q);
            count = 1;
        }
    }
    return p->no;
}

// 长度为n的单循环链表
linklist create(int n){
     
    int count = 0;
    node * p, * pre, * head;
    p = (node*)malloc(sizeof(node));
    p->no = count + 1;
    ++count;
    pre = p;
    head = p;
    while(count<n){
     
        p = (node*)malloc(sizeof(node));
        p->no = count + 1;
        ++count;
        pre->next = p;
        pre = p;
    }
    pre->next = head;
    return head;
}

int main(){
     
    int n;
    scanf("%d", &n);
    printf("%d\n", num(create(n)));
    return 0;
}

对文件的操作自行看,不多

第十一章自行看,可用作读程纠错题

你可能感兴趣的:(编程语言学习,c,c语言,编程语言)