C学习笔记(九)结构和其他数据形式

</pre><p><span style="font-size: 32px;">一、结构</span></p><p></p><pre name="code" class="plain">#include <stdio.h>
#define MAXTITL  41      // maximum length of title + 1
#define MAXAUTL  31      // maximum length of author's name + 1

struct book {            // structure template: tag is book
    char title[MAXTITL];
    char author[MAXAUTL];
    float value;
};                       // end of structure template

int main(void)
{
    struct book library; // declare library as a book variable

    printf("Please enter the book title.\n");
    gets(library.title); // access to the title portion

    printf("Now enter the author.\n");
    gets(library.author);

    printf("Now enter the value.\n");
    scanf("%f", &library.value);

    printf("%s by %s: $%.2f\n",library.title,
          library.author, library.value);
    printf("%s: \"%s\" ($%.2f)\n", library.author,
          library.title, library.value);
    printf("Done.\n");

    return 0;
}

1、声明结构

struct book { 
    char title[MAXTITL];
    char author[MAXAUTL];
    float value;
};
或者

struct book { 
    char title[MAXTITL];
    char author[MAXAUTL];
    float value;
} library

或者

struct { 
    char title[MAXTITL];
    char author[MAXAUTL];
    float value;
} library

 

2、初始化结构

struct book library={ "C Primer Plus ","Stephen Prata",60.0};

指定初始化项目


</pre><pre name="code" class="plain">struct book library={ 
     .title="C Primer Plus ",
     .author="Stephen Prata",
     .value=60.0
};

</pre><p></p><pre>

3、访问结构成员

library.value


4、结构数组

#include <stdio.h>
#define MAXTITL   40
#define MAXAUTL   40
#define MAXBKS   100             

struct book {                   
    char title[MAXTITL];
    char author[MAXAUTL];
    float value;
};

int main(void)
{
    struct book library[MAXBKS]; 
    int count = 0;
    int index;

     printf("Press [enter] at the start of a line to stop.\n");
	 printf("Please enter the book title.\n");
   
    while (count < MAXBKS && gets(library[count].title) != NULL
                          && library[count].title[0] != '\0')
    {
        printf("Now enter the author.\n");
        gets(library[count].author);
        printf("Now enter the value.\n");
        scanf("%f", &library[count++].value);
        while (getchar() != '\n')
            continue;         
        if (count < MAXBKS)
        printf("Enter the next title.\n");
    }
    
    if (count > 0)
    {
        printf("Here is the list of your books:\n");
        for (index = 0; index < count; index++)
        printf("%s by %s: $%.2f\n", library[index].title,
            library[index].author, library[index].value);
    }
    else
    	printf("No books? Too bad.\n");
    
    return 0;
}

5、指向结构的指针

#include <stdio.h>
#define LEN  20


struct names {
    char first[LEN];
    char last[LEN];
};

struct guy {
	struct names handle;
	char favfood[LEN];
	char job[LEN];
	float income;
};

int main(void)
{

	struct guy fellow[2] = {
			{{"Ewen","Villard"},
			  "grilled salmon",
			  "personnal coach",
			  58112.00
			}
			,{{"Rodeny","Swillbelly"}
			,"tripe",
			"tabloid editor",
			232400.00}
	};
	struct guy * him;
	printf("address #1:%p;#2:%p\n",&fellow[0],&fellow[1]);
	him = &fellow[0];

	printf("*pointer #1:%p #2:%p\n",him,him+1);
	printf("him->income is $%.2f ;(*him).income is ;$%.2f\n",him->income,(*him).income);

	him++;
	printf("him->favfood is %s ;him->handle.last is %s\n",him->favfood,him->handle.last);
    return 0;
}
-------------------------------------------------------------------------------------------------------

address #1:0028FE90;#2:0028FEE4
*pointer #1:0028FE90 #2:0028FEE4
him->income is $58112.00 ;(*him).income is ;$58112.00
him->favfood is tripe ;him->handle.last is Swillbelly


讨论:在结构中使用字符数组还是字符指针?

struct names {
    char first[LEN];
    char last[LEN];
};
可以改成这样吗?

struct pnames {
    char * first;
    char * last;
};
确实可以,但是会遇到麻烦。
struct names veep  ={ "Ewen","Villard"} ;

struct pnames treas={ "Brad","Fallingjaw"} ;

对于veep  来说 字符串存储在LEN长度的数组里。

对于treas来说,字符串存到哪去了?

pnames 结构不会为字符串分配任何存储空间。只适合用于在另外的地方已经为字符串分配了空间。

如果需要一个结构来存储字符串,建议使用字符数组成员,或者用一个已经分配空的字符串的地址赋给字符指针。


6、结构、指针和malloc( )

