【问题标题】:String Compare C++字符串比较 C++
【发布时间】:2013-06-19 15:23:44
【问题描述】:

我正在尝试编写一个程序来读取由 4 列组成的文本文件(时间戳、登录/注销、正在注销/登录的内容、用户注销)

    15:47:10 OUT: "RS5K_700.EXE" SYSTEM@ALNWSPCNTRCTR1
    15:47:10 IN: "RS5K_700.EXE" SYSTEM@ALNWSPCNTRCTR1
    16:07:48 OUT: "RS5K_700.EXE" CONHorodeski@ALNWSPCNTRCTR1
    16:10:15 OUT: "RS5K_700.EXE" CONHorodeski@ALNWSPCNTRCTR1
    16:11:28 IN: "RS5K_700.EXE" CONHorodeski@ALNWSPCNTRCTR1
    16:46:34 IN: "RS500.EXE" mlulchak@alnsvpmillterm
    17:01:49 OUT: "RS500.EXE" mlulchak@alnsvpmillterm
    17:49:32 IN: "RS500.EXE" mlulchak@alnsvpmillterm
    9:30:28 OUT: "RS5K_700.EXE" CONHorodeski@ALNWSPCNTRCTR1
    15:39:32 OUT: "RS5K_700.EXE" CONHorodeski@ALNWSPCNTRCTR1
    15:40:10 OUT: "RS5K_700.EXE" CONHorodeski@ALNWSPCNTRCTR1
    15:40:31 OUT: "RS5K_700.EXE" CONHorodeski@ALNWSPCNTRCTR1
    0:10:59 IN: "RS5K_700.EXE" CONHorodeski@ALNWSPCNTRCTR1
    1:28:20 IN: "RS5K_700.EXE" CONHorodeski@ALNWSPCNTRCTR1
    1:28:38 IN: "RS5K_700.EXE" CONHorodeski@ALNWSPCNTRCTR1
    1:28:41 IN: "RS5K_700.EXE" CONHorodeski@ALNWSPCNTRCTR1

我希望该程序对列表进行排序,并且只写入未重新登录的行(即,如果已注销,则列表中应该稍后再登录。列表是有序的,但时间不多,所以不用担心.)

这是我目前所拥有的:

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

    int main()
    {
    ifstream inFile;
    string array[2000][4];

    int count, i, j, h;
    inFile.open("test.rtf");

    if(!inFile){
    cout << "Unable to open file" << endl;
    exit(1);
    }
    i=0;
    while(!inFile.eof()) {
    inFile>> array[i][0]   >>array[i][1]   >>array[i][2] >>array[i][3];
    i++;
            }
        inFile.close();


    j=0;
    h=i;

    while(j<i-1)
    {   
cout << j;
count=j+1;

 if (array[j][1]== "OUT:")
 {
     while(count < i)
     {
         if(array[count][1]=="IN:" && array[count][2]==array[j][2] && array[count][3]==array[j][3])
         {
            for (int k = count; k < i; k++)
            {
            array[k][0] = array[k+1][0]; 
            array[k][1] = array[k+1][1];
            array[k][2] = array[k+1][2];
            array[k][3] = array[k+1][3];
            }
        array[i-1][0] = " ";
            array[i-1][1] = " ";
            array[i-1][2] = " ";
            array[i-1][3] = " ";
            i--;
            for (int k = j; k < i; k++){
            array[k][0] = array[k+1][0]; 
            array[k][1] = array[k+1][1];
            array[k][2] = array[k+1][2];
            array[k][3] = array[k+1][3];
            }
            array[i-1][0] = " ";
            array[i-1][1] = " ";
            array[i-1][2] = " ";
            array[i-1][3] = " ";

            i--;
            count=i;

         }
         else if (array[j][1]== "IN:")
 {
     for (int k = j; k < i; k++)
     {
        array[k][0] = array[k+1][0]; 
        array[k][1] = array[k+1][1];
        array[k][2] = array[k+1][2];
        array[k][3] = array[k+1][3];            
     }
        array[i-1][0] = " ";
        array[i-1][1] = " ";
        array[i-1][2] = " ";
        array[i-1][3] = " ";
        j++;
        i--;
 }
         else if (count=i)
         {
             j++;

         }

         else
         {
             count++;
         }

     }

 }
 else if (array[j][1]== "IN:")
 {
     for (int k = j; k < i; k++)
     {
        array[k][0] = array[k+1][0]; 
        array[k][1] = array[k+1][1];
        array[k][2] = array[k+1][2];
        array[k][3] = array[k+1][3];            
     }
        array[i-1][0] = " ";
        array[i-1][1] = " ";
        array[i-1][2] = " ";
        array[i-1][3] = " ";
        j++;
        i--;
 }

    }




    h=i;
    i=0;
    ofstream outFile;
    outFile.open("test2.rtf");
    while(h!=0){
    outFile << array[i][0] << " " << array[i][1] << " " <<array[i][2] << " "  <<array[i][3]<<endl;
    i++;
    h--;                
    }
    inFile.close();

    return 0;
    }

