c primer plus第14章总结:结构和其他数据形式

结构声明:

struct book{
     char title(MAX);
     char author(MAX);
     float value;
};

定义结构变量:

声明:struct book library;
初始化:struct book library = {
                                   "abd",// 用逗号隔开
                                    "asd",
                                    1.95
                            };

访问成员:
gets(library.title); // 不需要带结构名
scanf(“%f”, &library.value); // library.value为float类型
// gets()读取换行符,但舍弃,不会对后续的输入造成影响;优先选择;

结构数组:

struct book library[NAXBOOK]gets(library[count].title);
gets(library[count].title[0]);
printf("%s", library[index].title);

嵌套结构:

struct name{
char first[LEN];
char last[LEN];
};
struct guy{
struct name handle;// 声明一个name变量,嵌套;
char favfood[LEN];
char jio[LEN];
float income
};
struct guy fellow;
printf("%s", fellow.handle.first);
printf("%s", fellow.job);

指向结构的指针:

struct guy fellow[2];
struct guy* him;
him = &fellow[0];// 同一结构类型,不需要带结构名称;
printf("%s", him -> handle.first);
printf("%s", him -> job);
// 指针him->与fellow.的作用等效;

补充

引用:http://www.cnblogs.com/vace/archive/2011/04/14/2015754.html
C的结构体和C++结构体的区别
(1)C的结构体内不允许有函数存在,C++允许有内部成员函数,且允许该函数是虚函数。所以C的结构体是没有构造函数、析构函数、和this指针的。
(2)C的结构体对内部成员变量的访问权限只能是public,而C++允许public,protected,private三种。
(3)C语言的结构体是不可以继承的,C++的结构体是可以从其他的结构体或者类继承过来的。

以上都是表面的区别,实际区别就是面向过程和面向对象编程思路的区别:
C的结构体只是把数据变量给包裹起来了,并不涉及算法。而C++是把数据变量及对这些数据变量的相关算法给封装起来,并且给对这些数据和类不同的访问权限。C语言中是没有类的概念的,但是C语言可以通过结构体内创建函数指针实现面向对象思想。

C++的结构体和C++类的区别
(1)C++结构体内部成员变量及成员函数默认的访问级别是public,而c++类的内部成员变量及成员函数的默认访问级别是private。
(2)C++结构体的继承默认是public,而c++类的继承默认是private。

函数指针:

void  (*p)(char* ); // pf 是一个指向函数的指针;
void *pf (char* );  // pf 是返回一个指针的函数;

可以把适当类型的函数地址赋值给函数指针,函数名能表示函数地址;

void ToUpper(char* );
void ToLower(char* );
void (*pf) (char * );  // 声明一个函数指针,可以用来指向ToUpper、ToLower;
pf = ToLower;          // 赋值;

函数指针用法:

void show (void (* fp )(char *), char * str)
{
     (* fp)( str); // 把函数传给str
     puts(str);    // 显示调用该函数的输出结果
}

补充

引用:
http://blog.csdn.net/wujiangguizhen/article/details/17153495
http://blog.csdn.net/newtonnl/article/details/7724649
http://www.cnblogs.com/processakai/archive/2011/06/24/2089345.html

函数指针的好处:
(1)提供调用的灵活性。设计好了一个函数框架,但是设计初期并不知道自己的函数会被如何使用。比如C的”stdlib”中声明的qsort函数,用来对数值进行排序。显然,顺序还是降序,元素谁大谁小这些问题,库程序员在编写qsort的时候不可能决定。这些问题是要在用户调用这个函数的时候才能够决定。那边qsort如何保证通用性和灵活性呢?采用的办法是让函数的使用者来制定排序规则。于是调用者应该自己设计comparator函数,传给qsort函数。这就在程序设计初期保证了灵活性。尽管使用函数指针使得程序有些难懂,但是这样的牺牲还是值得的。
(2)回调函数。Windows编程中的事件handle函数,即回调函数,在事件队列都是一个函数指针来保存的:
typedef void (*event_handler) (unsigned int para1, unsigned int para2);
struct event {
unsigned int ev_id;
event_handler handler;
};

struct event event_queue[MAX_EVENT_SIZE];
程序可以通过扫描这个事件队列来获取每个事件对应的处理函数,然后调用它,即为回调函数。

课后习题

//第11题 transform()接受是个参数,定义一个指针函数,用于接受用户选择的函数;

#include "stdafx.h"
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#define LEN 100

char showmenu(void);
void eatline(void);
double add(double x);     // 自定义+1函数
double square(double x);  // 自定义求平方函数
void transform(double source[], double target[], int n, double (*pfun)(double));

int main(void)
{


    double (*pfun)(double) = NULL;      // 指向一个函数,该函数接受source[]的一个double元素;
                                        // 返回一个double值,预赋给target[]; 
    double source[LEN] = {0};
    double  target[LEN] = {0};
    int n = LEN;
    char choice;    

    srand((unsigned)time(0));
    for(int i = 0; i < n; i++)
    {
        source[i] = rand()/(double)(RAND_MAX/20);
        //(rand() % 200) / 10.; 
        // rand取得0~INT_MAX随机值,%200取得0~200的整数随机值,除以10得到0~20之间保留一位有效数字的double
        printf("%.2lf ", source[i]);

        if ((i + 1) % 10 == 0)
            printf("\n");
    }
    printf("\n");

    while ((choice = showmenu()) != 'n')
    {
        switch (choice)                 // 设置指针
        {
        case 'a' : pfun = add; break;
        case 's' : pfun = square; break;
        case 'c' : pfun = ceil; break;  // math.h自带函数
        case 'f' : pfun = fabs; break;  // math.h自带函数
        default:
            break;
        }
        transform(source, target, n, pfun);
    }

    puts("Bye!");
    return 0;
}

char showmenu(void)
{
    char ans;
    puts("Enter menu choice:");
    puts("a) add       c) ceil");
    puts("s) square    f) fabs");
    puts("q) quit");
    ans = getchar();              
    ans = tolower(ans);                // 转换用户输入,为小字母   
    eatline();          
    while (strchr("acsfq", ans) == NULL)
    {
        puts("Please enter a \"a\", \"c\", \"s\", \"f\", or \"q\":");
        ans = tolower(getchar());
        eatline();
    }

    return ans;
}

void eatline(void)
{
    while (getchar() != '\n')
        continue;
}

void transform(double source[], double target[], int n, double (*pfun)(double))
{
    for (int i = 0; i < n; i++)
    {
        target[i] = pfun(source[i]);
    }

    printf("source\ttarget\t\n");
    for(int i = 0; i < n; i++)
    {
        printf("%.1lf\t%.2lf\n",source[i], target[i]);
    }
}

double add(double x)
{
    return x + 1;
}

double square(double x)
{
    return x * x;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值