c学习笔记 结构和其他数据形式 210210326

枚举类型(enumerated type)

可以用enum可以创建一个枚举类型(enum常量是int类型, 只要能使用int型的地方就可以使用枚举类型)
其语法结构与结构的语法相同

enum spectrum {red, orange, yellow, green, blue, violet};
enum spectrum color;

color 的值可能为red、orange、yellow等, 这些符号称之为枚举符(enumerator)

int c;
color = blue;
 if (color == yellow)
 	...;
 for (color = red; color <= violet; color++)
 ...;

枚举变量可以是任意的整数类型
tips:c++不允许枚举变量使用++运算符, 除非将其声明为int类型。

enum常量

printf("red = %d, orange = %d\n", red, orange);

其输出:

red = 0, orange = 1

默认值

默认情况下, 枚举列表中常量都被赋予0、1、2等

enum kids (nippy, slats, skippy, nina, liz);

nippy == 0, slats == 1, skippy == 2,…

赋值

enum levels (low =  100, medium = 500, high = 2000);
enum feline {cat, lynx = 10, puma, tiger};

cat为0, lynx, puma, tiger分别为10、11、12。

用法

#include <stdio.h>
#include <string.h>
#include <stdbool.h>  //c99特性
enum spectrum {red, orange, yellow, green, blue, violet };
const char* colors[] = { "red", "orange", "yellow", "green", "blue", "violet" };
#define LEN 30
int main(void)
{
   char choice[LEN];
   enum spectrum color;
   bool color_is_found = false;
   puts("Enter a color (empty line to quit):");
   while (s_gets(choice, LEN) != NULL && choice[0] != '\0')
   {
   	for (color = red; color <= violet; color++)
   	{
   		if (strcmp(choice, colors[color]) == 0)
   		{
   			color_is_found = true;
   			break;
   		}
   	}
   	if (color_is_found)
   		switch (color)
   		{
   		case red: puts("Roses are red.");
   			break;
   		case orange: puts("Poppies are orange.");
   			break;
   		case yellow: puts("Sunflowers are yellow.");
   			break;
   		case green: puts("Grass is green.");
   			break;
   		case blue: puts("Bluebells are blue.");
   			break;
   		case violet: puts("Violets are violet.");
   			break;
   		}
   	else
   		printf("I don not know about the color %s.\n", choice);
   	color_is_found = false;
   	puts("Next color, please (empty line to quit):");
   }
   puts("Good bye!");
   return 0;
}

该程序使用默认值方法使之成为字符串的索引。

共享名称空间

c中在相同作用域的变量和标记的名称可以相同, 不会引起冲突

struct rect {double x; double y;};
int rect;

但是c++不允许如此, 因为其把标记名与变量名放在相同的名称空间。

typedef

其与#define 类似
但是

  1. typedef创建的符号名只受限于类型, 不能用于值
  2. typedef由编译器解释, 而非预处理器
  3. 比#define更灵活

假设要用BYTE表示一字节的数组, 则

typedef unsigned char BYTE;
BYTE x, y[10], *z;

作用域取决于typedef定义所在位置。

size_t, time_t类型都是由typedef定义产生的

time_t time(time_t *);

time_t在一些系统可能是unsigned long 在一些系统也可能是unsigned long long.

typedef char * STRING;

编译器会把STRING解释成一个类型的标识符, 该类型是指向char的指针
其也可作用于结构

typedef struct complex{
	float real;
	float imag;
} COMPLEX;

即可使用COMPLEX类型代替complex结构表示复数
使用typedef命名一个结构时, 可省略该结构的标签:

typedef struct {double x; double y;}rect;

使用方法:

rect r1 = {3.0, 6.0};
rect r2;
r2 = r1;

typedef可用于给复杂的类型命名:

typedef char (*FRPTC ()) [5];

FRPTC声明为一个函数类型, 该函数返回一个内含5个char类型元素的数组的指针。

其他复杂的声明

  1. 数组名后面的[]和函数名后面的()有相同优先级, 他们比解引用运算符(*)的优先级高
  2. [], ()都是从左到右结合
int (* uof[3])[4];    // 内含3个指针元素的数组,每个指针指向一个内含4个int类型元素的数组
char (*frump)(int);  // 指向函数的指针, 该函数返回类型为char
char* flump[3](int);    // 内含3个指针的数组, 每个指针指向返回类型为char的函数

可使用typedef建立一系列相关类型

