?一.结构学习
1.枚举 ? ?枚举是一种用户定义的数据类型,它用关键字enum以如下语法来声明: enum 枚举类型名字{名字0....名字n} ; ? ? 枚举类型 名字通常并不真的使用,要用的是在大括号里的名字,因为它们就是就是常量符号,它们的类型是int,值则依次从0到n。如:enum colors { red, yellow, green }就创建了三个常量, red的值是0,yellow是1, 而green是2。 ? ? 当需要一些可以排列起来的常量值时,定义枚举的意义就是给了这些常量值名字。 ? ? ? 声明枚举量的时候也可以指定值 ? ?例如:enum COLOR { RED=1, YELLOW, GREEN = 5};?
#include<stdio.h>
enum color { red, yellow, green };
void f(enum color c);
int main(void) {
enum color t = red;
scanf("%d", &t);
f(t);
return 0;
}
void f(enum color c) {
printf("%d", c);
}
注:自动计数的枚举
#include<stdio.h>
enum COLOR { red, yellow, green,NumCOLORS };
int main(int argc ,char* argv[]) {
int color = -1;
char* ColorNames[NumCOLORS] = {
"red","yelloe","green",
};
char* colorName = NULL;
printf("输入喜欢颜色的代码");
scanf("%d", &color);
if (color >= 0 && color < NumCOLORS) {
colorName = ColorNames[color];
}
else {
colorName = "umknown";
}
printf("你喜欢的颜色是%s\n", colorName);
return 0;
}
方便建立数组或遍历枚举量
2.结构
数组是一组具有相同类型的数据的集合。但在实际的编程过程中,我们往往还需要一组类型不同的数据,例如对于学生信息登记表,姓名为字符串,学号为整数,年龄为整数,所在的学习小组为字符,成绩为小数,因为数据类型不同,显然不能用一个数组来存放,结构便可以解决这个事情。
struct 结构体名{
结构体所包含的变量或数组
};
结构体是一种集合,它里面包含了多个变量或数组,它们的类型可以相同,也可以不同,每个这样的变量或数组都称为结构体的成员(Member)。
int、float、char 等是由C语言本身提供的数据类型,不能再进行分拆,我们称之为基本数据类型;而结构体可以包含多个基本类型的数据,也可以包含其他的结构体,我们将它称为复杂数据类型或构造数据类型。
结构体变量
struct stu{
char *name; //姓名
int num; //学号
int age; //年龄
char group; //所在学习小组
float score; //成绩
};
?其中stu是结构体名,它包含了 5 个成员,分别是 name、num、age、group、score。结构体成员的定义方式与变量和数组的定义方式相同,只是不能初始化。 ? (1)? 结构和数组有点像
? (2)数组用运算符和下标访问其成员a[0]=l0
(3)结构用 “? . ”运算符和名字访问其成员
today.day? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??pl.x
student.firstName? ? ? ? ? ? ? ? ? ?pl.y
#include<stdio.h>
struct date {
int year;
int mouth;
int day;
};
int main(void) {
struct date today;
today = (struct date){ 2021,11,21 };
struct date day;
day = today;
day.year = 2018;
printf("Today is %d-%d-%d.\n", today.year, today.mouth, today.day);
printf("The day is %d-%d-%d.\n", day.year, day.mouth, day.day);
return 0;
}
%i:有符号十进制整数(与%d相同)
注意大括号后面的分号; 不能少,这是一条完整的语句。
struct stu stu1, stu2;
定义了两个变量 stu1 和 stu2,它们都是 stu 类型,都由 5 个成员组成。注意关键字不能少struct。
也可以在定义结构体的同时定义结构体变量:
struct stu{
char *name; //姓名
int num; //学号
int age; //年龄
char group; //所在学习小组
float score; //成绩
} stu1, stu2;
结构体的各个成员在内存中是连续存储的,和数组非常类似,例如上面的结构体变量 stu1、stu2 的内存分布如下图所示,共占用 4+4+4+1+4 = 17 个字节。
?以下是一个例子,运行可得Tom的资料。
#include<stdio.h>
int main()
{
struct{ //没有写 stu
char *name; //姓名
int num; //学号
int age; //年龄
char group; //所在学习小组
float score; //成绩
} stu1
;stu1.name="tom";
stu1.num=1;
stu1.age=18;
stu1.group=9;
stu1.score=100;
printf("%s的学号是%d,年龄是%d,在%d组,今年的成绩是%.1f!\n",
stu1.name, stu1.num, stu1.age, stu1.group, stu1.score);
return 0;
}
以下是翁恺老师课上讲的一个例子,但是在编译器里出现了一些问题
#include<stdio.h>
#include<string.h>
#define bool int
struct date {
int year;
int month;
int day;
};
bool isLeap(struct date d)
int numberOfDays(struct date d);
int main(int argc, char const* argv[])
{
struct date today, tomorrow;
printf("Enter today is date (year month day)");
scanf("%d %d %d", &today.year, &today.month, &today.day);
if (today.day != numberOfDays(today)) {
tomorrow.day = today.day + 1;
tomorrow.month = today.month;
tomorrow.year = today.year;
}
else if(today.month==12){
tomorrow.day = 1;
tomorrow.month = 1;
tomorrow.year = today.year + 1;
}
else {
tomorrow.day = 1;
tomorrow.month = today.month;
tomorrow.year = today.year;
}
printf("Tomorrow is date %d-%d-%d.", tomorrow.year, tomorrow.month, tomorrow.day);
return 0;
}
int numberOfDays(struct date d)
{
int days;
const int daysPerMonth[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 };
if (d.month == 2 && isLeep(d)) {
days = 29;
}
else {
days = daysPerMonth[d.month - 1];
}
return days;
}
bool isLeep(struct date d)
{
bool leap = false;
if ((d.year % 4 == 0 && d.year % 100 != 0) || d.year % 400 == 0)
{
leap = true;
}
return leap;
}
?还在解决和学习这些问题中
二.练习题
1.清空数组
#include<stdio.h>
#include<string.h>
int main(int argc, char* argv[])
{
char str[20];
memset(str,00,sizeof(str));//清空数组每一项 ,让他们变成0
//memset(要清空的名字,清空变成什么,清空的长度)
int i;
for(i=0;i<sizeof(str)/sizeof(char);i++)
{
printf("%d ",str[i]);
}
return 0;
}
memset函数的使用,memset(要清空的名字,清空变成什么,清空的长度)
2.复习大小写字符转换
#include<stdio.h>
int main()
{
char a[100];
int i;
gets(a);
// scanf("%s",&a);
//printf("%s\n",a);
// puts(a);
for(i=0;a[i]!='#';i++){
if(a[i]>='a'&&a[i]<='z')
{
a[i]-=32;
}
if(a[i]>='A'&&a[i]<='Z')
{
a[i]+=32;
}
//printf("%s\n",a);
}
for(i=0;a[i]!='#';i++){
printf("%c",a[i]);
}
// printf("%s\n",a);
return 0;
}
检验对ASCII码值的掌握,大小写字符ASCII码值相差32.
3.malloc函数定义数组
#include<stdio.h>
#include<stdlib.h>//malloc函数所在的头文件
int main()
{
int number;
scanf("%d",&number);
//int a[number];
int *a;
// char *p = (char *)malloc(100);
a=(int*)malloc(number*sizeof(int));//(number*4)
int i,j;
for(j=0;j<number;j++)
{
scanf("%d",&a[j]);
}
for(i=0;i<number;i++)
{
printf("%d ",a[i]);
}
free(a);
return 0;
}
malloc()
在堆内存分配了100个字节的内存,返回这块内存的首地址, 把地址强制转换成char *类型后赋给char *类型的指 针变量p; 同时告诉我们这块内存将用来存储char类型的数据。你只能通过指针变量p来操作这块内存, 这块内存 本身没有名字,对它的访问是匿名访问。 但是,不一定每次malloc函数都能成功分配到内存。 既然malloc函数申 请内存存在不成功的可能,那我们在使用指向这块内存的指针时, 必须用if( NULL != p)语句上来验证内存分 配确实成功了。
free()
既然有分配,那就必须有释放,不然的话,有限的内存就会用光, 而没有释放的内存却占用空间,与malloc对应 的就是free函数了。 free函数只有一个参数,就是所要释放的内存块的首地址(指针)。 按上例,则 为:free§.free函数其实它就做了一件事: 斩断指针变量和这块内存的对应关系。 free函数就是把这块内存和p 之间的关系斩断;p本身的值并没有改变或者消失, 即指针变量p本身保存的地址并没有改变,那块被释放的内存 里面保存的值也没有改变。 这就是free函数的功能,一个malloc对应一个free,是一夫一妻制。 在使用free(p) 函数内存释放后,指针变量p本身保存的地址并没有改变, 那我们必须需重新把p的值变为NULL:p = NULL。 如 果没有把该指针置NULL,这个指针就成为了“悬空指针”,这是很危险的,且也是经常出错的地方。
只是看了一下理论,并没有掌握会运用
4.删除字符
实现一个删除字符串中的指定字符的简单函数。其中char *str是传入的字符串,c是待删除的字符。函数delchar的功能是将字符串str中出现的所有c字符删除。
#include<stdio.h>
#define MAXN 20
void delchar1(char* str, char c)//做
{
int i, j;
int t = 0;
for (i = 0; i < MAXN; i++)
{
if (str[i] == c) {
for (j = i; j < (MAXN - i); j++) {
str[j] = str[j + 1];
}
i--;
}
}
}
void delchar2(char* str, char c)//答案
{
int i, j;
int t=0;
for (i = MAXN - 1; i >= 0; i--)
{
if (str[i] == c)
{
for (j = i; j < (MAXN - i); j++) {
str[j] = str[j + 1];
}
t++;//几个重复的
}
}
}
//删除函数的俩个for循环一个后往前遍历一个前往后遍历
int main(int argc, char* argv[])
{
char str[MAXN], c;
scanf("%c\n", &c);
//ReadString(str);
gets(str);
delchar1(str, c);
printf("%s\n", str);
delchar2(str, c);
printf("%s\n", str);
return 0;
}
5.俩点之间距离
其中用户传入的参数为平面上两个点的坐标(x1, y1)和(x2, y2),函数dist应返回两点间的距离。
#include<stdio.h>
#include<math.h>
double dist(double x1, double y1, double x2, double y2)
{
double a, b;
double dist;
a = x1 - x2;
b = y1 - y2;
dist = sqrt(a * a + b * b);
return dist;
}
int main005(int argc, char* argv[])
{
double x1 = 0;
double x2 = 0;
double y1 = 0;
double y2 = 0;
scanf_s("%lf %lf %lf %lf", &x1, &y1, &x2, &y2);
printf("length=%.2f", dist(x1, y1, x2, y2));
return 0;
}
6.ASCII码值排序字符,并删除重复
上周有问题的地方,经过学姐指导,明白了是数组长度的控制不当导致会有乱码,成功写出了
#include<stdio.h>
int main()
{
char s[100];
int i, j, k, cnt = 0;
char t;
memset(s, 0, sizeof(s));//sizeof()计算字节大小
//初始化数组
gets(s);
i = 0;
//计算数组长度
while (s[i] != '\0') {
i++;
cnt++;
}
//输出数组
for (i = 0; i < cnt; i++) {
printf("%c", s[i]);
}
printf("\n");
printf("\n");
//利用冒泡原理,ASCII值排序
for (j = 0; j < cnt; j++)
{
for (i = j + 1; i < cnt; i++)
{
if (s[j] > s[i]) {
t = s[i];
s[i] = s[j];
s[j] = t;
}
}
}
//输出数组
for (i = 0; i < cnt; i++)
{
printf("%c", s[i]);
}
printf("\n");
printf("\n");
//删重复,覆盖前一个
for (j = 0; j < cnt; j++)
{
for (i = j; i < cnt; i++)
{
if (s[j + 1] == s[j])
{
for (k = j; k < cnt; k++)
{
s[k] = s[k + 1];
}
cnt--;
}
}
}
//赋给b数组
int c = 0;
char b[20];
for (i = 0; i < cnt; i++)
{
if (s[i] != s[i + 1])
{
b[c] = s[i];
c++;
}
}
//输出b数组
for (i = 0; i < cnt; i++) {
printf("%c", s[i]);
}
printf("\n");
return 0;
}
(写了俩周的题写出来还是有成就感的)
三.问题
1.回文字符
没有正确使用for循环,写的很乱,还不能正确运行
#include<stdio.h>
int main(int argc,char* argv[])
{
char s[50000];
gets(s);
int cnt=0,i=0,j,t=0;
int b = 0;
while (s[i] != '\0') {
i++;
cnt++;
}
printf("%d\n", cnt);
if (cnt % 2 == 0) {
for (i = 0; i < cnt / 2; i++) {
for (j = (cnt-1) ; j > ((cnt / 2)-1); j--) {
//printf("%c,%c\t", s[i], s[j]);
if (s[i] == s[j]) {
t++;
}
if (t == (cnt / 2))
{
b = 1;
}
}
}
}
else {
for (i = 0; i < cnt / 2; i++) {
for (j = (cnt - 1); j > (cnt / 2) ; j--) {
//printf("%c,%c\t", s[i], s[j]);
if (s[i] == s[j]) {
t++;
}
if (t == cnt / 2)
{
b = 1;
}
}
}
}
if (b == 1) {
printf("true");
}
else {
printf("false");
}
return 0;
}
2.输出月份英文名
#include <stdio.h>
#include<string.h>
char* getmonth(int n) {
switch (n) {
case 1: return "January";
case 2: return "February";
case 3: return "March";
case 4: return "April";
case 5: return "May";
case 6: return "June";
case 7: return "July";
case 8: return "August";
case 9: return "September";
case 10: return "October";
case 11: return "November";
case 12:return "December";
default: return NULL;
}
}
int main015()
{
int n;
char* s;
char* b;
scanf_s("%d", &n);
b = getmonth(n);
if (s == NULL) printf("wrong input!\n");
else printf("%s\n", s);
printf("%s", b);
return 0;
}
这个是运行正确的,我想用strcpy函数将每个月份的英文拷贝到一个字符串数组中,并利用swtich-case输出,还在尝试中没写出来
|