通信原理课设(gec6818) 001:环境配置+文件操作

       

目录

常用终端命令

终端命令格式

查阅命令

实用技巧(特别有用尤其电脑分屏的时候)

编译

一、设置环境

二、学会操作文件

1、打开文件

2、读/写文件

2.1  读文件

2.2  写文件

3、关闭文件

三、练习

1、打开一个文件

2、在一个1.txt的前面4个字节放了一个千位数,以 %d的形式输出它的两倍

3、写一个简单的学生信息录入系统:学生信息包括:姓名 学号 年龄 地址    从终端输入学生信息写入到文件里面保存,一个学生一行数据


        简单记录一下为期两周的通信原理课设,本次课设采用交叉编译,所谓交叉编译是指一种计算机环境中运行的编译程序,能编译出在另外一种环境下运行的代码。简而言之即在一个平台上生成另一个平台上的可执行代码。此次课设的代码先在ubuntu里面使用arm-linux-gcc编译,再利用SecureCRT将编译好的文件传输到开发板上。

Securecrt网盘链接:
链接:https://pan.baidu.com/s/1pnA4HHJybezT-zPxCD3_Uw?pwd=scrt 
提取码:scrt

上课之前,自己先准备了一点基础知识,主要是ubuntu的基本命令,更快上手,还挺有用的:

常用终端命令

ls 查看当前文件夹下的内容 -a:所有的 -l:表示长列表形式

pwd (print work directory)查看当前所在文件夹

cd (change directory)      切换文件夹

touch                               如果文件不存在,新建文件

mkdir (make directory)    创建目录

rm                                    删除指定的文件夹

clear                                清屏
 

终端命令格式

command [-optinons] [parameter]

  • command :命令名

  • -optinons:选项,用来对命令进行控制,可省略

  • parameter:传递给命令的参数

[]代表可选

查阅命令

command --help : 显示command命令的帮助信息

man command : 查阅命令手册
man 页数 函数接口

(command替换成具体的命令)
 

实用技巧(特别有用尤其电脑分屏的时候)

ctrl+shift+= 放大终端窗口的字体显示

ctrl+- 缩小终端窗口的字体显示

ctrl+c 退出选择,另起一行

 

编译

gcc编译c文件,g++编译c++文件。

当你的程序只有一个源文件时,直接就可以用gcc命令编译它。但是当你的程序包含很多个源文件时,用gcc命令逐个去编译时,你就很容易混乱而且工作量大.

所以出现了make工具!make工具可以看成是一个智能的批处理工具,它本身并没有编译和链接的功能,而是用类似于批处理的方式—通过调用makefile文件中用户指定的命令来进行编译和链接的。

makefile在一些简单的工程完全可以人工手下,但是当工程非常大的时候,手写makefile也是非常麻烦的,如果换了个平台makefile又要重新修改。

这时候就出现了Cmake这个工具,cmake就可以更加简单的生成makefile文件给上面那个make用。当然cmake还有其他功能,就是可以跨平台生成对应平台能用的makefile,你不用再自己去修改了。可是cmake根据什么生成makefile呢?它又要根据一个叫CMakeLists.txt文件(学名:组态档)去生成makefile。

一、设置环境

1、安装VMware-player-full-17.0.2-21581411
2、设置虚拟机共享文件夹

      由于我们的开发是在win里面,因此我们写的代码要放在共享文件夹里面linux才可以看得到。
      菜单栏选择虚拟机设置-> 选项 -> 共享文件夹 -> 总是启动 -> 添加 -> 下一步-> 浏览 -> 选择自己喜欢的文件夹(最好是不带中文以及空格的)-> 确定 -> 下一步 -> 完成 -> 确定。

      打开终端(ctrl + alt + t),切换到我们的共享目录:

cd /mnt/hgfs/你的共享目录名字

二、学会操作文件

        Linux -> 是世界上面运用做广的系统,它是一个开源的系统,这个系统是继承于unix。Linux中“everything is file !!!”,也就是一切皆文件。操作系统操作文件即可,因此系统的操作就离不开文件io。

        正如把大象装进冰箱需要三步: 1 打开冰箱门       2 将大象装进去       3 关闭冰箱门

        所以操作文件也类似上述三步: 1 打开文件           2  读/写文件            3 关闭文件

     (特别重要,之后的文件操作都是基于这三步)

