OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 7136|回复: 20

《C语言程序设计 现代方法》

[复制链接]

94

主题

370

帖子

0

精华

高级会员

Rank: 4

积分
865
金钱
865
注册时间
2016-8-25
在线时间
485 小时
发表于 2018-9-6 20:52:12 | 显示全部楼层 |阅读模式
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

94

主题

370

帖子

0

精华

高级会员

Rank: 4

积分
865
金钱
865
注册时间
2016-8-25
在线时间
485 小时
 楼主| 发表于 2018-9-6 21:53:06 | 显示全部楼层
本帖最后由 学习stm32f4 于 2018-9-7 15:35 编辑

是本好书,做个笔记。欢迎讨论。

第一章

第7页
揭穿神话。现今的编译器常常与过去的C语言基本假设不一致,我很乐于揭穿C语言的某些神话,并挑战一些存在了很久的C语言信条(例如,指针的算术运算一定比数组下标操作快)。我重新审查了C语言的旧惯例,保留了那些仍然有帮助的惯例。
不再强调“手工优化”。许多书籍指导读者编写一些技巧性较强的代码,以获得程序效率的些许提高。如今优化的C语言编译器随处可见,这些编程技巧往往已经不必要了;事实上,它们反而会降低程序的运行效率。

第21页
应用程序的输入/输出、存储管理以及其他众多服务都依赖于操作系统,因此操作系统一定不能运行得太慢。

第23页
紧贴标准。大多数C编译器都提供不属于C89或C99标准的特性和库函数。为了程序的可移植性,若非确有必要,最好避免使用这些特性和库函数。

问:Lint是做什么的?(p.4)
答:lint检查C程序中潜在的错误,包括(但不限于)可疑的类型组合、未使用的变量、不可达的代码以及不可移植的代码。lint会产生一系列程序员有必要从头到尾仔细阅读的诊断信息。使用lint的好处是,它可以检查出被编译器漏掉的错误。另一方面,我们需要记住使用lint,因为它太容易被忘记了。更糟的是,lint可以产生数百条信息,而这些信息中只有少部分涉及了实际错误。

问:如何获得lint?
答:如果使用UNIX系统,那么将会自动获得lint,因为它是一个标准的UNIX工具。如果采用其他操作系统,则可能没有lint。幸运的是,lint的各种版本都可以从第三方获得。在许多Linux发行版中都包含lint的增强版本splint(Secure Programming Lint),这一工具可以从www.splint.org免费下载。

第24页
问:有没有办法在不使用lint的情况下强制编译器进行更彻底的错误检查?
答:有。大多数编译器都能根据我们的要求进行更彻底的检查。除了检查错误(毫无疑问违背C语言规定的情况)外,大多数编译器还提供警告,指出可能存在问题的地方。有些编译器具有多个“警告级别”,选择较高的级别能发现更多问题。如果你的编译器支持多级警告,建议选择最高级别以便编译器执行其能力范围内最彻底的检查。第2章最后的“问与答”部分讨论了GCC编译器(2.1节)的错误检查选项,GCC编译器是随Linux操作系统发布的。

问:我很关心能让程序尽可能可靠的方法。除了lint和调试工具以外,还有其他有效的工具吗?
答:有的。其他常用的工具包括越界检查工具(bounds-checker)和内存泄漏检测工具(leak-finder)。C语言不要求检查数组下标,而越界检查工具增加了此项功能。内存泄漏监测工具帮助定位“内存泄漏”,即那些动态分配却从未被释放的内存块。
回复 支持 反对

使用道具 举报

94

主题

370

帖子

0

精华

高级会员

Rank: 4

积分
865
金钱
865
注册时间
2016-8-25
在线时间
485 小时
 楼主| 发表于 2018-9-7 14:57:56 | 显示全部楼层
本帖最后由 学习stm32f4 于 2018-9-7 15:29 编辑

第二章

第28页
由于语句可以连续占用多行,有时很难确定它的结束位置,因此用分号来向编译器显示语句的结束位置。但指令通常都只占一行,因此不需要用分号结尾。


第32页
当我们把一个包含小数点的常量赋值给float型变量时,最好在该常量后面加一个字母f(代表float):
profit=2150.48f;
不加f可能会引发编译器的警告。

如果要显示float型变量,需要用%f来代替%d。默认情况下,%f会显示出小数点后6位数字。如果要强制%f显示小数点后p位数字,可以把.p放置在%和f之间。例如为了显示信息
Profit: $2150.48
可以把printf写为如下形式:
printf(“Profit: $%.2f\n”,profit);


第33页
当程序开始执行时,某些变量会被自动设置为零,而大多数变量则不会(18.5节)。


第34页
scanf中的字母f和printf中的字母f含义相同,都是表示“格式化”(format)的意思。


第37页
37.png

第38页
38.png

第40页
40_1.png

40_2.png

40_3.png

40_4.png
第41页
41_1.png

41_2.png

第42页
编程题
[mw_shl_code=c,true]1.
#include "stdio.h"

int main()
{
    int i,j;
    for(i=0;i<6;i++)
    {
        for(j=0;j<8;j++)
        {
            if((i==0 && j==7) ||
               (i==1 && j==6) ||
               (i==2 && j==5) ||
               (i==3 && (j==0 || j==4)) ||
               (i==4 && (j==1 || j==3)) ||
               (i==5 && j==2))
            {
                printf("*");
            }
            else
            {
                printf(" ");
            }
        }
        printf("\n");
    }
    return 0;
}

2.
#include "stdio.h"
#include "math.h"

int main(void)
{
    float r = 10.0f, v;
    v = 4.0f / 3.0f * M_PI * r * r * r;
    printf("v = %.3f\n",v);
    return 0;
}

3.
#include "stdio.h"
#include "math.h"

int main(void)
{
    float r, v;
    printf("Enter r: ");
    scanf("%f", &r);
    v = 4.0f / 3.0f * M_PI * r * r * r;
    printf("v = %.3f\n",v);
    return 0;
}

7.
#include "stdio.h"

