一、 处理一段字符串,以空格为分割符,打印新的字符串(不打印空格)
1、 主要点就是字符分割函数内
思想:对字符串进行遍历,如果字符为空格给字符赋值为'\0'后续不打印,此时指针数组的第一个地址在后面判断内满足条件可以开始使用,继续一直往后遍历字符串当遇到非空格有效字符此时指针数组的第一个地址可以使用,将指针数组内第一个元素(也就是地址记住第一个字符串内非空有效字符的地址后续打印,但是为了防止重新指向,指针数组第一个禁止使用,直到再次遇到新的空格判断条件内可以开始使用指针数组第二个地址,到下次遇到非空有效字符时,开始使用第二个指针数组元素,记住新一个字符串内非空有效字符地址,以此类推但最后遇到空格,会满足判断条件将最后的'\0'(不是字符串内空格转换的)这个地址会记录到指针数组最后的一个元素内也会输出,所以主函数就进行了处理,也有可能字符串是以空格开始的所以先给使用第一个地址的权限,如果没有则照上面执行。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
enum VALUE
{
ERROR = -2,
NULL_ERROR,
OK,
};
int malloc_1(char **strN);
int split(char *str, char *aar[10], int *index);
int main()
{
char *str = NULL;
int index;
if((malloc_1(&str)) < 0 )
{
printf("开辟空间失败!\n");
return ERROR;
}
char *aar[10];
for(int i = 0; i < 10; i++)
{
aar[i] = (char *)malloc(sizeof(char) * 20);
memset(aar[i], '\0', sizeof(char) * 20);
}
if(split(str,aar,&index) < 0)
{
printf("拆分失败!\n");
return ERROR;
}
for(int i = 0; i<index+1; i++)
{
if(*aar[i] != '\0')
puts(aar[i]);
}
free(str);
str = NULL;
return OK;
}
//开辟空间
int malloc_1(char **strN)//*strN = &str strN = str
{
if(strN == NULL)
{
return NULL_ERROR;
}
*strN = (char *)malloc(sizeof(char) * 100);
memset(*strN, '\0' , sizeof(char) * 100);
return OK;
}
//分割字符
int split(char *str, char *aar[], int *index)
{
if(str == NULL || aar == NULL || index == NULL)
{
return NULL_ERROR;
}
printf("请输入一串字符:\n");
gets(str);
int i = 0, j = 1;
//思想
while( *str != '\0')
{
if(*str == ' ')
{
if(j == 0)
{
*str = '\0';
i++;
j = 1;
}
}
else
{
if(j == 1)
{
aar[i] = str;
j = 0;
}
}
str++;
}
*index = i;
return OK;
}
二、使用结构体输入学生信息,按成绩高低输出学生信息:
1、主要思想是利用冒泡排序,进行不同结构体内所有内容的整体置换:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct strudet
{
char name[20];
float score;
}ST;
int main()
{
ST *person = (ST *)malloc(sizeof(ST) * 5);
memset(person, '\0', sizeof(ST) * 5);
int i = 0;
printf("请输入学生的姓名,成绩:\n");
for(i = 0; i < 5; i++)
{
scanf("%s%*c%f",(person+i)->name,&(person+i)->score);
}
printf("INPUT SUCCESS\n");
int j = 0;
ST tmp;
for(i = 0; i < 4; i++)
{
for(j = 0;j < 4-i; j++)
{
if(((person+j)->score) > ((person+j+1)->score))
{
tmp = *(person+j+1);
*(person+j+1) = *(person+j);
*(person+j) = tmp;
}
}
}
for(i = 0; i < 5; i++)
{
printf("姓名:%s,成绩:%1.f\n",(person+i)->name,(person+i)->score);
}
}
2、思想:将学生的成绩按照顺序放置在一个新的数组内,然后定义一个下标数组,根据冒泡排序当新的数组内(也就是学生成绩)进行排序时,让下标数组内也进行相同的排序,当排序完后下标数组也排序完后,此时就可以依次使用下标数组内的值进行排序输出,因为下标数组内的值对应着哪一个几个的学生成绩。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct strudet
{
char name[20];
float score;
}ST;
int main()
{
ST *person = (ST *)malloc(sizeof(ST) * 5);
memset(person, '\0', sizeof(ST) * 5);
int i = 0;
printf("请输入学生的姓名,成绩:\n");
for(i = 0; i < 5; i++)
{
scanf("%s%*c%f",(person+i)->name,&(person+i)->score);
}
printf("INPUT SUCCESS\n");
int j = 0;
int tmp;
int tmp1;
int a[5] = {0,1,2,3,4};
float aa[5] = {0};
for(i = 0; i <5; i++)
{
aa[i] = (person+i)->score;
}
//思想
for(i = 0; i < 4; i++)
{
for(j = 0; j < 4-i; j++)
{
if(aa[j] > aa[j+1])
{
tmp = aa[j+1];
aa[j+1] = aa[j];
aa[j] = tmp;
tmp1 = a[j+1];
a[j+1] = a[j];
a[j] = tmp1;
}
}
}
for(i = 0; i < 5; i++)
{
printf("姓名:%s,成绩:%1.f\n",(person+a[i])->name,(person+a[i])->score);
}
free(person);
person = NULL;
}
三、多文件编译
工程目录下:四个文件夹 一个Makefile
1、Makefile
makefile关系到了整个工程的编译规则。一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系 列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为makefile就像一个Shell 脚本一样,其中也可以执行操作系统的命令。
makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。make是 一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令。
#自定义变量赋值小makefile都可用这个定义的变量$(OBJS)或者$OBJS都可以取值
OBJS:=Fir.o Good.o input.o main.o malloc_1.o menu.o output.o Two.o
MyAPP:=Mystruct
#系统变量无默认值给其赋值
CFLAGS:=-c -g -Wall
RM:= rm -rf
CC:= gcc
#声明赋值后的变量
export OBJS CFLAGS RM CC
#执行目标先执行src内的makefile再执行obj内的
ALL:
make -C ./src/
make -C ./obj/
Clear:
RM ./obj/*.o
RM ./bin/*
2、bin 用来存放生成的可执行文件
3、include 用来存放头文件
#ifndef _MAIN_H_ //判断不存在main.h
#define _MAIN_H_//定义头文件main.h
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//定义学生结构体 姓名 学号 3门成绩数组
typedef struct student
{
char name[20];
int ID;
float grade[3];
}ST;
//定义枚举用到函数内报错返回值以及输入功能选择
enum VALUE
{
COUNT_ERROR = -3,
ERROR = -2,
MALLOC_ERROR,
NULL_ERROR,
MALLOC,
INPUT,
OUTPUT,
FIR_AVE,
TWO_BAD,
GOOD,
QUIT,
OK
};
//声明子函数
int malloc_1(ST **Nperson, int count);//*Nperson == &person Nperson = person
int input(ST *person, int count);
int output(ST *person, int count);
int fir_ave(ST *person, int count, float *Fir_ave);
int two_bad(ST *person, int count, ST *personNEW, int *index);
int good(ST *person, int count, ST *personNEW, int *index);
void menu();
#endif
4、obj 用来存放源文件生成的.o文件
需要写makefile执行
#执行目标将生成的MyAPP送到bin文件下 $^当前的所有依赖文件
#All为目标 MyAPP为依赖
All:MyAPP
mv $^ ../bin/
#$(CC)调取gcc $(OBJS)调取生成的.o文件
MyAPP:$(OBJS)
$(CC) $^ -o MyAPP
5、src 存放源文件
makefile
#移动所有的依赖文件到obj下 依赖文件即生成的.o文件
All:$(OBJS)
mv $^ ../obj/
#以下就是对.c代码进行预编译 $<为第一个依赖文件 $@为目标文件
Fir.o:Fir.c
$(CC) $(CFLAGS) $< -o $@
Good.o:Good.c
$(CC) $(CFLAGS) $< -o $@
input.o:input.c
$(CC) $(CFLAGS) $< -o $@
main.o:main.c
$(CC) $(CFLAGS) $< -o $@
malloc_1.o:malloc_1.c
$(CC) $(CFLAGS) $< -o $@
menu.o:menu.c
$(CC) $(CFLAGS) $< -o $@
output.o:output.c
$(CC) $(CFLAGS) $< -o $@
Two.o:Two.c
$(CC) $(CFLAGS) $< -o $@
各源文件(编写在一起了,如果分开编写,则需引用头文件)
//引用工程目录下include内的头文件
#include "../include/main.h"
int main()
{
//结构体类型定义指针用来存放开辟多少个学生的空间
ST *person = NULL;
//用来存放临时开辟的学生空间执行后面的功能
ST *personNEW = NULL;
//用来输入学生个数
int count = 0;
//用来存放个学生第一门成绩的平均值
float Fir_ave = 0;
//用来统计临时开辟的空间内,有多少个学生占据了
int index = 0;
while(1)
{
//输入菜单供选择
menu();
//输入数字选择执行哪项功能
int Option;
printf("请选择哪项功能:\n");
scanf("%d",&Option);
//推出死循环
if(QUIT == Option)
{
printf("退出成功!\n");
break;
}
switch(Option)
{
//开辟空间enum对应的为1 后面依次对应菜单栏数字 输入其它报错
case MALLOC:
{
//统计班级人数
printf("请输入班级人数:\n");
scanf("%d",&count);
//如果子函数传回负值
//则意味着子函数内执行程序开辟空间失败
if((malloc_1(&person, count)) < 0)
{
printf("学生信息空间开辟失败!\n");break;
}
printf("%d个学生信息空间开辟成功!\n",count);
//开辟临时空间
if((malloc_1(&personNEW, count)) < 0)
{
//如果开辟临时空间失败则前面开辟的空间也无意义,给其释放
free(person);
person = NULL;
return ERROR;break;
}
printf("临时存放%d个学生信息空间开辟成功!\n",count);
break;
}
case INPUT:
{
if((input(person, count)) < 0 )
{
return ERROR;break;
}
printf("输入学生信息成功!\n");
break;
}
case OUTPUT:
{
printf("学生信息如下:\n");
if(output(person, count) < 0 )
{
return ERROR;break;
}
break;
}
case FIR_AVE:
{
if((fir_ave(person, count, &Fir_ave)) < 0 )
{
printf("计算学生第一门平均分失败!\n");break;
}
printf("学生第一门成绩平均分为:%.1f\n",Fir_ave);break;
}
case TWO_BAD:
{
if((two_bad(person, count, personNEW, &index)) < 0)
{
return ERROR;break;
}
output(personNEW, index);
break;
}
case GOOD:
{
memset(personNEW, '\0', sizeof(ST) * count);
if((good(person, count, personNEW, &index)) < 0)
{
return ERROR;break;
}
output(personNEW, index);
break;
}
default: printf("INPUT ERROR!!!");
}
}
//释放所有开辟的空间
free(person);
person = NULL;
free(personNEW);
personNEW = NULL;
return 0;
}
//引入上个目录下文件内自定义的头文件
//#include "../include/main.h"
//定义计算所有学生第一门成绩平均值
//形参为开辟的空间内容 输入学生个数 以及用来存放最后计算结果的指针
int fir_ave(ST *person, int count, float *Fir_ave)
{
//如果传进来的地址为空则报错返回负值 后面均如此
if(person == NULL)
{
return NULL_ERROR;
}
if(count < 0)
{
return COUNT_ERROR;
}
int i;
float sum;
for(i = 0; i < count; i++)
{
//计算每个学生的第一门成绩总和 (person+i)为5个空间每个空间的地址
sum += (person+i) -> grade[0];
}
*Fir_ave = sum / (float)count;
return OK;
}
//得出优秀的学生
//#include "../include/main.h"
int good(ST *person, int count, ST *personNEW, int *index)
{
if(person == NULL || personNEW == NULL || index == NULL)
{
return NULL_ERROR;
}
if(count < 0)
{
return COUNT_ERROR;
}
int i,j;
int index_1 = 0;
float average = 0;
printf("优秀的同学信息如下:\n");
for(i = 0; i < count; i++)
{
int sum = 0;
for(j = 0; j < 3; j++)
{
//计算3门成绩的总和
sum += (person+i)->grade[j];
}
average = (float)sum / 3;
if((((person+i)->grade[0]) >= 85 && ((person+i)->grade[1]) >= 85 \
&& ((person+i)->grade[2]) >= 85) || average >= 90)
{
//如果满足每门成绩大于85则将此空间内学生的信息放入新开辟的临时空间
*(personNEW+index_1) = *(person+i);
//计算存放了几个学生
index_1++;
}
}
*index = index_1;
return OK;
}
//#include "../include/main.h"
int input(ST *person, int count)
{
if(person == NULL)
{
return NULL_ERROR;
}
if(count < 0)
{
return COUNT_ERROR;
}
int i,j;
for(i = 0; i < count; i++)
{
printf("请输入第%d个学生的信息:\n",i+1);
//输入学生的各类信息指向结构体内各个内容
scanf("%s%*c%d",(person+i)->name,&(person+i)->ID);
for(j = 0; j < 3; j++)
{
scanf("%f",&(person+i)->grade[j]);
}
}
return OK;
}
//#include "../include/main.h"
int output(ST *person, int count)
{
if(person == NULL)
{
return NULL_ERROR;
}
if(count < 0)
{
return COUNT_ERROR;
}
int i,j;
//参照输入变为输出学生信息
for(i = 0; i < count; i++)
{
printf("学生姓名:%s\t学号:%d\t成绩:",(person+i)->name,(person+i)->ID);
for(j = 0; j < 3; j++)
{
printf("%.1f\t",(person+i)->grade[j]);
}
puts("");
}
return OK;
}
//开辟空间
//#include "../include/main.h"
int malloc_1(ST **Nperson, int count)//*Nperson == &person Nperson = person
{
if(Nperson == NULL)
{
return NULL_ERROR;
}
if(count < 0)
{
return COUNT_ERROR;
}
//开辟空间 结构体类型 大小也是结构体所占字节数
//总共开多少个空间由输入的学生数决定
*Nperson = (ST *)malloc(sizeof(ST) * count);
if(Nperson == NULL)
{
return MALLOC_ERROR;
}
//置空开辟的空间
memset(*Nperson, '\0', sizeof(ST) * count);
return OK;
}
//#include "../include/main.h"
//菜单功能选择
void menu()
{
printf("******学生信息*********\n");
printf("请选择:\n");
printf("1----------------malloc\n");
printf("2----------------input\n");
printf("3----------------output\n");
printf("4----------------fir_ave\n");
printf("5----------------two_bad\n");
printf("6----------------all_good\n");
printf("7----------------quit\n");
}
//#include "../include/main.h"
int two_bad(ST *person, int count, ST *personNEW, int *index)
{
if(person == NULL || personNEW == NULL || index == NULL)
{
return NULL_ERROR;
}
if(count < 0)
{
return COUNT_ERROR;
}
int i;
int index_1 = 0;
//输出两门以上不合格的学生
printf("不合格的同学信息如下:\n");
for(i = 0; i < count; i++)
{
if((((person+i)->grade[0]) < 60 && ((person+i)->grade[1]) < 60) \
|| (((person+i)->grade[0]) <60 && ((person+i)->grade[2]) < 60) \
|| (((person+i)->grade[1]) < 60 && ((person+i)->grade[2]) < 60))
{
//与之前相同
*(personNEW+index_1) = *(person+i);
index_1++;
}
}
*index = index_1;
return OK;
}