我如何在燃料中读取指令,然后使用来自Infile的参数将函数形状写入外档

How do I read instructions in an infile and then write the function shapes to an outfile using parameters from the infile

本文关键字:函数 参数 Infile 燃料 读取 取指令 然后      更新时间:2023-10-16

,所以我只需要一些指导,以了解如何修复此程序,因此我需要读取一个名为" infile.txt"的文件,而文件内部是描述描述的说明然后应绘制的形状(单个大写字符,即r,t,d,s,e),然后给出char,即应填充形状,然后用int中的列和行数填充。TXT文件看起来像这样:

T & 4
S @ 6
T x 5
R * 5 7
D $ 7
D + 5
R = 4 3
E

现在,我什至不太确定是否可以使用开关语句来完成此操作,因为Ifile被读为字符串。但是后来我对如何从开关语句进行更改感到困惑。无论如何,在读取流动后,我必须输出绘制到折叠件的形状。希望这是有道理的,我超级入门级,几乎不知道我在做什么。所以这是我的代码:

#include <iostream>
#include <fstream>
#include <cstdlib>
using namespace std;

void draw_rect (char out_char, int rows, int columns); // Draws a rectangle shape
void draw_square (char out_char, int rows); //Draws a square shape
void draw_triangle (char out_char, int rows);// Draws a triangle shape
void draw_diamond (char out_char, int rows); // Draws a diamond shape
//void dimension_instructions(char value);
int main()
{
    ofstream outfile;
    ifstream infile;
    int row, col;
    bool exit = false;
    char value;
    char code;
    infile.open("infile.txt");
    outfile.open("outfile.txt");
    if(!infile.good())
    {
        cout << "failed to openn";
    }else
    {
        string buffer;
        while(!infile.eof())
        {
            getline(infile, buffer);
            cout << buffer << endl;
        }
        while(!exit)
        {
            cout << "Enter your shape R for rectangle, T for triangle, D for diamond, S for square, and E to exit" << endl;
            cin >> code;
            switch(code)
            {
            case 'R':
               dimension_instructions(code);
               cin >> value >> row >> col;
               draw_rect(value, row, col);
               break;
            case 'T':
                dimension_instructions(code);
                cin >> value >> row;
                draw_triangle(value, row);
                break;
            case 'D':
                dimension_instructions(code);
                cin >> value >> row;
                draw_diamond(value, row);
                break;
            case 'S':
                dimension_instructions(code);
                cin >> value >> row;
                draw_square(value, row);
                break;
            case 'E':
                cout << "Exiting";
                exit = true;
                break;
            default:
                cout << "Invalid input, try again" << endl;
            }
        }
     infile.close();
    }
    outfile.close();
    return  0;
}
/*void dimension_instructions(char value)
{
    if (value == 'R')
    {
        cout << "Enter your character rows and columns values." << endl;
    }else
    {
        cout << "Enter your character and row values" << endl;
    }
}*/
void draw_diamond (char out_char, int rows)
{
    int space = 1;
    space = rows - 1;
    for (int i = 1; i <= rows; i++)
    {
        for (int k = 1; k <= space; k++)
        {
            cout << " ";
        }
        space--;
        for( int k = 1; k <= 2*i-1; k++)
        {
            cout << out_char;
        }
        cout << endl;
    }
    space = 1;
    for (int i = 1; i <= rows; i++)
    {
       for(int k = 1; k <= space; k++)
       {
           cout << " ";
       }
       space++;
       for(int k = 1; k <= 2*(rows-i)-1; k++)
       {
           cout << out_char;
       }
       cout << endl;
    }
}
void draw_triangle (char out_char, int rows)
{
     for (int i = 0; i < rows; i++)
    {
        for (int j = 0; j <= i; j++)
        {
            cout << out_char;
        }
        cout << endl;
}
}
void draw_square (char out_char, int rows)
{
    for (int i = 0; i < rows; i++)
    {
        for (int i = 0; i < rows; i++)
        {
            cout << out_char;
        }
        cout << endl;
    }
}
void draw_rect (char out_char, int rows, int columns)
{
    for (int i = 0; i < rows; i++)
    {
        for (int i = 0; i < columns; i++)
        {
            cout << out_char;
        }
        cout << endl;
    }
}

好的,根据您的评论,我看到您被卡住了,为什么。(也需要在draw_squaredraw_rect中修复循环变量,如果您尚未完成)。

您的主要问题是不了解如何处理每条不同的输入。当您面对此问题时,您已经正确选择了getline将每行读取到buffer中,但是那呢?这就是stringstream使所有不同的地方。

