我如何在燃料中读取指令,然后使用来自Infile的参数将函数形状写入外档
How do I read instructions in an infile and then write the function shapes to an outfile using parameters from the infile
,所以我只需要一些指导,以了解如何修复此程序,因此我需要读取一个名为" 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_square
和draw_rect
中修复循环变量,如果您尚未完成)。
您的主要问题是不了解如何处理每条不同的输入。当您面对此问题时,您已经正确选择了getline
将每行读取到buffer
中,但是那呢?这就是stringstream
使所有不同的地方。
为什么?两个原因,(1)它允许您使用基本的iostream >>
和(2)在需要时逐字化buffer
的内容。)令牌如下所示,当您到达行末端时停止(在>>
消耗whitespace时使用文件流本身上的>>
不可能,并且会很乐意在每个'n'
上跳过)
毫无疑问,您的代码确实需要一些重构(一个修复混乱逻辑的奇特词)。
启动不要硬码文件名或在您的代码中使用魔术数。使用对main()
的参数将文件名传递给您的程序,并在需要时声明常数。还要避免使用不会消耗领先空间的char
。cin >> 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
提供了您所需的一切。只需循环,而getline
为buffer
提供了良好的输入,例如
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_square
和draw_rect
,似乎是复制/粘贴错误 - 除此之外,没有对您的形状功能进行任何更改)
示例使用/输出
$ ./bin/drawshapes dat/drawshapes.txt
&
&&
&&&
&&&&
@@@@@@
@@@@@@
@@@@@@
@@@@@@
@@@@@@
@@@@@@
x
xx
xxx
xxxx
xxxxx
*******
*******
*******
*******
*******
$
$$$
$$$$$
$$$$$$$
$$$$$$$$$
$$$$$$$$$$$
$$$$$$$$$$$$$
$$$$$$$$$$$
$$$$$$$$$
$$$$$$$
$$$$$
$$$
$
+
+++
+++++
+++++++
+++++++++
+++++++
+++++
+++
+
===
===
===
===
Exiting
看事物,让我知道您是否还有其他问题。
- static_assert在宏中,但也可以扩展到可以用作函数参数的东西
- C++中的高效循环缓冲区,它将被传递给C样式数组函数参数
- 当从函数参数中的临时值调用复制构造函数时
- 如何从"decltype()"获取函数参数的数量<funtion>?
- 如何将lambda作为模板类的成员函数参数
- 模板参数推导失败,函数参数/参数不匹配
- 如何在C++中将迭代器作为函数参数传递
- 将函数参数"const char*"转换为"std::string_view"是
- C++ 如何将数组值解压缩为函数参数
- 主函数参数的属性
- 具有两个间接寻址运算符 (C++) 的函数参数的用途
- "Warning: Comma within array index expression"但逗号分隔函数参数
- 如何定义在用作函数参数时工作的类模板的转换
- 将函数参数完美转发到函数指针:按值传递呢?
- 为什么我不能将引用作为 std::async 的函数参数传递
- 什么..(省略号)作为函数原型中唯一的函数参数,C++?
- 是否可以就地构造一个固定大小的数组作为函数参数?
- 接受模板作为函数参数
- 将成员函数作为构造函数参数调用时出错 "Variable is not a type name"
- Arduino 函数参数