1、打开文件
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>

 int open(const char *pathname, int flags);//打开文件
 int open(const char *pathname, int flags, mode_t mode)//打开或者创建一个文件
 int creat(const char *pathname, mode_t mode);//创建一个文件

参数解释:

pathname:路径名 ,这个参数的原型是一个char *字符串
                   相对路径:  "./1.txt"、 "../2.txt"(.是相对于当前目录;..是相当于上级目录或者
                                                                        叫做父目录)
                   绝对路径:"/mnt/hgfs/share/1.txt" 
flags: 打开文件的一些标志  用位域表示这里用宏去搞定这些功能的问题
          如果有需求多个功能同时打开,那么直接用 | 按位或
          下面的三个标志任选其一,这个标记是必须要给的
          O_RDONLY  :只读
          O_WRONLY: 只写
          O_RDWR:     读写

          下面的标记根据自己的需求去选择
          O_CREAT:创建标记:如果你给这个创建标记  第三个参数就要给了,给了这个标                                                      记表示此文件存在即打开,不存在则创建并打开
          O_NONBLOCK:非阻塞打开这个文件 ,文件打开默认是阻塞的
          O_APPEND:追加标记, 打开文件光标默认在开头
          O_TRUNC:截短标记,将内容清空

mode:权限 linux里面的权限分为三个部分:用户 组用户 其它用户
                S_IRWXU   用户可读可写可执行
                S_IRUSR    用户只读
                ....
                S_IRWXG    组户可读可写可执行
                .....
                S_IRWXO 其它用户可读可写可执行
                ......
                我们可以使用8进制去表示一个权限:常用的是:0664
返回值
            成功返回一个大于等于0的整数(实际上是 >= 3)
            我们的进程在一启动的时候操作系统就会为这个程序打开三个文件
                    1 标准的输入 -> 0
                    2 标准的输出 -> 1
                    3 标准的出错 -> 2
            返回给你的这个整数是一个数组(进程文件表项)的下标
            这个整数我们有一个名词去描述 ---- 文件描述符(fd)
            后续对于文件的操作都是基于这个fd的
            失败返回-1,同时errno被设置,perror可以解析一个系统错误

perror:

   #include <stdio.h>
   void perror(const char *s);
		

s:程序员设计的一个标记,该接口调用会打印出系统的错误信息。

使用方法:

int fd = open();
if(-1 == fd)//马上进行错误判断
{
	perror("发生错误:");
}
2、读/写文件
2.1  读文件
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);

参数解释:

fd:文件描述符
buf:我们读到的内容你要放在一个内存才能操作,这个buf就是这块内存的首地址
         c语言是没有边界检查的,因此我们要时刻的注意是否会越界的问题
         程序员开辟内存一般是在栈空间或者堆空间
         栈:在代码块里面开辟变量或者数组,代码块执行完毕,这块空间会被释放
         堆:动态内存分配:malloc、calloc、realloc;在堆上面开辟的内存是不会主动释放的

count: 你要读取多少个字节 (>= 0)

返回值:成功返回实际读到的字节数 <= count
              失败返回-1,同时errno被设置
              文件内容的读取都是从光标位置进行的,每读写一个字节,光标就会自动往后面偏移一个。

2.2  写文件
#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);

参数解释:

 fd:文件描述符
 buf:你要写什么样子的内容到我们的文件,实际上就是一个内存,里面存储我们要写入的             内容 

count:我们要写入多少个字节
返回值:成功返回实际写入的字节数 <= count
              失败返回-1,同时errno被设置

3、关闭文件
#include <unistd.h>
int close(int fd);

close - 关闭一个文件描述符

三、练习

