C++ 如何避免阅读文本文件中的注释?

C++ 如何避免阅读文本文件中的注释?,c++,parsing,input,output,readfile,C++,Parsing,Input,Output,Readfile,目前,我已使用此代码成功地将一些介于0到10之间的随机数写入我的文件(下面只是一些示例代码来演示此问题): 当我从该文件读取数据并输出到另一个文件时,会出现问题: int type; while (afile >> type) { if(type == 0) { afile >> .........; .......... } else if(type == 1) {.........}

目前,我已使用此代码成功地将一些介于0到10之间的随机数写入我的文件(下面只是一些示例代码来演示此问题):

当我从该文件读取数据并输出到另一个文件时,会出现问题:

int type;

while (afile >> type)
{
    if(type == 0) 
    {
        afile >> .........;
        ..........
    } 
        else if(type == 1) {.........}
        else if(type == 2) {.........}
    }       
}
...................................... 

我的输出文件在第一行之后停止读取,因为它也读取了要处理的无效数据的注释,如果我删除了注释,则一切正常。那么我该如何克服这种情况呢?谢谢。

有几种方法可以做到这一点

找到报价后跳过行的其余部分(更快)

基本上,这里要做的是在循环中逐行读取文件。当您点击两个字符“/”时。你可以叫“休息”,然后跳到下一行

一些未经测试的伪代码:

while(line = file.getLine()){
  loopChars = sizeof(line);
  for(x = 0; x < loopChars; x++) {
    char currentChar = line[x];
    if(x+1 < loopChars){
       char nextChar = line[x+1];
    } else {
       char nextChar = '';
    }

    if(nextChar == "/" && currentChar == "/"){
      // Go to next line 
      break; 
    } else {
      // Do your normal processing here
    }
  }
}
while(line=file.getLine()){
loopChars=sizeof(行);
对于(x=0;x
先删除引号(较慢)

下面是一个从文件中删除引号(一行“/”和多行“/**/”)的解决方案。基本上,在开始读取数字数据之前,您会对正在处理的文件运行此操作

#包括
#包括
使用名称空间std;
int main(){
河流充填;
字符串文件名;
出流孔的直径;
字符c1,c2;
bool-isInsideComment=false;
cout>文件名;
infle.open(filename.c_str());
if(infle.fail()){

你有几个合理的选择:

  • 将整行内容读入
    std::string
    ,扫描并删除任何注释,然后从剩下的内容中创建
    std::istringstream
    ,并从中提取非注释值

  • 在读取值之前,请使用std::ws
afile.peek()
查看下一个字符是否为
'/'
:如果是,请跳过,直到到达换行符

前者是一种在C++中使用的有用的技术(当你想用数据问题报告行数时),看起来像这样:

if (std::ifstream in(filename))
{
    std::string line;
    while (getline(in, line))
    {
        std::string::size_type n = line.find("//");
        if (n != std::string::npos)
            line.erase(n);

        std::istringstream iss(line);

        int atype;
        while (iss >> atype)
            ...etc...
    }

正如我所见,Tony D已经提供了一个合理的答案,但我想我也应该添加一个自己的代码,因为我已经编写并测试了它

下面对于任何一个讲C++的人来说都是很清楚的,它基本上是托尼提出的,但是有一个扭曲——用一行一行的数据,利用<代码> STD::StrugStule,但是也利用了数据OP的二进制性质。数据既有有效的整数,也有注释。r是否为有效整数。因此,在下面的代码中,当无法将数据从流有效转换为整数时,该行的其余部分将被视为注释。编辑:……实际上,虽然这是一个有点有效的解决方案,但我修改了代码,使其包含一种更为合理的方法—跳过注释的方法(用

#
/
表示,以显示两种方法)但仍然让我们决定对格式错误的值执行什么操作。这不允许
45fubar
作为
45
传递,然后是坏
fubar
,这是前面代码的问题,但允许正确解释
45//comment

我仍然认为直接删掉
\/\/.*?
是一个更好的方法。不过,这个答案的要点是有点不同

#包括
#包括
#包括
#包括
#包括
#包括
#包括
无效写入(std::ostream&output,int行){
对于(int i=0;i输出您需要检查它正在处理的字符\数据是否等于“\”。如果发生这种情况,它将立即中断或进入下一行您使用的
!infle.eof()
不可靠…它只能保证在尝试读取文件结尾后设置,因此如果
infle.get(c1)
读取一个字符,并且文件中没有其他字符,它仍然没有设置
eof
,并将继续执行
infle.get(c2);
操作失败,在尝试将
c2
与“*”和“/”进行比较之前,保持
c2
不变(可能未初始化)(可能未定义的行为)很可能调用
outfile.put(c2);
.Yep,这可能会导致软件出现错误,当你看到
而(!stream.eof())
时,你应该开始非常小心了。;)很好的建议Xupicor.BTW,如果解析数字后流不在
eof()
,你可以使用
ss.clear();
然后
ss.get()='/'&&ss.get()=='/'
以确保有评论……感谢您的努力,但我现在还不熟悉vector,因为我只是一个新手。我将来会回到您的解决方案,因为它看起来非常复杂!:)@Resolution:
std::vector
只是标准模板库(STL)中的一个标准容器你可以把它当作一个动态分配内存的数组,代码中的所有内容都符合标准C++,虽然有些是C++ 11专用的,比如尼斯for for循环。)@ Tyyd你找到的解决方案<代码> //<代码>,擦除后面的内容,我几乎要做的是——除非一个包含它的字符串这可能是一个格式良好的数据,但它看起来不像。我这样写的全部目的是利用数据的性质,并成为一个与你的答案稍有不同的答案。;)不过……请稍后查看编辑。
while(line = file.getLine()){
  loopChars = sizeof(line);
  for(x = 0; x < loopChars; x++) {
    char currentChar = line[x];
    if(x+1 < loopChars){
       char nextChar = line[x+1];
    } else {
       char nextChar = '';
    }

    if(nextChar == "/" && currentChar == "/"){
      // Go to next line 
      break; 
    } else {
      // Do your normal processing here
    }
  }
}
#include <iostream>
#include <fstream>
using namespace std;

int main (){
    ifstream infile;
    string filename;
    ofstream outfile;
    char c1, c2;
    bool isInsideComment = false;

    cout << "Please input file name (to remove comments from): ";
    cin >> filename;

    infile.open (filename.c_str());
    if (infile.fail()) {
        cout << "nInvaild file name.n";
        return 1;
    }
    outfile.open(("out_"+filename).c_str());

    infile.get (c1);
    while (!infile.eof()) {
        if ((c1 == '/') && (!isInsideComment)) {
            infile.get (c2);
            if (c2 == '*')
            isInsideComment = true;
            else if ((c1 == '/') && (c2 == '/'))
            isInsideComment = true;
            else {
                outfile.put (c1);
                outfile.put (c2);
            }
        }

        else if ( (c1 == '*') && isInsideComment) {
            infile.get (c2);
            if (c2 == '/')
            isInsideComment = false;
            else if ((c1 == 'n') && isInsideComment)
            isInsideComment = false;
        }
        else if (!isInsideComment)
        outfile.put (c1);
        infile.get (c1);
    }
    infile.close();
    outfile.close();
}
if (std::ifstream in(filename))
{
    std::string line;
    while (getline(in, line))
    {
        std::string::size_type n = line.find("//");
        if (n != std::string::npos)
            line.erase(n);

        std::istringstream iss(line);

        int atype;
        while (iss >> atype)
            ...etc...
    }
$ ./test.exe < data > data
50 44 92 43 97
26 32 54
30 91
93 4
$ cat data
50      44      92      43      97 // 5 numbers
26      32      54 // 3 numbers
30      91 // 2 numbers
93      4 // 2 numbers


$ ./test.exe < data2 > dump
Unexpected symbol: 'i91'
Unexpected symbol: '4i'
Unexpected symbol: 'lol'
Unexpected symbol: 'numbers'
50 44 92 43 97
26 32 54
30
93 3 2
7337
7337
$ cat data2
50      44      92      43      97 // 5 numbers
26      32      54 # 3 numbers
30      i91 // 2 numbers
93      4i      lol 3 2 numbers
7337//test comment
7337#test comment 2