int main(void)
{
    int a[4]={20,10,5,1},b[4]={0};
    int amount,i;
    printf("amount: ");
    scanf("%d",&amount);
    for(i=0;i<4;i++)
    {
        b=amount/a;
        printf("%d\n",b);
        if(b==0)
            continue;
        amount-=a*b;
    }
    return 0;
}

8.
#include "stdio.h"

int main(void)
{
    float s[4]={20000.0f,0.0f};
    int i;
    for(i=1;i<4;i++)
    {
        s=(1+0.06f/12)*s[i-1]-386.66f;
        printf("%.2f\n",s);
    }
    return 0;
}
[/mw_shl_code]


回复 支持 反对

使用道具 举报

109

主题

5556

帖子

0

精华

资深版主

Rank: 8Rank: 8

积分
10447
金钱
10447
注册时间
2017-2-18
在线时间
1889 小时
发表于 2018-9-7 15:34:08 | 显示全部楼层
多谢分享
回复 支持 反对

使用道具 举报

94

主题

370

帖子

0

精华

高级会员

Rank: 4

积分
865
金钱
865
注册时间
2016-8-25
在线时间
485 小时
 楼主| 发表于 2018-9-8 12:36:02 | 显示全部楼层
第三章

第44页
44.png

第45页
45.jpg
例如:
i=40;
printf(“%5.3d”,i);

输出﹂﹂040。(﹂表示空格)

第48页
48.png

第49页
49.png

第50页
50.png

第51页
51.png

51-2.png

51-3.png

51-4.png
例如:
int i=0,j=0;
scanf(“%d%d”,&i,&j);

在控制台输入1,2后,那么i=1,j还是0。

第53页

编程题
[mw_shl_code=c,true]
2.
#include "stdio.h"

int main(void)
{
    int item,mm,dd,yyyy;
    float price;
    printf("Enter item number: ");
    scanf("%d",&item);
    printf("Enter unit price: ");
    scanf("%f",&price);
    printf("Enter purchase date (mm/dd/yyyy): ");
    scanf("%d/%d/%d",&mm,&dd,&yyyy);
    printf("Item\tUnit    \tPurchase\n    \tPrice   \tDate\n");
    printf("%-4d\t$%7.2f\t%02d/%02d/%d\n",item,price,mm,dd,yyyy);
    return 0;
}

5.
#include "stdio.h"

int main(void)
{
    int a[16]={0},i,sum=0;
    for(i=0;i<16;i++)
        scanf("%d",a+i);
    for(i=1;i<=16;i++)
    {
        printf("%2d  ",a[i-1]);
        if(i%4==0)
            printf("\n");
    }
    printf("Row sums: ");
    for(i=1;i<=16;i++)
    {
        sum+=a[i-1];
        if(i%4==0)
        {
            printf("%d  ",sum);
            sum=0;
        }
    }
    printf("\nColumn sums: ");
    for(i=0;i<4;i++)
    {
        printf("%d  ",a+a[i+4]+a[i+8]+a[i+12]);
    }
    printf("\nDiagonal sums: ");
    sum=0;
    for(i=0;i<16;i++)
    {
        if(i%5==0)
            sum+=a;
    }
    printf("%d  ",sum);
    sum=0;
    for(i=0;i<16;i++)
    {
        if((i!=0) && (i!=15) && (i%3==0))
            sum+=a;
    }
    printf("%d  \n",sum);
    return 0;
}
[/mw_shl_code]



回复 支持 反对

使用道具 举报

94

主题

370

帖子

0

精华

高级会员

Rank: 4

积分
865
金钱
865
注册时间
2016-8-25
在线时间
485 小时
 楼主| 发表于 2018-9-8 16:12:19 | 显示全部楼层
本帖最后由 学习stm32f4 于 2018-9-8 19:54 编辑

第四章

第55页
55.png

第57页
scanf(“%1d”,&a);
只将输入的数的1个位保存在变量a中。

第58页
58.png

58-2.png

第63页
63.png

第64页
64.png

64-2.png

第65页
65.png
65-2.png

第67页
[mw_shl_code=c,true]4.
#include "stdio.h"

int main(void)
{
    int a[5]={0},i=0,j=0,num;
    printf("Enter a number between 0 and 32767: ");
    scanf("%d",&num);
    while(num!=0)
    {
        a[i++]=num%8;
        num/=8;
    }
    for(i=0;i<5;i++)
    {
        if(a!=0)
            j++;
        else
            break;
    }
    printf("In octal, you number is: 0");
    for(i=j-1;i>=0;i--)
        printf("%d",a);
    printf("\n");
    return 0;
}

[/mw_shl_code]
回复 支持 反对

使用道具 举报

94

主题

370

帖子

0

精华

高级会员

Rank: 4

积分
865
金钱
865
注册时间
2016-8-25
在线时间
485 小时
 楼主| 发表于 2018-9-9 22:22:49 | 显示全部楼层
本帖最后由 学习stm32f4 于 2018-9-10 23:00 编辑

第五章

第69页
69.png

第70页
70.png

第75页
75.png

第77页
77.png

77-2.png

第78页
78.png

78-2.png

第82页
82.png

82-2.png

第83页
83.png
i>j?1: ((i==j)?0:-1)或者(i>j)-(i<j)

第86页
[mw_shl_code=c,true]9.
#include "stdio.h"

int main(void)
{
    int mm1,dd1,yy1,mm2,dd2,yy2,flag_m,flag_d,flag_y,flag;
    printf("Enter first date (mm/dd/yy): ");
    scanf("%d/%d/%d",&mm1,&dd1,&yy1);
    printf("Enter second date (mm/dd/yy): ");
    scanf("%d/%d/%d",&mm2,&dd2,&yy2);
    flag_m=(mm1>mm2)-(mm1<mm2);
    flag_d=(dd1>dd2)-(dd1<dd2);
    flag_y=(yy1>yy2)-(yy1<yy2);
    if(flag_y==1)
        flag=1;
    else if(flag_y==0)
    {
        if(flag_m==1)
            flag=1;
        else if(flag_m==0)
        {
            if(flag_d==1)
                flag=1;
            else if(flag_d==0)
                flag=0;
            else
                flag=2;
        }
        else
            flag=2;
    }
    else
        flag=2;
    switch(flag)
    {
        case 0:  printf("%d/%d/%d == %d/%d/%d",mm1,dd1,yy1,mm2,dd2,yy2);break;
        case 1:  printf("%d/%d/%d > %d/%d/%d",mm1,dd1,yy1,mm2,dd2,yy2);break;
        case 2:  printf("%d/%d/%d < %d/%d/%d",mm1,dd1,yy1,mm2,dd2,yy2);break;
        default: break;
    }
    return 0;
}