为什么?两个原因,(1)它允许您使用基本的iostream >>和(2)在需要时逐字化buffer的内容。)令牌如下所示,当您到达行末端时停止(在>>消耗whitespace时使用文件流本身上的>>不可能,并且会很乐意在每个'n'上跳过)

毫无疑问,您的代码确实需要一些重构(一个修复混乱逻辑的奇特词)。

启动不要硬码文件名在您的代码中使用魔术数。使用对main()的参数将文件名传递给您的程序,并在需要时声明常数。还要避免使用不会消耗领先空间的charcin >> a_char;与阅读其他内容一样愉快地阅读' '(空间)。

还适当地范围范围。您不需要声明的所有变量,因此在整个main()中都可以看到它们。在适当的范围中声明/定义它们。

例如:

...
#include <sstream>
...
int main (int argc, char **argv) {  /* don't hardcode filenames */
    ifstream infile;    /* infile and buffer are the only variables */
    string buffer;      /* that need to be scoped at main() */

通过文件名作为参数,只需验证您的用户提供的文件名或在保释之前向他提供使用信息。

    if (argc < 2) {     /* validate at least 1 argument is provided */
        cerr << "error: insufficient input.n"
                "usage: " << argv[0] << " filename.n";
        return 1;
    }

您有参数,现在验证您打开文件以进行阅读:

    infile.open (argv[1]);  /* open filename provided as 1st argument */
    if(!infile.good()) {    /* validate file is open for reading */
        cerr << "failed to open infilen";
        return 1;
    }

现在,您如何控制读取循环的重要变化。getline提供了您所需的一切。只需循环,而getlinebuffer提供了良好的输入,例如

    while (getline(infile, buffer)) {   /* loop reading each line */
        int row, col;               /* remaining variables scoped inside */
        string value, code;         /* your read loop, use strings */
        stringstream ss(buffer);    /* create stringstream from buffer */

现在您正在阅读每一行,并且已经创建了一个从buffer创建了一个stringstream,以从CC_20中解析您的字符 - 除 note> note 如何将value, code声明为string而不是char - 提供了一种简单的方法跳过领先的空格只读取非空格字符。然后,您可以简单地访问所需的角色,例如value[0]

验证您对code

有很好的阅读
        if (!(ss >> code)) {        /* validate code read into string */
            cerr << "error: ss >> code.n";
            break;
        }

那么,这只是重复所需数据读取的相同验证的问题。

        switch (code[0])    /* switch on 1st char of code */
        {
            case 'R':
                if ((ss >> value >> row >> col))    /* validate read */
                    draw_rect (value[0], row, col); /* draw rect */
                else    /* or handle error */
                    cerr << "error: 'R' invalid format '" << buffer << "'n'";
                break;
            case 'T':
                if ((ss >> value >> row))   /* ditto for rest of shapes */
                    draw_triangle(value[0], row);
                else
                    cerr << "error: 'T' invalid format '" << buffer << "'n'";
                break;
            case 'D':
                if ((ss >> value >> row))
                    draw_diamond(value[0], row);
                else
                    cerr << "error: 'D' invalid format '" << buffer << "'n'";
                break;
            case 'S':
                if ((ss >> value >> row))
                    draw_square(value[0], row);
                else
                    cerr << "error: 'S' invalid format '" << buffer << "'n'";
                break;
            case 'E':
                cout << "Exitingn";
                goto exitE;     /* goto to break nested loops / scopes */
                break;
            default:
                cout << "Invalid input, try again" << endl;
        }
    }
    exitE:;     /* the lowly goto provides a simple exit */

除了关闭infile之外(这将自动发生,但手动显示您对接近的考虑并没有伤害)。

NOTE 使用goto而不是使用exit的标志。尽管goto并没有得到太多的按下,但它具有一个宝贵的目的,可以清晰地脱离嵌套环和示波器。请勿使用它跳出功能(longjmp是技术限制),但是它可以极大地简化您的逻辑,以打破嵌套环和跳下几行。(在同一设置中,在错误条件下循环结束时正常执行的过去代码也很有用)

因此,请理解其用途。您可以免费使用标志,但是您可能会在许多设置中找到goto清洁器。

这样,您可以将其完全放置(暂时忽略outfile),与类似的内容:

#include <iostream>
#include <fstream>
#include <sstream>
#include <cstdlib>
using namespace std;
void draw_rect (char out_char, int rows, int columns); // Draws a rectangle shape
void draw_square (char out_char, int rows); //Draws a square shape
void draw_triangle (char out_char, int rows);// Draws a triangle shape
void draw_diamond (char out_char, int rows); // Draws a diamond shape
int main (int argc, char **argv) {  /* don't hardcode filenames */
    ifstream infile;    /* infile and buffer are the only variables */
    string buffer;      /* that need to be scoped at main() */
    if (argc < 2) {     /* validate at least 1 argument is provided */
        cerr << "error: insufficient input.n"
                "usage: " << argv[0] << " filename.n";
        return 1;
    }
    infile.open (argv[1]);  /* open filename provided as 1st argument */
    if(!infile.good()) {    /* validate file is open for reading */
        cerr << "failed to open infilen";
        return 1;
    }
    while (getline(infile, buffer)) {   /* loop reading each line */
        int row, col;               /* remaining variables scoped inside */
        string value, code;         /* your read loop, use strings */
        stringstream ss(buffer);    /* create stringstream from buffer */
        if (!(ss >> code)) {        /* validate code read into string */
            cerr << "error: ss >> code.n";
            break;
        }
        switch (code[0])    /* switch on 1st char of code */
        {
            case 'R':
                if ((ss >> value >> row >> col))    /* validate read */
                    draw_rect (value[0], row, col); /* draw rect */
                else    /* or handle error */
                    cerr << "error: 'R' invalid format '" << buffer << "'n'";
                break;
            case 'T':
                if ((ss >> value >> row))   /* ditto for rest of shapes */
                    draw_triangle(value[0], row);
                else
                    cerr << "error: 'T' invalid format '" << buffer << "'n'";
                break;
            case 'D':
                if ((ss >> value >> row))
                    draw_diamond(value[0], row);
                else
                    cerr << "error: 'D' invalid format '" << buffer << "'n'";
                break;
            case 'S':
                if ((ss >> value >> row))
                    draw_square(value[0], row);
                else
                    cerr << "error: 'S' invalid format '" << buffer << "'n'";
                break;
            case 'E':
                cout << "Exitingn";
                goto exitE;     /* goto to break nested loops / scopes */
                break;
            default:
                cout << "Invalid input, try again" << endl;
        }
    }
    exitE:;     /* the lowly goto provides a simple exit */
    infile.close();
    return  0;
}
void draw_diamond (char out_char, int rows)
{
    int space = 1;
    space = rows - 1;
    for (int i = 1; i <= rows; i++)
    {
        for (int k = 1; k <= space; k++)
        {
            cout << " ";
        }
        space--;
        for( int k = 1; k <= 2*i-1; k++)
        {
            cout << out_char;
        }
        cout << endl;
    }
    space = 1;
    for (int i = 1; i <= rows; i++)
    {
    for(int k = 1; k <= space; k++)
    {
        cout << " ";
    }
    space++;
    for(int k = 1; k <= 2*(rows-i)-1; k++)
    {
        cout << out_char;
    }
    cout << endl;
    }
}
void draw_triangle (char out_char, int rows)
{
    for (int i = 0; i < rows; i++)
    {
        for (int j = 0; j <= i; j++)
        {
            cout << out_char;
        }
        cout << endl;
    }
}
void draw_square (char out_char, int rows)
{
    for (int i = 0; i < rows; i++)
    {
        for (int j = 0; j < rows; j++)
        {
            cout << out_char;
        }
        cout << endl;
    }
}
void draw_rect (char out_char, int rows, int columns)
{
    for (int i = 0; i < rows; i++)
    {
        for (int j = 0; j < columns; j++)
        {
            cout << out_char;
        }
        cout << endl;
    }
}

注意:循环变量i, j固定到draw_squaredraw_rect,似乎是复制/粘贴错误 - 除此之外,没有对您的形状功能进行任何更改)

示例使用/输出

$ ./bin/drawshapes dat/drawshapes.txt
&
&&
&&&
&&&&
@@@@@@
@@@@@@
@@@@@@
@@@@@@
@@@@@@
@@@@@@
x
xx
xxx
xxxx
xxxxx
*******
*******
*******
*******
*******
      $
     $$$
    $$$$$
   $$$$$$$
  $$$$$$$$$
 $$$$$$$$$$$
$$$$$$$$$$$$$
 $$$$$$$$$$$
  $$$$$$$$$
   $$$$$$$
    $$$$$
     $$$
      $
    +
   +++
  +++++
 +++++++
+++++++++
 +++++++
  +++++
   +++
    +
===
===
===
===
Exiting

看事物,让我知道您是否还有其他问题。