【问题标题】:How to number input in ascending order?如何按升序编号输入?
【发布时间】:2013-09-08 20:13:03
【问题描述】:

我以文件 input.txt 的形式输入了两列字符串,例如:

string1 string2
string3 string4
etc.

我试图从 0 开始按升序对字符串进行编号,但这样重复的字符串不会被分配新值,而是保留曾经分配给它们的值。 我决定使用 set::find 操作来做到这一点,但我很难让它工作。到目前为止,这是我所拥有的:

int main(int argc, char* argv[]) { 

  std::ifstream myfile ("input.txt");
  std::string line;
  int num = 0;  // num is the total number of input strings

  if (myfile.is_open()) {      
      while(std::getline(myfile, line)) {
          ++num; 
      }
  }

  std::string str1, str1; // strings form input
  int str1Num, str2Num; // numbers assigned to strings

  int i = 0; // used to assign values to strings
  StringInt si;
  std::vector<StringInt> saveStringInts(num);
  std::set<std::string> alreadyCounted(num, 0); 
  std::set<std::string>::iterator sit;

  std::ifstream myfile2 ("input.txt");
  if (myfile2.is_open()) {      
      while(myfile2.good()) {
          // read in input, put it in vars below
          myfile2 >> str1 >> str2;

    // if strings are not already assigned numbers, assign them
    if ((*(sit = alreadyCounted.find(str1)).compare(str1) != 0) { // doesn't work
      str1Num = i++;
      alreadyCounted.insert(str1);
      saveStringInts.push_back(StringInt(str1Num));
    }
    else {
      str1Num = si->getNum(str1);
    }
    if ((*(sit = alreadyCounted.find(str2)).compare(str2) != 0) { 
      str2Num = i++;
      alreadyCounted.insert(str2);
      saveStringInts.push_back(StringInt(str2Num));
    }
    else {
      str2Num = si->getNum(str2);
    }

    // use str1 and str2 in the functions below before the next iteration


    }
  }

不幸的是,我尝试了其他方法,现在完全卡住了。如果您知道如何修复我的代码或可以提出更好的方法来完成我的任务,我将非常感谢您的帮助。

【问题讨论】:

  • 总是测试输入是否成功您尝试读取您的值之后,例如,while (myfile2 &gt;&gt; str1 &gt;&gt; str2) ...
  • 是的,我测试过了,输入成功,我得到了字符串但是不能按升序编号。
  • 按原样,您的代码将处理最后一行输入两次。在你的情况下它可能是无害的,但总的来说它不是。
  • 我应该如何解决它?抱歉,我不太擅长 io。
  • 好吧,我在第一条评论中已经提到过:while (myfile2 &gt;&gt; str1 &gt;&gt; str2) { ... }。有趣的是,您在读取第一个文件时使用了正确的方法。

标签: c++ string c++11 io


【解决方案1】:

您需要将std::set&lt;int&gt;::iterator 与您的集合中的end() 迭代器进行比较,而不是取消对迭代器的引用并将其值与某些东西进行比较!实际上,取消 end() 迭代器是未定义的行为:

if ((*(sit = alreadyCounted.find(str1)).compare(str1) != 0) // WRONG: don't do that!

应该是

if (alreadyCounted.find(str1) != alreadyCounted.end())

... 对于其他字符串也是如此。不过,就我个人而言,我会使用一种不同的技术:当insert() 进入std::set&lt;T&gt; 时,您会得到一对迭代器和一个是否插入对象的指示符。后者与当前集合的大小一起给出下一个值,例如:

bool result = alreadyCounted.insert(str1).second;
strNum1 = result? alreadyCounted.size() - 1: si->getNum(str1);

【讨论】:

  • 谢谢,我会努力解决的。
  • 很抱歉,我一直在尝试理解您提供的“std::pair<...>
  • 结果应该只是一个布尔值,因为那是alreadyCounted.insert(str1).second 将返回的?
  • @LachlanEaston:是的,我会纠正的。不知何故,我开始认为可以从这个集合中获得计数,但无论如何它不能。
  • @Napalidon:set.find(x) 的定义是将迭代器返回到与x 匹配的set 元素,或者,如果没有这样的元素,则返回set.end()。它没有隐藏任何东西:如果你有一个包含n 元素的范围,那么就有n + 1 有意义的位置可以讨论:指向每个n 元素并在末尾。然而,set.end() 并不指向一个元素,也就是说,它不能被取消引用。
猜你喜欢
  • 1970-01-01
  • 2022-12-31
  • 1970-01-01
  • 2021-12-13
  • 1970-01-01
  • 1970-01-01
  • 2019-05-14
  • 1970-01-01
  • 2018-03-16
相关资源
最近更新 更多