typedef int arr5[5];
typedef arr5 *p_arr5;
typedef p_arr5 arrp10[10];
arr5 togs;   //togs是内含5个int型的数组
p_arr5 p2;     //  p2 是一个指向数组的指针, 该数组内含5个int型值
arrp10 ap;      // ap为内含10个指针的数组, 每个指针都指向一个含5个int型值的数组

函数和指针

指向函数的指针中储存着函数代码起始处的地址。
声明函数指针时必须声明指针指向的函数类型, 为指明函数类型, 要指明函数签名, 即函数的返回类型与形参类型

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

定义方法:

void ToUpper(char *);
void ToLower(char *);
int round(double);
void (*pf)(char *);
pf = ToUpper;
pf = ToLower;
pf = round;
pf = ToLower();      //无效, ToLower()不是地址

访问方法:

void ToUpper(char *);
void ToLower(char *);
void (*pf) (char *);
char mis[] = "Nina Metier";
pf = ToUpper;
(*pf)(mis);      //语法1
pf = ToLower;
pf(mis);      //语法2
void show(void (* fp)(char *), char * str);

其声明了两个形参, fp是一个函数指针, str是一个数据指针; fp指向的函数接受char * 类型参数, 返回类型为void。
可以这样调用函数:

show(ToLower, mis);   // show使用ToLower()函数
show(pf, mis);             //show使用pf指向的函数

show()使用方法;

void show(void (* fp)(char *), char * str)
{
	(*fp)(str);      //所选函数作用于str
	puts(str);     //显示结果
}

带返回值的函数作为参数传递给其他函数有两种方法;

function1(sqrt);          //传递sqrt()函数地址, 在function1中使用该函数
function2(sqrt(4.0));  //传递sqrt()函数返回值
#include <stdio.h>
#include <string.h>
#include <ctype.h>

#define LEN 81
char showmenu(void);
void eatline(void);
void show(void(*fp)(char*), char* str);
void ToUpper(char*);
void ToLower(char*);
void Transpose(char*);
void Dummy(char*);

int main(void)
{
	char line[LEN];
	char copy[LEN];
	char choice;
	void (*pfun)(char*);   // 声明函数指针

	puts("Enter a string (empty line to quit):");
	while (s_gets(line, LEN) != NULL && line[0] != '\0')
	{
		while ((choice = showmenu()) != 'n')
		{
			switch (choice)        // 设置指针
			{
			case 'u': pfun = ToUpper; break;
			case 'l': pfun = ToLower; break;
			case 't': pfun = Transpose; break;
			case 'o': pfun = Dummy; break;
			}
			strcpy(copy, line);   // 为show()函数拷贝一份
			show(pfun, copy);
		}
		puts("Enter a string (empty to quit):");
	}
	puts("bye!");
	return 0;
}

char showmenu(void)
{
	char ans;
	puts("Enter menu choice:");
	puts("u) uppercase		1) lowercase");
	puts("t) transposed case  o) original case");
	puts("n) next string");
	ans = getchar();
	ans = tolower(ans);
	eatline();
	while (strchr("ulton", ans) == NULL)
	{
		puts("Please enter a u, l, t, o, or n:");
		ans = tolower(ans);
		eatline();
	}
	return ans;
}

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

void ToUpper(char* str)
{
	while (*str)
	{
		*str = toupper(*str);
		str++;
	}
}

void ToLower(char* str)
{
	while (*str)
	{
		*str = tolower(*str);
		str++;
	}
}

void Transpose(char* str)
{
	while (*str)
	{
		if (islower(*str))
			*str = toupper(*str);
		else if (isupper(*str))
			*str = tolower(*str);
		str++;
	}
}

void dummy(char* str)
{
	//不改变字符串
}

void show(void (*fp)(char*), char* str)
{
	(*fp)(str);
	puts(str);
}

程序通过将不同的函数赋予函数指针, 但是也可以把这四个函数中任一函数名作为参数, 如

show(Transpose, copy);

可以使用typeddef:

typedef void (* V_FP_CHARP)(char *);
void show (V_FP_CHARP fp, char *);
V_FP_CHARP pfun;

可以声明并初始化一个函数指针数组:

v_FP_CHARP arpf[4] = {ToUpper, ToLower, Transpose, Dummy};

把showmenu()返回值改为int, 若用户输入u, 则返回0, 若输入l, 则返回1, 以此类推

index = showmenu();
while(index >= 0 && index <= 3)
{
	strcpy(cpoy, line);
	show (arpf[index], copy);
	index = showmenu();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值