任何想法都会很好,因为我的想法已经用完了:)

【问题讨论】:

  • 一般来说,不要使用while (!file.eof()),因为直到读取操作失败后才会设置EOF标志。相反,例如while (inFile &gt;&gt; array[i][0] &gt;&gt; ...)
  • 并且不要使用硬编码数组,而是使用std::vector。在这种情况下,std::vector 可能是 std::array
  • 但是 (!file.eof()) 工作正常。在注释掉大部分程序时,我可以完美地重现该列表。
  • 但它不能正常工作,因为它会循环一对多,从而将索引i 增加到超出实际数据的一个。
  • 好电话,没想到。

标签: c++ arrays string text-files


【解决方案1】:

我首先将输入的每一行转换为一个逻辑记录。然后我会为每个“已注销”记录插入一条记录到map,并删除每个“已登录”记录的匹配记录。根据您正在做什么(如果有的话),set 可能比map 更容易一些。

如果您有当前未注销的项目的“已登录”记录,则表明输入存在问题。

完成后,写出map(或set)中的所有项目。这些是已退出但未重新登录的那些。

编辑:代码看起来像这样:

#include <string>
#include <set>
#include <algorithm>
#include <fstream>
#include <sstream>
#include <iostream>

struct record {
    std::string time;
    std::string inout;
    std::string item;
    std::string user;

    bool operator<(record const &other) const { 
        return item < other.item;
    }
};

std::istream &operator>>(std::istream &is, record &r) { 
    std::string line;
    std::getline(is, line);
    std::stringstream buffer(line);

    buffer >> r.time >> r.inout >> r.item >> r.user;
    return is;
}

std::ostream &operator<<(std::ostream &os, record const &i) { 
    return os << i.item << "\t" << i.user;
}

int main() {
    std::set<record> items;
    record temp;
    std::ifstream in("test.rtf");

    while (in >> temp) {
        if (temp.inout == "OUT:")
            items.insert(temp);
        else
            items.erase(temp);
    }

    for (auto const & i : items) 
        std::cout << i << "\n";
}

【讨论】:

  • 你有点迷路了,杰瑞,我真的只熟悉 C++ 中的简单语法。
  • 这看起来可以工作,但经过测试,当使用更长的列表时,它似乎有大约 8 个项目的错误。另外我想写时间戳,我猜“out:”只是为了验证它是否选择了正确的行。我将不得不尝试找出您的代码以找到错误,否则这是一个开始:)。
  • @IanFolk:最可能的问题是它假设输入中唯一的空格是在字段之间。对于包含空格的文件名(例如),您必须使用匹配的引号来获取整个文件名。
【解决方案2】:

看看这个解决方案来解决您的问题,我建议您使用 stl 排序算法对输出进行排序并使用结构来存储数据。