11.
#include "stdio.h"

int main(void)
{
    int num;
    char str[][10]={
        "ten",
        "eleven",
        "twelve",
        "thirteen",
        "fourteen",
        "fifteen",
        "sixteen",
        "seventeen",
        "eighteen",
        "nineteen",
        "twenty",
        "thirty",
        "forty",
        "fifty",
        "sixty",
        "seventy",
        "eighty",
        "ninety",
        "one",
        "two",
        "three",
        "four",
        "five",
        "six",
        "seven",
        "eight",
        "nine"
    };
    printf("Enter a two-digit number: ");
    scanf("%d",&num);
    if(num>=10 && num<=19)
    {
        printf("%s\n",str[num-10]);
    }
    else if(num%10==0)
        printf("%s\n",str[num/10+8]);
    else
        printf("%s-%s\n",str[num/10+8],str[num%10+17]);
    return 0;
}

[/mw_shl_code]

附录:字符数组的大小,至少应比实际存放字符个数多1个,多出来的用于存放'\0'。例如char str[4]={"abc"};

多维字符数组
一维字符数组:
char s[10]={"a"};
字符串a的首地址是s。
puts(s)输出a

二维字符数组:
char s2[][10]={"ab","cd"};
它是这样表示的:
1.png
字符串ab的首地址是s2[0],字符串cd的首地址是s2[1],这里方括号表示第二维。
puts(s2[0])输出ab
putchar(s2[0][1])输出b

三维字符数组:
char s3[][2][10]={{"abc","def"},{"123","456"},{"ABC","DEF"}};
它是这样表示的:
2.png
字符串abc的首地址是s3[0][0],字符串DEF的首地址是s3[2][1],这里从右数第一个方括号表示第二维,第二个方括号表示第三维。
puts(s3[0][0])输出abc,puts(s3[2][1])输出DEF
putchar(s3[2][1][0])输出D




回复 支持 反对

使用道具 举报

94

主题

370

帖子

0

精华

高级会员

Rank: 4

积分
865
金钱
865
注册时间
2016-8-25
在线时间
485 小时
 楼主| 发表于 2018-9-10 22:39:05 | 显示全部楼层
本帖最后由 学习stm32f4 于 2018-9-11 20:16 编辑

第六章

第93页
93.png

93-2.png

第94页
94.png

94-2.png

94-3.png

第97页
97.png

97-2.png

第98页
98.png

第101页
101.png

101-2.png

101-3.png

第105页
[mw_shl_code=c,true]8.
#include "stdio.h"

int main(void)
{
    int days,day,i;
    printf("Enter number of days in month: ");
    scanf("%d",&days);
    printf("Enter starting day of the week (1=Sun, 7=Sat): ");
    scanf("%d",&day);
    for(i=1;i<=31+day-1;i++)
    {
        if(i<day) printf("   ");
        else printf("%2d ",i-day+1);
        if(i%7==0) printf("\n");
    }
    return 0;
}

10.
#include "stdio.h"

int main(void)
{
    int mm,dd,yy,mm2,dd2,yy2;
    printf("Enter a date (mm/dd/yy): ");
    scanf("%d/%d/%d",&mm,&dd,&yy);
    do
    {
        printf("Enter a date (mm/dd/yy): ");
        scanf("%d/%d/%d",&mm2,&dd2,&yy2);
        if(yy2==0 && mm2==0 && dd2==0)
            break;
        if(yy2<yy)
        {
            mm=mm2;
            dd=dd2;
            yy=yy2;
        }
        else if(yy2==yy && mm2<mm)
        {
            mm=mm2;
            dd=dd2;
        }
        else if(yy2==yy && mm2==mm && dd2<dd)
            dd=dd2;
    }while(mm2!=0 && dd2!=0);
    printf("%d/%d/%2d is the earliest date\n",mm,dd,yy);
    return 0;
}
[/mw_shl_code]

附录:(gcc v5.1.0测试,-std=c99)
若f是flaot型的,则scanf时,用scanf("%f",&f)。
若f是double型的,则scanf时,用scanf("%lf",&f)。
无论f是float型还是double型,printf时,用printf("%f",f)。注:若-std=c89,则printf("%f",f)与printf("%lf",f)均可。
回复 支持 反对

使用道具 举报

94

主题

370

帖子

0

精华

高级会员

Rank: 4

积分
865
金钱
865
注册时间
2016-8-25
在线时间
485 小时
 楼主| 发表于 2018-9-11 20:24:21 | 显示全部楼层
第七章
第108页
108.png

第109页
109.png

109-2.png

109-3.png

109-4.png

第110页
110.png

第111页
float精度是小数点后6个数字,double精度是小数点后15个数字。

第112页
112.png

112-2.png

第113页
113.png

113-2.png
例如:
char ch='a';
printf("%d,%d\n",sizeof(ch),sizeof('a'));
显示1,4

字符变量是char类型,而字符常量是int类型。

第115页
115.png

第116页
116.png

116-2.png

第124页
124.png

124-2.png

第125页
125.png

125-2.png

125-3.png

125-4.png

125-5.png

第128页
[mw_shl_code=c,true]1.
#include "stdio.h"

int main(void)
{
    short i=0,j;
    int i2,j2;
    long i3,j3;
    while(1)
    {
        j=i;
        i++;
        if(i<j) break;
    }
    printf("%10d\t%8x\n",j,j);
    i2=j;
    while(1)
    {
        j2=i2;
        i2++;
        if(i2<j2) break;
    }
    printf("%d\t%x\n",j2,j2);
    i3=j2;
    while(1)
    {
        j3=i3;
        i3++;
        if(i3<j3) break;
    }
    printf("%d\t%x\n",j3,j3);
    return 0;
}
short int values are usually stored in 16 bits, int and long int values are usually stored in 32 bits.

