鱼C论坛

 找回密码
 立即注册
查看: 1768|回复: 16

[已解决]关于从dat文件获取数据控制机器人行走问题(用C++)

[复制链接]
发表于 2019-9-12 13:53:17 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 丶不离不弃 于 2019-9-12 13:58 编辑

最近我们老师布置了一个很难的作业,我一点都不会写,求大神们给予帮助!!(这段代码是我同学copy给我+我自己写的,我肯定不能直接交,所以求会写的大神帮帮我和我说下思路,解释下我在程序中注释部分的意思,看看我有哪些错误的地方和要改进的地方,谢谢大家!)
作业是关于机器人路径控制的C++程序,首先要创立一个dat文件,里面写几4行代码(如图附在下面),第一行第一个是角度theta,第二个是半径r,分别给予了4组数据。
我们需要做的就是创建一个polar2Rect(r,theta,dx,dy)这个函数,分别读取角度和半径数据,然后赋值刀dx,dy中,最后输出dx,dy,停止的条件就是dat文档中角度theta和半径r都为负数。
#include <iostream>
#include <string>
#include <fstream>
#include <cmath>
#include <sstream>
//#include <iomanip>    //这里的库为啥可用可不用,这个库是干啥的?
#define _USE_MATH_DEFINES
using namespace std;
void polar2Rect(double theta, double r, double&dx, double&dy){          /*老师让定义一个机器人行走的函数,我就是不明白这是啥,
 *                                                                   为啥将theta和r调换下位置就不行了?*/
    theta = (M_PI*(theta-90))/180;
    dx = cos(theta)*r;
    dy = sin(theta)*r;
}
int main() {
    ifstream infile("hw2e.txt");       //我在网上搜的关于打开文件夹并读取上面的数据的代码,对了infile 这个可以随便改吗?
    string line;                          //求解释这语句
    double dx,dy;
    if(!infile.is_open()){
        cout<<"cant not open the file"<<'\n';
        return -1;                  //求解释
    }
    while(getline(infile,line)){       //以下所有语句直到if那里都需要解释
        string b1;
        string b2;
        stringstream ss(line);
        ss>>b1;
        ss>>b2;
        double theta=stod(b1);
        double r = stod(b2);
        if(r<0 && theta<0){
            cout<< "Robot has reached final destination." <<'\n';
        }
        else{
            polar2Rect(theta,r,dx,dy);
            cout<< "New robot position (X,Y): " <<"("<<dx<<","<<dy<<")"<<'\n';
        }
        infile.close();

    }
    return 0;
}
最佳答案
2019-9-12 19:46:29
本帖最后由 superbe 于 2019-9-12 19:53 编辑

#include <iostream>
#include <string>
#include <fstream>
#include <cmath>
#include <sstream>
#include <iomanip>        //后面输出用了setprecision(4),就要用这个库

//#define _USE_MATH_DEFINES
#define M_PI 3.14159        //添加了这行

using namespace std;

void polar2Rect(double r, double theta, double &dx, double &dy){        //theta和r可以调换位置,相应调用函数的参数也调换下,保证对应就可以。这里调换过了
    theta = (M_PI*(theta-90))/180;
    dx+= cos(theta)*r;        //这行原来是dx=cos(theta)*r;不对,看说明应该是累加计算
    dy+= sin(theta)*r;        //这行原来是dy=sin(theta)*r;
}

int main() {
    ifstream infile("hw2e.txt");       //infile是一个ifstream类的对象名(有点变量的意思),可以改,后面用到infile的都相应改
    string line;                       //定义一个string类的对象,这个类是用来处理字符串的,后面从文件读一行到line
    double dx=0,dy=0;                  //添加了初始化0
    if(!infile.is_open()){
        cout<<"cant not open the file"<<'\n';
        return -1;                  //main函数返回值是给系统的,程序中用不到,返回多少都可以没关系
    }
    while(getline(infile,line)){       //从文件中读取一行到line中
        string b1;                     //string类的对象b1
        string b2;                     //string类的对象b2
        stringstream ss(line);         //字符串流的对象ss,用line"初始化",支持字符串输入输出操作      
        ss>>b1;                        //从ss输入一个值到b1(字符串形式的数值)
        ss>>b2;                        //从ss输入一个值到b2
        double theta=stod(b1);         //stod()函数把字符串转换成double,这里把b1转换成double型给r
        double r = stod(b2);           //把b2转换成double给theta
        if(r<0 || theta<0){        //这里if条件原来是r<0 && theta<0,而看说明应该是r或theta为负
            cout<< "Robot has reached final destination." <<'\n';
        }
        else{
            polar2Rect(r,theta,dx,dy);        //这里theta和r也相应调换过了
            cout<< "New robot position (X,Y): " <<"("<<fixed<<setprecision(4)<<dx<<","<<dy<<")"<<'\n';    //增加了<<fixed<<setprecision(4),为了使输出整齐,好看些
        }
    }
    infile.close();

    return 0;
}
robot.PNG
代码修改的地方注释里说明了。我也只能理解到这个程度了。
wenjian.jpg

老师要求的输出范例,最后面