1、打开一个文件
#include <stdio.h>
#include <sys/types.h>  
#include <sys/stat.h>
#include <fcntl.h>
int main()
{
	//打开一个文件
	int fd=open("./1.txt",O_RDWR);
	if(-1==fd)
	{
		perror("open 1.txt error");
		return -1;
	}
	
	printf("open 1.txt sucessful!\r\n");
	printf("test");
	return 0;
}
2、在一个1.txt的前面4个字节放了一个千位数,以 %d的形式输出它的两倍
#include <stdio.h>
#include <sys/types.h>  
#include <sys/stat.h>
#include <fcntl.h>
int main()
{
	//1、打开一个文件
	int fd=open("./1.txt",O_RDWR);
	int a,b,c,d,e;
	int A[5];
	if(-1==fd)
	{
		perror("open 1.txt error");
		return -1;
	}
	//2、读取文件内容
	char buf[1025] = {0}; //在栈上开辟1024字节
	int r = read(fd,buf,1024);//1025是为了\0,读取1.txt的内容并存放在了buf
	//以%d的形式输出两倍,前四个字节
	if(-1 == r)
	{
		perror("read error");
		return -2;
	}
	printf("%c\n",buf[0]);
	printf("%c\n",buf[1]);
	printf("%c\n",buf[2]);
	printf("%c\n",buf[3]);
	
	a = (buf[0]-'0')*1000;
	b = (buf[1]-'0')*100;
	c = (buf[2]-'0')*10;
	d = (buf[3]-'0')*1;
	e = a+b+c+d;
	printf("%d\n",e*2);
	
	//3、关闭文件
	close(fd);
	return 0;
}
3、写一个简单的学生信息录入系统:学生信息包括:姓名 学号 年龄 地址
    从终端输入学生信息写入到文件里面保存,一个学生一行数据
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>

//全局的学生信息文件
int fd_stu = -1;

//初始化文件 这个文件是固定的
void StudentFileInit(void)
{
    fd_stu = open("./student.txt",O_RDWR | O_CREAT,0664);
    if(-1 == fd_stu)
    {
        perror("open error");
        exit(2);
    }
}

//将文件销毁
void DestoryStudentFile(void)
{
    close(fd_stu);
}

//往一个文件里面写入一个字符串
void WriteStringToFile(int fd,const char * str)
{
    write(fd,str,strlen(str));
}

//存储学生信息
void SaveStudentMassage(void)
{

    StudentFileInit();//将文件打开

    char name[64];
    int age;
    int id;
    char addr[128];

    while(1)//录到sb250就结束输入
    {
        //获取学生信息
        printf("请输入学生姓名(sb250结束):");
        fflush(stdout);
        scanf("%s",name);
        if(!strcmp(name,"sb250"))
        {
            break;
        }
        //printf("name = %s\n",name);
        printf("请输入学生学号:");
        fflush(stdout);
        scanf("%d",&id);
        printf("请输入学生年龄:");
        fflush(stdout);
        scanf("%d",&age);
        printf("请输入学生地址:");
        fflush(stdout);
        scanf("%s",addr);

        char buf[1024];
        sprintf(buf,"%d %s %d %s\n",id,name,age,addr);
        WriteStringToFile(fd_stu,buf);

    }
    DestoryStudentFile();
}

//缓冲区的概念测试
void hehe(void)
{
    int i;
    for(i = 0;i < 1024;i++)
    {
        printf("A");
    }
    //我们也可以强制让它刷新
    fflush(stdout);
    while(1);
}

//FILE * stdout = fopen
int main(int argc,char * argv[])
{
    if(argc < 3)
    {
        printf("参数不对\n");
        return -1;
    }   
    printf("%s %s\n",argv[1],argv[2]);
    SaveStudentMassage();  
    return 0;
}

代码解释:

1、flush(stdout):强制刷新

对于标准输出,需要输出的数据并不是直接输出到终端上,而是首先缓存到某个地方,当遇到行刷新标志或者该缓存已满的情况下,才会把缓存的数据显示到终端设备上。 ANSI C中定义换行符'n'可以认为是行刷新标志。 所以,printf函数没有带'n'是不会自动刷新输出流,直至缓存被填满。flush(stdout)的作用就是强制刷新,将缓冲区里的内容送到屏幕上。

2、int main(int argc,char * argv[])

argc是命令行总的参数个数
argv[]是argc个参数,其中第0个参数是程序的全名。

argc和argv是你通过命令行窗口传给程序的

当你需要程序带参数地启动的时候,就用int main(int argc, char *argv[])

posted @ 2023-12-22 08:33  Flying3080  Views(65)  Comments(0Edit  收藏  举报  来源