12.
#include "stdio.h"

int main(void)
{
    float f,f2,sum;
    char ch;
    printf("Enter an expression: ");
    scanf("%f",&f);
    ch=getchar();
    while(ch!='\n')
    {
        scanf("%f",&f2);
        switch(ch)
        {
            case '+':
                sum=(f+f2);
                break;
            case '-':
                sum=(f-f2);
                break;
            case '*':
                sum=(f*f2);
                break;
            case '/':
                sum=(f/f2);
                break;
            default:
                break;
        }
        f=sum;
        ch=getchar();
    }
    printf("%.2f\n",sum);
    return 0;
}

13.
#include "stdio.h"

int main(void)
{
    int length=0,word=0;
    char ch;
    scanf(" %c",&ch);
    while(ch!='\n')
    {
        if((ch>='a'&&ch<='z') || (ch>='A'&&ch<='Z') || (ch=='.' || ch==','))
        {
            length++;
        }
        if(ch==' ')
        {
            while(ch==' ')
            {
                ch=getchar();
                if(ch=='\n')
                {
                    word++;
                    printf("%.1f\n",(float)length/word);
                    return 0;
                }
            }
            word++;
            length++;
        }
        ch=getchar();
    }
    word++;
    printf("%.1f\n",(float)length/word);
    return 0;
}

[/mw_shl_code]

回复 支持 反对

使用道具 举报

94

主题

370

帖子

0

精华

高级会员

Rank: 4

积分
865
金钱
865
注册时间
2016-8-25
在线时间
485 小时
 楼主| 发表于 2018-9-17 13:20:12 | 显示全部楼层
本帖最后由 学习stm32f4 于 2018-9-25 16:38 编辑

第八章

第132页
132.png
确实是个循环。

第134页
134.png

第139页
139.png

第140页
140.png

140-2.png

第142页
142.png

142-2.png

142-3.png

第144页
[mw_shl_code=c,true]7.
#include "stdio.h"

int main(void)
{
    int i,j,sum=0;
    int a[5][5];
    int (*p)[5];
    for(i=0;i<5;i++)
    {
        printf("Enter row %d: ",i+1);
        for(j=0;j<5;j++)
            scanf("%d",*(a+i)+j);
    }
    printf("Row totals: ");
    for(i=0;i<5;i++)
    {
        sum=0;
        for(j=0;j<5;j++)
        {
            sum+=*(*(a+i)+j);
        }
        printf("  %d",sum);
    }
    printf("\nColumn totals: ");
    for(j=0;j<5;j++)
    {
        sum=0;
        for(i=0;i<5;i++)
        {
            p=(int (*)[5])(a+j);
            sum+=**p;
        }
        printf("  %d",sum);
    }
    return 0;
}

9.
#include "stdio.h"
#include "stdlib.h"
#include "time.h"
#include "stdbool.h"

int main(void)
{
    char str[10][10];
    int i,j,num=1,num2,count=0;
    bool flag;
    for(i=0;i<10;i++)
        for(j=0;j<10;j++)
            str[j]='.';
    srand(time(NULL));
    str[0][0]='A';
    i=0;
    j=0;
    while(num<26)
    {
        flag=true;
        while(flag)
        {
            count++;
            num2=rand()%4;
            switch(num2)
            {
                case 0:
                    i--;
                    if(i>=0&&str[j]=='.')
                    {
                        str[j]='A'+num;
                        flag=false;
                        break;
                    }
                    else
                    {
                        i++;
                        break;
                    }
                case 1:
                    i++;
                    if(i<=9&&str[j]=='.')
                    {
                        str[j]='A'+num;
                        flag=false;
                        break;
                    }
                    else
                    {
                        i--;
                        break;
                    }
                case 2:
                    j--;
                    if(j>=0&&str[j]=='.')
                    {
                        str[j]='A'+num;
                        flag=false;
                        break;
                    }
                    else
                    {
                        j++;
                        break;
                    }
                case 3:
                    j++;
                    if(j<=9&&str[j]=='.')
                    {
                        str[j]='A'+num;
                        flag=false;
                        break;
                    }
                    else
                    {
                        j--;
                        break;
                    }
                default:
                    break;
            }
            if(count>100)
            {
                for(i=0;i<10;i++)
                {
                    for(j=0;j<10;j++)
                        printf("%c ",str[j]);
                    printf("\n");
                }
                return 0;
            }
        }
        num++;
    }
    for(i=0;i<10;i++)
    {
        for(j=0;j<10;j++)
            printf("%c ",str[j]);
        printf("\n");
    }
    return 0;
}

14.
#include "stdio.h"
#include "string.h"

int main(void)
{
    char str[100]={'\0'};
    char *p,*q;
    int num,i;
    printf("Enter a sentence: ");
    gets(str);
    q=str+strlen(str)-1;
    while(!(*q>='a'&&*q<='z')&&!(*q>='A'&&*q<='Z'))
        q--;
    p=q;
    while(strlen(q)!=strlen(str))
    {
        while(*q!=' '&&strlen(q)!=strlen(str))
            q--;
        num=p-q;
        if(strlen(q)==strlen(str))
            num++;
        for(i=0;i<num;i++)
            if(*q==' ')
                printf("%c",*(q+i+1));
            else
                printf("%c",*(q+i));
        while(!(*q>='a'&&*q<='z')&&!(*q>='A'&&*q<='Z'))
        {
            printf("%c",*q);
            q--;
        }
        p=q;
    }
    printf("%c",str[strlen(str)-1]);
    return 0;
}
[/mw_shl_code]
附录:二维数组指针
对于一维数组,例如:
char str[4]={“abc”};
char *p;
p=str;
p指向一维数组的起始地址。
f1.jpg

对于二维数组,例如:
char str[3][3]={
{‘a’,’b’,’c’},
{‘d’,’e’,’f’},
{‘g’,’h’,’i’}
};
f2.jpg
str、str+1、str+2是行指针,str[2]+1等是列指针。由于str[2]可表示为*(str+2),故str[2]+1可表示为*(str+2)+1。

