丶不离不弃 发表于 2019-9-12 13:53:17

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

本帖最后由 丶不离不弃 于 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 13:55:38

求求各位大神讲解下解题思路,然后用到的许多语句我都不会,能不能讲解下从dat文件中读取数据的各类语句的意思呢?还有一个就是为啥我的dat文件读取不出来呢?macbook怎么创建dat文件呢?谢谢大家

丶不离不弃 发表于 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;
}

superbe 发表于 2019-9-12 17:52:20

M_PI没定义,是3.14吗,还有main函数里dx,dy都没赋初值,再把dx,dy传给polar2Rect有问题吧

superbe 发表于 2019-9-12 18:07:34

你同学的dx,dy是累加计算的,但没赋初值,而你的dx,dy是每次都重新计算一个新值,结果不同,不懂你们的原理,哪个是对的

superbe 发表于 2019-9-12 18:15:56

刚看到上面的英文有详细说明,明白了

superbe 发表于 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;
}

代码修改的地方注释里说明了。我也只能理解到这个程度了。

丶不离不弃 发表于 2019-9-12 20:45:11

superbe 发表于 2019-9-12 19:46
#include
#include
#include


真的是万分感谢,我想问的是我的dat文件怎么创建呢?还有文件读取的时候,文件需要放在main.cpp那个文件夹的的根目录下吗,我的事macbook,我只会创建txt文件,我不知道如何把txt转化为dat。。。cpp也可以读取txt文件吗?

丶不离不弃 发表于 2019-9-12 20:55:04

superbe 发表于 2019-9-12 18:15
刚看到上面的英文有详细说明,明白了

可不可以稍微把程序改一改,我感觉把这个程序交给老师,,老师一下就能看出来我抄的,有木有其他读取文件中数据的方式呢?

superbe 发表于 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文件)同一目录下。

代码我再改下吧。

superbe 发表于 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;
}

丶不离不弃 发表于 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)来写吗?

superbe 发表于 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)这样的,和说明里的不一样。

丶不离不弃 发表于 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文件放在那里才可以读取出来呢?图片如下帖子所示。

superbe 发表于 2019-9-15 19:06:37

本帖最后由 superbe 于 2019-9-15 19:13 编辑

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

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

以前没用过CLion,感觉很难用。

丶不离不弃 发表于 2019-9-15 22:37:50

superbe 发表于 2019-9-15 19:06
hw2e.dat是在项目文件夹下吧,Run菜单-->Edit Configurations,弹出窗口中右侧有一项Working directory,把 ...

谢谢啦我解决了,文件夹路径不对。。我要好好学一学这个路径的问题。

雷蛇 发表于 2019-9-16 17:34:23

{:10_334:}
页: [1]
查看完整版本: 关于从dat文件获取数据控制机器人行走问题(用C++)