老师要求的输出范例,最后面
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2019-9-12 13:55:38 | 显示全部楼层
求求各位大神讲解下解题思路,然后用到的许多语句我都不会,能不能讲解下从dat文件中读取数据的各类语句的意思呢?还有一个就是为啥我的dat文件读取不出来呢?macbook怎么创建dat文件呢?谢谢大家
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-9-12 13:57:59 | 显示全部楼层
下面是我同学写的代码,我的代码是参考他的,但是我完全不懂意思。
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <math.h>
#include <iomanip>
using namespace std;
void polar2Rect(double theta, double r, double&dx, double&dy){
    theta=(-theta+90)*M_PI/180.0;
    dx+=cos(theta)*r;
    dy+=sin(theta)*r;
}
int main(int argc, char** argv)
{
    ifstream file("hw2e.txt");
    string line;
    double dx,dy;
    if(file.is_open())
    {
        while(getline(file,line)){
            string buf_0;
            string buf_1;
            stringstream ss(line);
            double r;
            double theta;
            ss>>buf_0;
            ss>>buf_1;
            theta=stod(buf_0);
            r=stod(buf_1);
            if(theta<0||r<0)
            {
                cout<<"Robot has reached final destination."<<endl;
                return 0;
            }
            polar2Rect(theta,r,dx,dy);
            cout<<"New robot position (X,Y):("<<fixed<<setprecision(4)<<dx<<","<<dy<<")."<<endl;
        }
        file.close();
    }
    cout<<"Robot has reached final destination."<<endl;
    return 0;
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-9-12 17:52:20 | 显示全部楼层
M_PI没定义,是3.14吗,还有main函数里dx,dy都没赋初值,再把dx,dy传给polar2Rect有问题吧
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-9-12 18:07:34 | 显示全部楼层
你同学的dx,dy是累加计算的,但没赋初值,而你的dx,dy是每次都重新计算一个新值,结果不同,不懂你们的原理,哪个是对的
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-9-12 18:15:56 | 显示全部楼层
刚看到上面的英文有详细说明,明白了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-9-12 19:46:29 | 显示全部楼层    本楼为最佳答案   
本帖最后由 superbe 于 2019-9-12 19:53 编辑

#include <iostream>
#include <string>
#include <fstream>
#include <cmath>
#include <sstream>
#include <iomanip>        //后面输出用了setprecision(4),就要用这个库

//#define _USE_MATH_DEFINES
#define M_PI 3.14159        //添加了这行

using namespace std;

void polar2Rect(double r, double theta, double &dx, double &dy){        //theta和r可以调换位置,相应调用函数的参数也调换下,保证对应就可以。这里调换过了
    theta = (M_PI*(theta-90))/180;
    dx+= cos(theta)*r;        //这行原来是dx=cos(theta)*r;不对,看说明应该是累加计算
    dy+= sin(theta)*r;        //这行原来是dy=sin(theta)*r;
}

int main() {
    ifstream infile("hw2e.txt");       //infile是一个ifstream类的对象名(有点变量的意思),可以改,后面用到infile的都相应改
    string line;                       //定义一个string类的对象,这个类是用来处理字符串的,后面从文件读一行到line
    double dx=0,dy=0;                  //添加了初始化0
    if(!infile.is_open()){
        cout<<"cant not open the file"<<'\n';
        return -1;                  //main函数返回值是给系统的,程序中用不到,返回多少都可以没关系
    }
    while(getline(infile,line)){       //从文件中读取一行到line中
        string b1;                     //string类的对象b1
        string b2;                     //string类的对象b2
        stringstream ss(line);         //字符串流的对象ss,用line"初始化",支持字符串输入输出操作      
        ss>>b1;                        //从ss输入一个值到b1(字符串形式的数值)
        ss>>b2;                        //从ss输入一个值到b2
        double theta=stod(b1);         //stod()函数把字符串转换成double,这里把b1转换成double型给r
        double r = stod(b2);           //把b2转换成double给theta
        if(r<0 || theta<0){        //这里if条件原来是r<0 && theta<0,而看说明应该是r或theta为负
            cout<< "Robot has reached final destination." <<'\n';
        }
        else{
            polar2Rect(r,theta,dx,dy);        //这里theta和r也相应调换过了
            cout<< "New robot position (X,Y): " <<"("<<fixed<<setprecision(4)<<dx<<","<<dy<<")"<<'\n';    //增加了<<fixed<<setprecision(4),为了使输出整齐,好看些
        }
    }
    infile.close();

    return 0;
}
robot.PNG
代码修改的地方注释里说明了。我也只能理解到这个程度了。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-9-12 20:45:11 | 显示全部楼层
superbe 发表于 2019-9-12 19:46
#include
#include
#include

真的是万分感谢,我想问的是我的dat文件怎么创建呢?还有文件读取的时候,文件需要放在main.cpp那个文件夹的的根目录下吗,我的事macbook,我只会创建txt文件,我不知道如何把txt转化为dat。。。cpp也可以读取txt文件吗?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-9-12 20:55:04 | 显示全部楼层
superbe 发表于 2019-9-12 18:15
刚看到上面的英文有详细说明,明白了

可不可以稍微把程序改一改,我感觉把这个程序交给老师,,老师一下就能看出来我抄的,有木有其他读取文件中数据的方式呢?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-9-12 22:33:15 | 显示全部楼层
本帖最后由 superbe 于 2019-9-12 22:34 编辑

添加.dat文件在Visual Studio里就可以,跟你添加.ccp源文件的步骤是一样的,只是输入名称时把默认的xxx.cpp改成hw2e.dat,就会在项目文件夹下生成hw2e.dat。VS里运行可以读这个文件。

如果你在命令行窗口里运行的话,把hw2e.dat放在执行文件(不是cpp文件)同一目录下。

代码我再改下吧。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-9-12 23:01:31 | 显示全部楼层
本帖最后由 superbe 于 2019-9-12 23:03 编辑

刚发现上面代码y坐标正负号错了,把polar2Rect函数里theta-90改成90-theta就可以了。
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <iomanip>

#define PI 3.14159

using namespace std;

void polar2Rect(double,double,double&,double&);

int main() {
    ifstream infile("hw2e.dat");
    string line;
    double dx,dy,x=0,y=0;
    if(!infile.is_open()){
        cout<<"cant not open the file"<<'\n';
        return -1; 
    }
    while(getline(infile,line)){
        string b1;
        string b2;
        stringstream ss(line);
        ss>>b1;
        ss>>b2;
        double theta=stod(b1);
        double r = stod(b2);
        if(r<0 || theta<0){
            cout<< "Robot has reached final destination.\n";
        }
        else{
            polar2Rect(r,theta,dx,dy);
            x+=dx; y+=dy;
            cout<<fixed<<setprecision(4);
            cout<< "New robot position (X,Y):"<<"("<<x<<","<<y<<").\n";
        }
    }
    infile.close();

    return 0;
}

void polar2Rect(double r, double theta, double &dx, double &dy){
    theta = (PI*(90-theta))/180;
    dx = cos(theta)*r;
    dy = sin(theta)*r;
}
robot3.PNG
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-9-13 10:40:08 | 显示全部楼层
本帖最后由 丶不离不弃 于 2019-9-13 10:59 编辑
superbe 发表于 2019-9-12 23:01
刚发现上面代码y坐标正负号错了,把polar2Rect函数里theta-90改成90-theta就可以了。


你可以解释下第11行第44行的代码嘛,如果说要定义一个函数,以后都可以这样定义吗,小括号里面的数值都是代表着什么呢,我同学说double& 这个是赋值的,但是不会永久改变数值,我不是特别明白,你能解释下这个嘛?谢谢!
还有第34行可以解释下吗?
还有就是最后的格式化输出可以用left<<setw(4)来写吗?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-9-13 23:18:14 | 显示全部楼层
本帖最后由 superbe 于 2019-9-13 23:20 编辑

11行是函数声明,说明polar2Rect这个函数定义在main函数后面,否则编译找不到polar2Rect。如果函数放在main前就不用声明了。
44行就是polar2Rect函数定义。
double&里的&表示参数是按引用传递,这时形参和实参实际上指向同一地址,polar2Rect里dx,dy的变化导致main函数里dx,dy同时变化。
34行的x,y是用来保存累计横、纵坐标的变量,每次dx,dy变化都累加到x,y上,输出的坐标就是x,y值。
格式改成left<<setw(4),是左对齐并且占4位宽度,实际输出坐标是(5,0)(5,-3)这样的,和说明里的不一样。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-9-15 03:50:20 | 显示全部楼层
本帖最后由 丶不离不弃 于 2019-9-15 04:00 编辑
superbe 发表于 2019-9-13 23:18
11行是函数声明,说明polar2Rect这个函数定义在main函数后面,否则编译找不到polar2Rect。如果函数放在main ...


我想问一下为什么我的文件总是读取不聊了,可能我弄懂clion的CMAKE的运行机制,你可以指导下我该把txt文件放在那里才可以读取出来呢?图片如下帖子所示。

你帮我看一下,我文件昨晚那么晚都读不出来。

你帮我看一下,我文件昨晚那么晚都读不出来。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-9-15 19:06:37 | 显示全部楼层
本帖最后由 superbe 于 2019-9-15 19:13 编辑

hw2e.dat是在项目文件夹下吧,Run菜单-->Edit Configurations,弹出窗口中右侧有一项Working directory,把这一项设置成你的项目文件夹就可以了(可以点后面的文件夹图标设置)。

在CLion里,上面的程序要添加一行#include <cmath>,不能省略。在VS里就没问题。

以前没用过CLion,感觉很难用。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-9-15 22:37:50 | 显示全部楼层
superbe 发表于 2019-9-15 19:06
hw2e.dat是在项目文件夹下吧,Run菜单-->Edit Configurations,弹出窗口中右侧有一项Working directory,把 ...

谢谢啦我解决了,文件夹路径不对。。我要好好学一学这个路径的问题。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-9-16 17:34:23 | 显示全部楼层
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-11-21 01:27

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表