行指针前加*号就转变成列指针,例如行指针str+2前加*号为*(str+2),即为列指针str[2]。
列指针前加&号就转变成行指针,例如列指针str[2]前加&号为&str[2],即&*(str+2),为行指针str+2。
列指针前加*号就是取内容。


要想用一个指针变量指向列指针str[2]+2,则可定义该指针变量为:
char *p;
p=str[2]+2;

要想用一个指针变量指向行指针str+2,则可定义该指针变量为:
char (*p)[3];
p=str+2;
(*p)[3]称为数组指针,即指向包含3个元素的数组的指针。由此可见,行指针是char (*)[3]类型的,而列指针是char *类型的。此时,p--就使p指向了行指针str+1。若想让p索引‘d’,由于p此时指向行指针str+1,故先将其变成列指针,即*p,再对列指针取内容,即**p就是’d’了。又例如,让p指向’b’,写法是:
p=(char (*)[3])(str[0]+1);
那么,**p就是’b’,**(p+1)就是’e’。
又例,求各列和:
[mw_shl_code=c,true]#include "stdio.h"

int main(void)
{
    int a[3][3]={
        {2,1,5},
        {7,10,15},
        {4,3,8},
    };
    int (*p)[3];
    int i,j,sum=0;
    for(j=0;j<3;j++)
    {
        sum=0;
        for(i=0;i<3;i++)
        {
            p=(int (*)[3])(a+j);
            sum+=**p;
        }
        printf("%d\n",sum);
    }
    return 0;
}[/mw_shl_code]

二维数组作为函数实参时,以char str[3][3]为例,引用格式是f((char (*)[3])str)。






回复 支持 反对

使用道具 举报

94

主题

370

帖子

0

精华

高级会员

Rank: 4

积分
865
金钱
865
注册时间
2016-8-25
在线时间
485 小时
 楼主| 发表于 2018-9-19 17:50:55 | 显示全部楼层
第九章

第156页
156.png

第158页
158.png

158-2.png

158-3.png

第159页
159.png

159-2.png

159-3.png

第160页
160.png

第161页
161.png
161-2.png
exit()和return在main函数中是等价的,但是在其它函数中,例如:
int main(void)
{
       f();
       printf(“test\n”);
       return 0;
}
int f(void)
{
       exit(EXIT_SUCCESS);
}

调用f()中的exit()后,直接从f()函数里退出整个程序,不再返回main函数,故不会打印test。

第166页
166.png

166-2.png

166-3.png

166-4.png

166-5.png

166-6.png

第170页
将整数n的二进制格式保存在ch[]数组里。
[mw_shl_code=c,true]19.
#include "stdio.h"

void pb(char ch[],int n);

int main(void)
{
    char ch[32]={'\0'};
    int n;
    printf("Enter n: ");
    scanf("%d",&n);
    pb(ch,n);
    puts(ch);
    return 0;
}

void pb(char ch[],int n)
{
    static int i=0;
    if(n!=0)
    {
        pb(ch,n/2);
        ch[i++]='0'+n%2;
    }
}
[/mw_shl_code]

第171页
[mw_shl_code=c,true]1.
#include "stdio.h"

void selection_sort(int a[],int n);

int main(void)
{
    int a[10],i;
    printf("Enter: ");
    for(i=0;i<10;i++)
        scanf("%d",a+i);
    selection_sort(a,10);
    for(i=0;i<10;i++)
        printf("%d\t",a);
    return 0;
}

void selection_sort(int a[],int n)
{
    if(n==1) return;
    int *max=a,i,t;
    for(i=0;i<n;i++)
    {
        if(*max<a)
            max=a+i;
    }
    t=*max;
    *max=a[n-1];
    a[n-1]=t;
    selection_sort(a,n-1);
}

7.
#include "stdio.h"

double pow2(double x,int n);

int main(void)
{
    double x,res;
    int n;
    printf("Enter x,n: ");
    scanf("%lf,%d",&x,&n);
    res=pow2(x,n);
    printf("%.2f\n",res);
    return 0;
}

double pow2(double x,int n)
{
    if(n==0) return 1;
    else
    {
        if(n%2==0)
        {
            return pow2(x,n/2)*pow2(x,n/2);
        }
        else
            return x*pow2(x,n-1);
    }
}

8.
#include "stdio.h"
#include "time.h"
#include "stdlib.h"
#include "stdbool.h"

int roll_dice(void);
bool play_game(void);

int main(void)
{
    srand(time(NULL));
    char ch='\0';
    int win=0,lose=0;
    while(1)
    {
        if(play_game())
        {
            printf("You win!\n");
            win++;
        }
        else
        {
            printf("You lose!\n");
            lose++;
        }
        printf("Play again? ");
        scanf(" %c",&ch);
        if(ch=='n'||ch=='N') break;
    }
    printf("Wins: %d\tLosses: %d\n",win,lose);
    return 0;
}

int roll_dice(void)
{
    return (rand()%6+1)+(rand()%6+1);
}

bool play_game(void)
{
    int rd=roll_dice(),rd2;
    printf("You rolled: %d\n",rd);
    if(rd==7||rd==11)
        return true;
    else if(rd==2||rd==3||rd==12)
        return false;
    printf("You point is %d\n",rd);
    do
    {
        rd2=roll_dice();
        printf("You rolled: %d\n",rd2);
        if(rd2==7) return false;
    }while(rd2!=rd);
    return true;

}
[/mw_shl_code]

回复 支持 反对

使用道具 举报

94

主题

370

帖子

0

精华

高级会员

Rank: 4

积分
865
金钱
865
注册时间
2016-8-25
在线时间
485 小时
 楼主| 发表于 2018-9-26 12:55:52 | 显示全部楼层
本帖最后由 学习stm32f4 于 2018-9-26 13:02 编辑

第十章
第189页
[mw_shl_code=c,true]6.

#include "stdio.h"
#include "stdbool.h"
#include "stdlib.h"
#define STACK_SIZE 100

void push(int i);
int pop(void);

int top=0,contents[STACK_SIZE];

