C语言小项目之电影粗劣信息系统
一、头文件编写:(Test_1.h)
#ifndef _TEST_1_H_
#define _TEST_1_H_
//#ifdef __cplusplus
//extern "C" {
//#endif
/*C语言中的基本数据类型:char
* short int long
* float double
* unsigned
* long long...
*
* c语言中默认int为signed即最高为符号位
*
* 另外c语言中的跳转判断:
* for(;;)
* do while
* while
* goto "tag"
*
* 在修饰变量的时候,static修饰的静态局部变量只执行一次,而且延长了局部变量的生命周期,直到程序运行结束以后才释放
* static修饰全局变量的时候,这个全局变量只能在本文件中访问,不能在其它文件中访问,即便是extern外部声明也不可以
* static修饰一个函数,则这个函数的只能在本文件中调用,不能被其他文件调用
*
* c语言中字符串表示:
* 一:字符数珠 char xxx[x]
* 二:字符指针 char* str
*
* 数组名即表示数组的首地址
* EOF:end of file文件结尾
* 关键字:extern---》表示变量或者函数在别处定义
* */
#define TSIZE 45//电影名字的数组长度--->define的用法 定义名 数值 注意的是不带分号;结尾
struct film {
char title[TSIZE];
int rating;
};
typedef struct film Item;
typedef struct node {
struct node *next;
Item item;
} Node;
typedef struct node *List;
/*枚举的常量是int类型
* 默认值从0开始...
* zero->0表示false
* one->1表示true
*/
typedef enum JudgeInt {
zero, one
} judgeInt;
//函数原型
void initializeList(List *pList); //初始化链表
/**
* 判断链表是否为空
* */
judgeInt listIsEmpty(const List *pList);
judgeInt listIsFull(const List *pList); //判断链表是否满了
unsigned int listItemCount(const List *pList); //链表中已存在的数据总数
judgeInt addItem(Item item, List *pList); //添加链表项
void traverse(const List *pList, void (*pfunction)(Item item)); //将函数pFunction作用于链表中的每一项
void emptyList(List *pList); //清空链表,释放内存
//#ifdef __cplusplus
//}
//#endif
#endif
二、头文件的实现:(Test_1.c)
#include "Test_1.h"
#include <stdlib.h>
#include <stdio.h>
/**
* static定义的局部函数
* */
static void copyToNode(Item item,Node *pNode);
void initializeList(List *pList){
*pList=NULL;
}
judgeInt listIsEmpty(const List *pList){
if(pList==NULL){
return one;
}else{
return zero;
}
}
//感觉有问题???----判断是否申请的内存超过一个节点的大小
judgeInt listIsFull(const List *pList){
Node *pt;
judgeInt temp;
pt=(Node*)malloc(sizeof(Node));
if(pt==NULL){
temp=one;
}else{
temp=zero;
}
return temp;
}
unsigned int listItemCount(const List *pList){
Node *head=*pList;
unsigned int count;
while(head!=NULL){
++count;
head=head->next;
}
return count;
}
judgeInt addItem(Item item,List *pList){
Node *pNew=(Node*)malloc(sizeof(Node));
Node *scan=*pList;
if(pNew==NULL){
return zero;
}
copyToNode(item,pNew);
pNew->next=NULL;
if(scan==NULL){
*pList=pNew;
}else{
while(scan->next!=NULL){
scan=scan->next;
}
scan->next=pNew;
}
return one;
}
/**
* 涉及到函数指针,让链表中的所有节点都执行该函数
* */
void traverse(const List *pList,void(*pfunction)(Item item)){
Node *head=*pList;
while(head!=NULL){
(*pfunction)(head->item);
head=head->next;
}
}
void emptyList(List *pList){
Node *pTemp;
while(*pList!=NULL){
pTemp=(*pList)->next;
free(*pList);
*pList=pTemp;
}
}
static void copyToNode(Item item,Node *pNode){
pNode->item=item;
}
三、简单的控制台显示main函数编写:(Test_One_1.c)
#include <stdio.h>
#include <stdlib.h>
#include "Test_1.h"
void showMovies(Item item);
char* s_gets(char* st,int n);
int main(void){
List movies;
Item temp;
initializeList(&movies);
//如果是满的
if(listIsFull(&movies)==one){
fprintf(stderr,"没有可用的内存\n");
exit(EXIT_FAILURE);//异常退出
}
puts("please enter first movie title:");//输出到控制台,自动换行(‘\0’换成回车换行)
while(s_gets(temp.title,TSIZE)!=NULL && temp.title[0]!='\0'){//如果输入的是空行则退出
puts("please enter your rating<0-10>:");
scanf("%d",&temp.rating);
while(getchar()!='\n'){
continue;
}
//如果添加失败的话
if(addItem(temp,&movies)==zero){
fprintf(stderr,"分配内存出现问题\n");
break;
}
if(listIsFull(&movies)==one){
fprintf(stderr,"这次真的满了\n");
break;
}
puts("please enter next movie title (empty line to stop):");
}
/*显示*/
if(listIsEmpty(&movies)==one){
printf("没有数据哦!");
}else{
printf("这里显示电影列表:\n");
traverse(&movies,showMovies);
}
/*清理*/
emptyList(&movies);
printf("再见!\n");
return 0;
}
//供traverse的通过调用--->使用函数指针
void showMovies(Item item){
printf("Movie: %s Rating: %d\n",item.title,item.rating);
}
/**
* 没看懂
* */
char* s_gets(char* st,int n){
char *ret_val;//是否读取到文件结尾
char *find;//查找换行符,如果有则用‘\0’代替
ret_val=fgets(st,n,stdin);//stdin标准输入,把键盘输入送入缓存区显示在控制台上,读取n-1个字符,最后一个字符置空字符,会保留一行结尾的换行符
if(ret_val){
find=strchr(st,'\n');//不存在则返回NULL,否则返回首次匹配到的地址
//如果存在‘\n’说明结束了把st中的换行符替换成空字符->字符串
//如果不存在
if(find){
*find='\0';
}else{
//getchar有缓存,输入多个,会从缓存中获取
while(getchar()!='\n')//将用户输入的字符回显到屏幕
continue;//处理后续内容
}
}
return ret_val;
}
四、使用JNI编译:
一、Android.mk的编写:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
#LOCAL_MODULE := student_manager_system
LOCAL_MODULE := movie_test_executable
LOCAL_SRC_FILES := src/Test_1.c \
src/Test_One_1.c
#LOCAL_C_INCLUDE := src \
$(LOCAL_PATH)/include
#添加PIE
LOCAL_CFLAGS += -pie -fPIE
LOCAL_LDFLAGS += -pie -fPIE
#optional表示在user eng tests版本下都编译
LOCAL_MODULE_TAGS := optional
include $(BUILD_EXECUTABLE)
二、Application.mk编写:(本例只指定了armeabi平台)
APP_ABI :=armeabi
三、我的编译方式:
1、使用eclipse目录结构如图:
2、进入jni目录中
按住shift+鼠标右键,会出现命令行选项,点击进入后输入:ndk-build.cmd即可编译(前提是你已经下载解压好ndk10及以上的版本,把build路径添加到系统环境变量path中),成功编译后会在生成libs和obj文件,所需的可执行文件或者so文件在
libs的armeabi下。
3、如何执行使用?
放在安卓系统的/system/bin下,执行./xxxx你的文件名回车即可
四、我要说的感谢的话
感谢没有放弃,感谢我还清醒,感谢所有支持我的人,谢谢!^__^