C++ std::stringstream 从字符串中读取 int 和字符串

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1883056/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 21:28:55  来源:igfitidea点击:

std::stringstream to read int and strings, from a string

c++stringstringstream

提问by Val

I am programming in C++ and I'm not sure how to achieve the following:

我正在用 C++ 编程,但不确定如何实现以下目标:

I am copying a file stream to memory (because I was asked to, I'd prefer reading from stream), and and then trying to access its values to store them into strings and int variables.

我正在将文件流复制到内存(因为我被要求这样做,我更喜欢从流中读取),然后尝试访问其值以将它们存储到字符串和 int 变量中。

This is to create an interpreter. The code I will try to interpret is (ie):

这是为了创建一个解释器。我将尝试解释的代码是(即):

10 PRINT A
20 GOTO 10

This is just a quick example code. Now the values will be stored in a "map" structure at first and accessed later when everything will be "interpreted". The values to be stored are:

这只是一个快速的示例代码。现在,这些值将首先存储在“映射”结构中,稍后在“解释”所有内容时进行访问。要存储的值是:

int lnum // line number

int lnum // 行号

string cmd // command (PRINT and GOTO)

string cmd // 命令(PRINT 和 GOTO)

string exp // expression (A and 10 in this case but could hold expressions like (a*b)-c )

string exp // 表达式(在本例中为 A 和 10,但可以包含 (a*b)-c 之类的表达式)

question is given the following code, how do I access those values and store them in memory? Also the exp string is of variable size (can be just a variable or an expression) so I am not sure how to read that and store it in the string.

问题给出了以下代码,我如何访问这些值并将它们存储在内存中?此外 exp 字符串的大小可变(可以只是一个变量或表达式),所以我不知道如何读取它并将其存储在字符串中。

code:

代码:



#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>
#include <cstring>
#include <map>
#include <sstream>

using namespace std;

 #include "main.hh"


int main () 
{
    int lenght;
    char *buffer;

// get file directory
    string dir;
    cout << "Please drag and drop here the file to interpret: ";
    getline (cin,dir);
    cout << "Thank you.\n";
    cout << "Please wait while your file is being interpreted.\n \n";

// Open File
    ifstream p_prog;
    p_prog.open (dir.c_str());

// Get file size
    p_prog.seekg (0, ios::end);
    lenght = p_prog.tellg();
    p_prog.seekg(0, ios::beg);

// Create buffer and copy stream to it
    buffer = new char[lenght];
    p_prog.read (buffer,lenght);
    p_prog.close();

// Define map<int, char>
    map<int, string> program;
    map<int, string>::iterator iter;


/***** Read File *****/
    int lnum; // line number
    string cmd; // store command (goto, let, etc...)
    string exp; // to be subst with expr. type inst.

//  this is what I had in mind but not sure how to use it properly
//  std::stringstream buffer;
//  buffer >> lnum >> cmd >> exp;

    program [lnum] = cmd; // store values in map




// free memory from buffer, out of scope
    delete[] buffer;
    return 0;
}

I hope this is clear.

我希望这很清楚。

Thank you for your help.

感谢您的帮助。

Valerio

瓦莱里奥

回答by pestilence669

You can use a std::stringstreamto pull tokens, assuming that you already know the type.

std::stringstream假设您已经知道类型,您可以使用 a来拉取令牌。

For an interpreter, I'd highly recommend using an actual parser rather than writing your own. Boost's XPressivelibrary or ANTLRwork quite well. You can build your interpreter primitives using semantic actions as you parse the grammar or simply build an AST.

对于解释器,我强烈建议使用实际的解析器,而不是自己编写。Boost 的XPressive库或ANTLR工作得很好。您可以在解析语法或简单地构建 AST 时使用语义操作构建解释器原语。

Another option would be Flex & Bison. Basically, these are all tools for parsing pre-defined grammars. You can build your own, but prepare for frustration. Recursively balancing parentheses or enforcing order of operations (divide before multiply, for example) isn't trivial.

另一种选择是 Flex & Bison。基本上,这些都是解析预定义文法的工具。你可以建立自己的,但要准备好受挫。递归平衡括号或强制执行操作顺序(例如,在乘法之前除法)并非易事。

The raw C++ parsing method follows:

原始的 C++ 解析方法如下:


#include <sstream>
#include <string>

// ... //

istringstream iss(buffer);
int a, b;
string c, d;

iss >> a;
iss >> b;
iss >> c;
iss >> d;

回答by asveikau

The way something like this can be done (especially the arithmetic expression part that you alluded to) is:

可以完成这样的事情的方式(尤其是你提到的算术表达式部分)是:

  • Write some code that determines where a token ends and begins. For example 5or +would be called a token. You might scan the text for these, or common separators such as whitespace.
  • Write up the grammar of the language you're parsing. For example you might write:
  • 编写一些代码来确定令牌在哪里结束和开始。例如5+将被称为令牌。您可以扫描这些文本或常用分隔符(如空格)。
  • 写下你正在解析的语言的语法。例如你可能会写:
    expression -> value
    expression -> expression + expression
    expression -> expression * expression
    expression -> function ( expression )
    expression -> ( expression )
    expression -> value
    expression -> expression + expression
    expression -> expression * expression
    expression -> function ( expression )
    expression -> ( expression )

Then based on this grammar you would write something that parses tokens of expressions into trees.

然后根据这个语法,你会写一些将表达式的标记解析为树的东西。

So you might have a tree that looks like this (pardon the ASCII art)

所以你可能有一个看起来像这样的树(原谅 ASCII 艺术)

            +
          /   \
         5     *
              / \
             x   3
            +
          /   \
         5     *
              / \
             x   3

Where this represents the expression 5 + (x * 3). By having this in a tree structure it is really easy to evaluate expressions in your code: you can recursively descend the tree, performing the operations with the child nodes as arguments.

其中 this 表示表达式 5 + (x * 3)。通过在树结构中使用它,可以很容易地评估代码中的表达式:您可以递归地下降树,以子节点作为参数执行操作。

See the following Wikipedia articles:

请参阅以下维基百科文章:

Or consult your local computer science department. :-)

或咨询您当地的计算机科学部门。:-)

There are also tools that will generate these parsers for you based on a grammar. You can do a search for "parser generator".

还有一些工具可以根据语法为您生成这些解析器。您可以搜索“解析器生成器”。

回答by Martin York

Don't do the dynamic allocation of the buffer explicitly use a vector.
This makes memory management implicit.

不要显式使用向量进行缓冲区的动态分配。
这使得内存管理隐含。

// Create buffer and copy stream to it   
std::vector<char>   buffer(lenght);
p_prog.read (&buffer[0],lenght);
p_prog.close();

Personally I don't explicitly use close() (unless I want to catch an exception). Just open a file in a scope that will cause the destructor to close the file when it goes out of scope.

我个人没有明确使用 close() (除非我想捕获异常)。只需在一个范围内打开一个文件,当它超出范围时,析构函数就会关闭文件。

回答by Stu

This might be of help:

这可能有帮助:

http://oopweb.com/CPP/Documents/CPPHOWTO/Volume/C++Programming-HOWTO-7.html

http://oopweb.com/CPP/Documents/CPPHOWTO/Volume/C++Programming-HOWTO-7.html

Especially section 7.3.

特别是第 7.3 节。

You might be better off just <<'ing the lines in rather than the seeking and charbuffer route.

您最好只使用 <<'ing 行而不是搜索和字符缓冲区路由。