int main(void)
{
    int n=-1,n2,n3;
    char ch;
    printf("Enter an RPN expression: ");
    scanf("%c",&ch);
    if(ch>='0'&&ch<='9')
        n=ch-'0';
    else if(ch=='+')
        n=43;
    else if(ch=='-')
        n=45;
    else if(ch=='*')
        n=42;
    else if(ch=='/')
        n=47;
    else if(ch=='=')
        n=61;
    else if(ch=='q')
        n=113;
    else if(ch=='Q')
        n=81;
    else if(ch==' ')
        n=-1;
    while(n!=81&&n!=113)
    {
        if(n>=0&&n<=9)
            push(n);
        else
        {
            switch(n)
            {
                case 43:
                    n2=pop();
                    n3=pop();
                    push(n3+n2);
                    break;
                case 45:
                    n2=pop();
                    n3=pop();
                    push(n3-n2);
                    break;
                case 42:
                    n2=pop();
                    n3=pop();
                    push(n3*n2);
                    break;
                case 47:
                    n2=pop();
                    n3=pop();
                    push(n3/n2);
                    break;
                case 61:
                    printf("Value of expression: %d\n",pop());
                    printf("Enter an RPN expression: ");
                    getchar();
                    break;
                default:
                    break;
            }
        }
        scanf("%c",&ch);
        if(ch>='0'&&ch<='9')
            n=ch-'0';
        else if(ch=='+')
            n=43;
        else if(ch=='-')
            n=45;
        else if(ch=='*')
            n=42;
        else if(ch=='/')
            n=47;
        else if(ch=='=')
            n=61;
        else if(ch=='q')
            n=113;
        else if(ch=='Q')
            n=81;
        else if(ch==' ')
            n=-1;
    }
    return 0;
}

void make_empty(void)
{
    top=0;
}

bool is_empty(void)
{
    return top==0;
}

bool is_full(void)
{
    return top==STACK_SIZE;
}

void stack_underflow(void)
{
    printf("stack underflow.\n");
}

void stack_overflow(void)
{
    printf("stack overflow.\n");
}

void push(int i)
{
    if(is_full())
    {
        stack_overflow();
        exit(EXIT_FAILURE);
    }
    else
        contents[top++]=i;
}

int pop(void)
{
    if(is_empty())
    {
        stack_underflow();
        exit(EXIT_FAILURE);
    }
    else
        return contents[--top];
}
7.
#include "stdio.h"
#include "windows.h"

void print_digits(char str[]);
static void SetPos(int x,int y);

char digits[][3][4]={
        {
            {' ','_',' ',' '},
            {'|',' ','|',' '},
            {'|','_','|',' '},
        },
        {
            {' ',' ',' ',' '},
            {' ',' ','|',' '},
            {' ',' ','|',' '},
        },
        {
            {' ','_',' ',' '},
            {' ','_','|',' '},
            {'|','_',' ',' '},
        },
        {
            {' ','_',' ',' '},
            {' ','_','|',' '},
            {' ','_','|',' '},
        },
        {
            {' ',' ',' ',' '},
            {'|','_','|',' '},
            {' ',' ','|',' '},
        },
        {
            {' ','_',' ',' '},
            {'|','_',' ',' '},
            {' ','_','|',' '},
        },
        {
            {' ','_',' ',' '},
            {'|','_',' ',' '},
            {'|','_','|',' '},
        },
        {
            {' ','_',' ',' '},
            {' ',' ','|',' '},
            {' ',' ','|',' '},
        },
        {
            {' ','_',' ',' '},
            {'|','_','|',' '},
            {'|','_','|',' '},
        },
        {
            {' ','_',' ',' '},
            {'|','_','|',' '},
            {' ','_','|',' '},
        }
};

int main(void)
{
    print_digits("123-123");
    return 0;
}

void print_digits(char str[])
{
    int i,j,n=0;
    char *p=str;
    while(*p!='\0')
    {
        while(*p>='0'&&*p<='9')
        {
            for(i=0;i<3;i++)
            {
                SetPos(4*n,i);
                for(j=0;j<4;j++)
                {
                    printf("%c",digits[*p-'0'][j]);
                }
            }
            p++;
            n++;
        }
        p++;
    }
}

static void SetPos(int x,int y)
{
    COORD point = {x, y};
    HANDLE HOutput = GetStdHandle(STD_OUTPUT_HANDLE);
    SetConsoleCursorPosition(HOutput, point);
}
或者:
#include "stdio.h"
#include "string.h"

#define MAX_DIGITS 10

void clear_digits_array(void);
void process_digit(int digit,int position);
void print_digits_array(void);

const int segments[10][7]={
    {1,1,1,1,1,1,0},
    {0,1,1,0,0,0,0},
    {1,1,0,1,1,0,1},
    {1,1,1,1,0,0,1},
    {0,1,1,0,0,1,1},
    {1,0,1,1,0,1,1},
    {1,0,1,1,1,1,1},
    {1,1,1,0,0,0,0},
    {1,1,1,1,1,1,1},
    {1,1,1,1,0,1,1}
};
char digits[3][MAX_DIGITS*4];

int main(void)
{
    char ch;
    int i=0;
    clear_digits_array();
    printf("Enter digits: ");
    while((ch=getchar())!='\n')
    {
        if(i<MAX_DIGITS&&ch>='0'&&ch<='9')
            process_digit(ch-'0',i++);
    }
    print_digits_array();
    return 0;
}

void clear_digits_array(void)
{
    memset(digits,' ',sizeof(digits));
}

void process_digit(int digit,int position)
{
    int n=4*position;
    if(segments[digit][0])
        digits[0][n+1]='_';
    if(segments[digit][1])
        digits[1][n+2]='|';
    if(segments[digit][2])
        digits[2][n+2]='|';
    if(segments[digit][3])
        digits[2][n+1]='_';
    if(segments[digit][4])
        digits[2][n]='|';
    if(segments[digit][5])
        digits[1][n]='|';
    if(segments[digit][6])
        digits[1][n+1]='_';
}

void print_digits_array(void)
{
    int i,j;
    for(i=0;i<3;i++)
    {
        for(j=0;j<MAX_DIGITS*4;j++)
            printf("%c",digits[j]);
        printf("\n");
    }
}
[/mw_shl_code]
附录:设置控制台光标位置
[mw_shl_code=c,true]#include "windows.h"
static void SetPos(int x,int y)
{
    COORD point = {x, y};
    HANDLE HOutput = GetStdHandle(STD_OUTPUT_HANDLE);
    SetConsoleCursorPosition(HOutput, point);
}[/mw_shl_code]
1.jpg
回复 支持 反对

