使用来自c ++标准库的堆栈反转一个句子的单词

时间:2015-10-19 13:16:38

标签: c++ stack

我正在尝试使用c ++标准库中的std::stack来反转每个句子的单词。

输入文件内容为:

  

3
  foob​​ar的
  这是一个测试   你所有的基地

所以答案应该是:

  

foobar的
  测试a是这个   以你的全部为基础

但相反,答案是:

  

foobar的
  试验测试试验
  基地基地

我无法弄清楚原因。以下是代码:

#include <cstdio>
#include <cstdlib>
#include <fstream>
#include <cstring>
#include <stack>

using namespace std;

int main() {
  FILE *fp, *fpo;
  fp = fopen("test.in", "r");
  int tests;
  fscanf(fp, "%d", &tests);
  char ch;
  fscanf(fp, "%c", &ch); 
  for (int i = 0; i < tests; i++) {
    char *letters;
    letters = (char*)calloc(1000, sizeof(char));
    stack <char*> words;
    fscanf(fp, "%s", letters); fscanf(fp, "%c", &ch);

    while (ch != '\n' && ch != EOF) {
      words.push(letters); printf(" %s", words.top());
      fscanf(fp, "%s", letters); fscanf(fp, "%c", &ch);
    }
    words.push(letters); printf(" %s", words.top());
    printf("  --  ");
    while (!words.empty()) {
      printf(" %s", words.top());
      words.pop();
    }
    printf("\n");
    free(letters);
  }
  fclose(fp);  
}

2 个答案:

答案 0 :(得分:4)

请不要以这种方式混合 C C ++ 。这几乎是不可读的。一些指导原则:

  • 不要对字符串使用原始字符数组,请使用:std::string
  • 使用C ++工具读取行:std::getline
  • 要使用上一个功能,您需要使用C ++文件流std::ifstream
  • 读完一行后,您可以使用std::stringstreamstd::string从该行中提取每个单词。
  • 然后你可以将每个单词推到堆栈上,然后弹出以反转整个字符串。

答案 1 :(得分:1)

正如其他人在评论中所说,您的代码错误

  • 您使用高级c ++堆栈,但只能存储char *,当您可以使用std::string
  • 您可以使用C标准库进行IO,当您可以使用C ++库时(std::stringstream会对此有所帮助)
  • 您的输入是面向行的,您使用fscanf代替fgets(或更好getline,因为您的问题被标记为c ++)

但是,错误的实际原因只是您在堆栈中存储char *,它总是指向相同的char数组,而不是为每个单词分配一个新数组。所以:

  • 你在字母中找到一个单词
  • 您只存储字母其内容
  • 的地址
  • 你用下一个字删除字母

并且您的堆栈包含n个字母地址的副本,每个字母指向最后一个单词的相同数组。

你应该:

  • 使用malloc或strdup为每个单词分配一个新数组(C路) - 并始终释放每个分配的数组
  • 使用std::string,更好地使用stack<string>(C ++方式)让C ++库为您管理分配和释放。

在C ++程序中使用C库函数是有充分理由的(在已经使用C代码的程序中的大小或性能约束,这样做的分配),但除非是这种情况,否则高级C ++库是使用起来更简单,错误风险低于低等级C语言。

TL / DR:如果您使用过C ++库(getline,std :: string,iostream,stringstream,stack),那么库本身可以帮助您避免该错误。