struct namect {
    char * first;
    char * last;
    int letters;

};

void getinfo(struct namect * );
void makeinfo(struct namect * );
void showinfo(const struct namect * );
void cleanup(struct namect * );

int main(void)
{

	struct namect person;
	getinfo(&person);
	makeinfo(&person);
	showinfo(&person);
	cleanup(&person);
    return 0;
}

void getinfo(struct namect * pst)
{
	char temp [81];

	printf("Please enter your first name.\n");
	gets(temp);
	pst->first = (char*)malloc(strlen(temp)+1);
	strcpy(pst->first,temp);

	printf("Please enter your last name.\n");
	gets(temp);
	pst->last = (char*)malloc(strlen(temp)+1);
	strcpy(pst->last,temp);

}

void makeinfo(struct namect * pst)
{

	pst->letters  = strlen(pst->first)+strlen(pst->last);
}
void showinfo(const struct namect * pst)
{

	printf("%s %s ,your name contains %d letters .\n",pst->first,pst->last,pst->letters);

}
void cleanup(struct namect * pst)
{

	free(pst->first);
	free(pst->last);
}


7、复合文字和结构(C99)

可以使用复合文字创建一个被用来作为函数参数或赋值给另一个结构的结构。语法是把类型名写在圆括号中,后面跟一个花括号括起来的初始化项目列表。

(struct book) {"The Idiot","pyodor Dos",6.99}



二、联合

 当多个数据需要共享内存或者多个数据每次只取其一时,可以利用联合体(union)。

     1)联合体是一个结构;

     2)它的所有成员相对于基地址的偏移量都为0;

     3)此结构空间要大到足够容纳最"宽"的成员;

     4)其对齐方式要适合其中所有的成员;

由于联合体中的所有成员是共享一段内存的,因此每个成员的存放首地址相对于于联合体变量的基地址的偏移量为0,即所有成员的首地址都是一样的。为了使得所有成员能够共享一段内存,因此该空间必须足够容纳这些成员中最宽的成员。对于这句“对齐方式要适合其中所有的成员”是指其必须符合所有成员的自身对齐方式。

下面举例说明:

如联合体

union U
{
    char s[9];
    int n;
    double d;
};
s占9字节,n占4字节,d占8字节,因此其至少需9字节的空间。然而其实际大小并不是9,用运算符sizeof测试其大小为16.这是因为这里存在字节对齐的问题,9既不能被4整除,也不能被8整除。因此补充字节到16,这样就符合所有成员的自身对齐了。

从这里可以看出联合体所占的空间不仅取决于最宽成员,还跟所有成员有关系,

即其大小必须满足两个条件:

1)大小足够容纳最宽的成员;

2)大小能被其包含的所有基本数据类型的大小所整除。

union U
{
    char s[9];
    int n;
    double d;
};
int main(void)
{

	union U text;
	union U * textP;
	printf("%d\n",sizeof(text));
	printf("%#p\n",&text);
	printf("%#p\n",&text.d);
	printf("%#p\n",text.s);
	printf("%#p\n",&text.n);

	printf("%#p\n",textP);
	printf("%#p\n",&textP->d);
	printf("%#p\n",&textP->n);
	printf("%#p\n",&textP->s);

	text.d=25.0;
	text.n = 12;
//	text.s = "union";
//	text.s[0] = 'u';
//	text.s[1] = 'n';
//	text.s[2] = 'i';
//	text.s[3] = 'o';
//	text.s[4] = 'n';
//	text.s[5] = '\0';

	printf("%d\n",text.d);
	printf("%d\n",text.n);
//	printf("%s\n",text.s);
    return 0;
}<span style="color:#990000;">
</span>
-----------------------------------------------------

16
0X0028FF30
0X0028FF30
0X0028FF30
0X0028FF30
0X77201162
0X77201162
0X77201162
0X77201162
12
12



三、枚举类型

<span style="font-size:18px;">int main(void)
{
        //默认起始为0,我这里设置为1。以后递增。可以为负。
	enum dayOfWeek {Mon, Tue=0, Wed, Thu, Fri, Sat, Sun};
	enum dayOfWeek dayNum;
	int i;
	dayNum = Fri;
	printf("Mon is %d dayOfWeek\n  ", Mon);
	printf("Wed is %d dayOfWeek\n  ", Wed);
	printf("Fri is %d dayOfWeek\n  ", dayNum);
	i = 0;
	i = dayNum + 1;
	printf("i is %d \n ", i);
    return 0;
}</span>


四、typeof简介

和#define相似,但是它们具有3个不同之处。

1)typeof给出的符号名称仅限于对类型,而不是对值。

2)typeof的解释由编译器,而不是预处理器执行。







  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值