使用道具 举报

94

主题

370

帖子

0

精华

高级会员

Rank: 4

积分
865
金钱
865
注册时间
2016-8-25
在线时间
485 小时
 楼主| 发表于 2018-9-27 10:46:31 | 显示全部楼层
第十一章
第198页
198.png

198-2.png

198-3.png

198-4.png


回复 支持 反对

使用道具 举报

94

主题

370

帖子

0

精华

高级会员

Rank: 4

积分
865
金钱
865
注册时间
2016-8-25
在线时间
485 小时
 楼主| 发表于 2018-9-28 10:22:01 | 显示全部楼层
第十二章
第204页
204.png

第212页
212.png

212-2.png

212-3.png


回复 支持 反对

使用道具 举报

94

主题

370

帖子

0

精华

高级会员

Rank: 4

积分
865
金钱
865
注册时间
2016-8-25
在线时间
485 小时
 楼主| 发表于 2018-10-21 20:20:03 | 显示全部楼层
本帖最后由 学习stm32f4 于 2018-10-22 15:59 编辑

第十三章

第217页
217.png

217-2.png
printf("%d\n",sizeof("abc"));
返回4


第218页
218.png

218-2.png

第219页
219.png

第221页
221.png

221-2.png

221-3.png


221-4.png

221-5.png

第225页
225.png

第226页
226.png
char str[10]={'\0'};
strcpy(str,"abc");
printf("%d\n",strlen(str));
printf("%d\n",sizeof(str));
output:3 10

226-2.png

226-3.png





第232页
232.jpg

232-2.jpg

232-3.jpg

232-4.jpg

232-5.jpg

or:
    char *test[]={"abc","def","ghijkl"};
    char **p=test;
    printf("%s\n",*p);
    printf("%c\n",(*p)[2]);
output:
    abc
    c

回复 支持 反对

使用道具 举报

94

主题

370

帖子

0

精华

高级会员

Rank: 4

积分
865
金钱
865
注册时间
2016-8-25
在线时间
485 小时
 楼主| 发表于 2018-10-23 16:35:05 | 显示全部楼层
本帖最后由 学习stm32f4 于 2018-10-23 21:28 编辑

第十四章

245
245.jpg

249
249.jpg


249-2.jpg

249-3.jpg
例子:
[mw_shl_code=c,true]#include "stdio.h"
#define GENERIC_MAX(type)       \
type type##_max(type x,type y)  \
{                               \
    return x>y?x:y;             \
}
int main(void)
{
    float f1=2.1,f2=4.2,f;
    GENERIC_MAX(float);
    f=float_max(f1,f2);
    printf("%f\n",f);
    int i1=3,i2=4,i;
    GENERIC_MAX(int);
    i=int_max(i1,i2);
    printf("%d\n",i);
    return 0;
}[/mw_shl_code]

250
250.jpg

251
251.jpg

251-2.jpg

252
252.jpg

252-2.jpg

253
253.jpg

253-2.jpg

254
254.jpg

254-2.jpg

254-3.jpg

255
255.jpg

256
256.jpg

256-2.jpg

256-3.jpg

257
257.jpg

258
258.jpg

258-2.jpg
例子:
[mw_shl_code=c,true]#include "stdio.h"
#define N
int main(void)
{
    #ifdef N
    #error N defined
    #endif // N
    return 0;
}[/mw_shl_code]

编译时,出现错误提示:
258-3.jpg
若将#define N改成#define N1,则不会报错:
[mw_shl_code=c,true]#include "stdio.h"
#define N1
int main(void)
{
    #ifdef N
    #error N defined
    #endif // N
    return 0;
}[/mw_shl_code]


259
#line的用法:
C语言中的__LINE__用以指示本行语句在源文件中的位置信息,举例如下:
259.jpg
该程序在linuxgcc编译,在windowsVS2013下编译都可以通过,执行结果都为:
7
8
9
还可以通过语句#line来重新设定__LINE__的值,举例如下:
259-2.jpg
编译执行后输出结果为:
202
203
204

#line 用法分析
#line用于强制指定新的行号和编译文件名,并对源程序的代码重新编号
用法: #line number filename
注:filename可省略,filename为字符串
#line编译指示字的本质是重定义 _ _ LINE _ _ _ _ FILE _ _
#line number filename语句的下一行开始,行号改为number的值。
举例说明:
259-3.jpg
输出为行号=22,文件名为 Hello.c

259-4.jpg

259-5.jpg

260
#pragma的用法:
我们今天来介绍下 C 语言中的 #pragma#pragma 用于指示编译器完成一些特定的动作。#pragma 所定义的很多指示字是编译器特有的,在不同的编译器间是不可移植的。
        预处理期将忽略它不认识的 file:////tmp/wps-wgt/ksohtml/wpscmNkkr.png#pragma 指令,不同的编译器可能以不同的方式解释同一条 #pragma 指令。一般用法:#pragma parameter。 注意:不同的 parameter 参数语法和意义各不相同!
        #pragma message1.message 参数在大多数的编译器中都有相似的实现;2.message 参数在编译时输出消息到编译输出窗口中;3.message 用于条件编译中可提示代码的版本信息。它与 #error #warning 不同,#pragma message 仅仅代表一条编译消息,不代表程序错误。
        下来我们来分析个示例代码,代码如下
260.jpg
这段代码是想利用 #pragma message 定义一条输出信息,我们来看看在 gcc 编译器中输出什么
260-2.jpg
若在程序中定义了ANDROID20,例如:
260-3.jpg
则编译时会出现信息:
260-4.jpg
运行程序后,输出:
260-5.jpg
下来我们再讲讲 #pragma once,它是用于保证头文件只被编译一次。那么问题来了,我们之前讲讲 #ifndef xxx_h_     #define xxx_h_     #endif 这种用法。它们两个有什么区别呢?因为后一种的实现是基于宏参数实现的,所以它每次包含到头文件时便会进去检查,所以效率不高。但是因为是宏参数,所以这是 C 语言支持的,在每个编译器中都会识别。#pragma once  是编译器相关的,它不一定被支持。但是因为编译器一看见它就不去包含了,所以它的效率及其高,因此两种方式各有利弊。我们下来做个试验分析下
260-6.jpg