#include <algorithm>
#include <string>
#include <vector>
#include <iostream>
#include<fstream>
using namespace std;

#define MAX 1005

struct record{
    string A,B,C,D;
    record(string A, string B, string C, string D) :
        A(A), B(B), C(C), D(D) {}

    bool operator < (const record& o) const
    {
        string tmp1 = A + " " + B + " " + C + " " + D;
        string tmp2 = o.A + " " + o.B + " " + o.C + " " + o.D;
        return (tmp1 < tmp2);
    }
};

int main() {
    string A,B,C,D;
    vector<record> my_vect;
    vector<record>::iterator it;

    ifstream inFile;
    inFile.open("test1.rtf");

    while(inFile >> A >> B >> C >> D) {
        if(B == "OUT:")
            my_vect .push_back( record(A,B,C,D) );
    }

    inFile.close();

    sort(my_vect.begin(), my_vect.end());

    ofstream outFile;
    outFile.open("test2.rtf");
    for(it = my_vect.begin(); it != my_vect.end(); ++it) {
        outFile << (*it).A << " " << (*it).B << " " << (*it).C << " " << (*it).D << endl;
    }
    outFile.close();

    return 0;
}

这个算法的输出是:

15:39:32 OUT: "RS5K_700.EXE" CONHorodeski@ALNWSPCNTRCTR1
15:40:10 OUT: "RS5K_700.EXE" CONHorodeski@ALNWSPCNTRCTR1
15:40:31 OUT: "RS5K_700.EXE" CONHorodeski@ALNWSPCNTRCTR1
15:47:10 OUT: "RS5K_700.EXE" SYSTEM@ALNWSPCNTRCTR1
16:07:48 OUT: "RS5K_700.EXE" CONHorodeski@ALNWSPCNTRCTR1
16:10:15 OUT: "RS5K_700.EXE" CONHorodeski@ALNWSPCNTRCTR1
17:01:49 OUT: "RS500.EXE" mlulchak@alnsvpmillterm
9:30:28 OUT: "RS5K_700.EXE" CONHorodeski@ALNWSPCNTRCTR1

【讨论】:

  • 没有必要使用 map,因为这样每次插入和获取数据都会带来 O(log n) 的不必要复杂性。您只需要使用 stl 中的排序算法对正确的列表进行一次排序。
  • 看起来您只是将所有“退出”都写入了一个文件。我需要消除所有匹配 'IN:' 的 'OUTS:'
【解决方案3】:

我会使用mapset 来得到你想要的:

#include <iostream>
#include <string>
#include <map>
#include <set>

int main(int, char**) {
  using namespace std;

  string time, in_out, exe, user;
  map<string,int> out;

  while( cin >> time >> in_out >> exe >> user ) {
    if( in_out == "OUT:" ) 
      out[user]++;
    else
      out[user]--;
    if( out[user] == 0 )
      out.erase(user);
  }

  set<string> ordered;
  for( auto& s: out ) {
    ordered.insert(s.first);
  }
  for( auto& s: ordered ) {
    cout << s << endl;
  } 

  return 0;
} 

样本输入的输出是:

CONHorodeski@ALNWSPCNTRCTR1
mlulchak@alnsvpmillterm

(第一个在 16:07 和 16:10 登出两次,但在 16:11 只登入一次,第二个在 17:49 登入,从未登出)

【讨论】:

  • 稍微处理一下,它似乎过滤了列表,但没有保持正确的行。你能解释一下你的淘汰过程吗?
  • 如果程序看到OUT:,它会为每个用户增加一个计数器;如果它看到IN:,它会递减它(if(int_out == "OUT:") out[user]++; else out[user]--; 部分。然后它会获取非零项目(在没有重新登录的情况下注销,反之亦然)并按顺序打印它们(这就是 @ 987654328@ 用于)。我编辑了答案以显示输出及其原因。
猜你喜欢
  • 2021-11-19
  • 2016-02-08
  • 2013-11-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多