260-7.jpg

编译后,不报错。
若将global.h中的#pragma once注释掉,则报错:
260-8.jpg
那么下来我们再来看看 C 语言中的内存对齐,什么是内存对齐呢?不同类型的数据在内存中按照一定规则排列,但是不一定是按照顺序的一个接一个的排列。那么为什么需要内存对齐呢?原因有这么几点:1CPU 对内存的读取不是连续的,而是分成块读取的,块的大小只能是124816 ... 字节;2、当读取操作的数据未对齐,则需要两次总线周期来访问内存,因此性能会大打折扣;3、某些硬件平台只能从规定的相对地址处读取特定类型的数据,否则会产生异常。#pragma pack 用于指定内存对齐方式。
下面我们来看个示例代码,代码如下
260-9.jpg
我们看到两个结构体中的成员变量都一样,但是位置不同。那么问题来了,它们所占的内存大小相同吗?我们来看看编译结果
260-10.jpg
很明显结果不一样,那么为什么呢?这就是内存对齐了,在计算机内部,默认的是4字节对齐,因为这样效率最高。我们可以指定它们都是1字节对齐,这样结果就一样了。#pragma pack 能够改变编译器的默认对齐方式,下面给个示例
260-11.jpg
分别在两个结构的前后都这样设置按照 1 字节对齐的方式,我们再来看看结果如何
260-12.jpg
这下它们占的内存大小就一样了。之前的那种内存分布如下图所示
260-13.jpg
那么 struct 占用的内存大小是怎样计算的呢?第一个成员起始于 0 偏移处,每个成员按其类型大小和 pack 参数中较小的一个进行对齐;偏移地址必须能被对齐参数整除,结构体成员的大小取其内部长度最大的数据成员作为其大小;结构体总长度必须为所有对齐参数的整数倍。编译器在默认情况下按照 4 字节对齐。

对于左边的图,由于默认是4字节对齐,再根据每个成员按其类型大小和 pack 参数中较小的一个进行对齐,偏移地址必须能被对齐参数整除,故s是从字节地址2开始的,若s从字节地址1开始,则不满足偏移地址必须能被对齐参数整除这一条件。类似的,i从字节地址8开始存储。

下来我们再做个实验,按照8字节对齐试试,代码如下
260-14.jpg
按照我们的分析,上面应该分别打印出 8 24。我们来看看 gcc 编译器的结果
260-15.jpg
我们看到打印出的是 8 20,那么我们是不是分析出错了?原来在 gcc 编译器中不支持 8 字节对齐的方式,因此它是按照 4 字节对齐方式进行打印的。那么最后一个 double 的起始距离就是 12 了,因此结果就是 20

通过对 #pragma 的学习,总结如下:1#pragma 用于指示编译器完成一些特定的动作;2、它所定义的很多指示字是编译器特有的;3#pragma message 用于 自定义编译消息、#pragma once 用于保证头文件只被编译一次、#pragma pack 用于指示内存对齐方式。

_pragma的用法:
260-16.jpg

260-17.jpg

261
261.jpg

261-2.jpg

261-3.jpg

262
262.jpg

262-2.jpg

262-3.jpg

263
263.jpg
回复 支持 反对

使用道具 举报

94

主题

370

帖子

0

精华

高级会员

Rank: 4

积分
865
金钱
865
注册时间
2016-8-25
在线时间
485 小时
 楼主| 发表于 2018-10-24 09:45:00 | 显示全部楼层
第十五章

267
267.jpg

268
268.jpg

270
270.jpg

271
271.jpg

272
272.jpg
又如:
272-2.jpg

272-3.jpg

283
283.jpg

283-2.jpg

回复 支持 反对

使用道具 举报

94

主题

370

帖子

0

精华

高级会员

Rank: 4

积分
865
金钱
865
注册时间
2016-8-25
在线时间
485 小时
 楼主| 发表于 2018-10-24 18:37:11 | 显示全部楼层
本帖最后由 学习stm32f4 于 2018-10-24 21:32 编辑

第十六章
0.jpg

287
287.jpg

287-2.jpg

288
288.jpg
例如:
#include <stdio.h>

int main()
{
    struct
    {
        int a[5];
    }test1={{1,4,2,0,3}},
     test2;
    test2=test1;
    int i;
    for(i=0;i<5;i++)
        printf("%d\n",test1.a);
    for(i=0;i<5;i++)
        printf("%d\n",test2.a);
    return 0;
}
288-2.jpg

288-3.jpg

289
289.jpg

289-2.jpg

289-3.jpg

290
290.jpg

290-2.jpg

291
291.jpg

291-2.jpg

292
292.jpg

292-2.jpg

292-3.jpg

293
293.jpg

299
299.jpg

299-2.jpg

300
300.jpg

301
301.jpg

302
302.jpg

302-2.jpg

303
303.jpg

303-2.jpg

303-3.jpg

304
304.jpg

304-2.jpg

304-3.jpg

304-4.jpg

305
305.jpg

306
306.jpg

307
307.jpg

回复 支持 反对

使用道具 举报

0

主题

7

帖子

0

精华

新手入门

积分
14
金钱
14
注册时间
2019-3-23
在线时间
3 小时
发表于 2019-4-10 18:44:48 | 显示全部楼层
谢谢分享,下载收藏
回复 支持 反对

使用道具 举报

0

主题

49

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
334
金钱
334
注册时间
2018-9-12
在线时间
50 小时
发表于 2019-5-13 01:55:51 | 显示全部楼层
有习题答案吗?
回复 支持 反对

使用道具 举报

1

主题

15

帖子

0

精华

初级会员

Rank: 2

积分
69
金钱
69
注册时间
2018-4-14
在线时间
18 小时
发表于 2019-5-27 21:06:58 | 显示全部楼层
是本好书
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-5-29 04:08

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表