简体   繁体   中英

Reverse words of a sentence using stack from c++ standard library

I am trying to reverse words of each sentence using std::stack from the c++ standard library.

The input file contents are:

3
foobar
this is a test
all your base

So the answer should be:

foobar
test a is this
base your all

But instead, the answer is:

foobar
test test test test
base base base base

I cannot figure out why. Following is the code:

#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);  
}

Please don't mix C and C++ this way. It is almost unreadable. Some guidelines:

  • don't use raw char arrays for strings, use: std::string
  • use C++ facility to read lines: std::getline
  • to use the previous function you will need to use a C++ file stream std::ifstream .
  • once you read a line you can use a std::stringstream and a std::string to extract each word from the line.
  • you can then push each word on the stack and then pop to reverse the whole string.

As others say in comments, your code is bad :

  • you use a high level c++ stack, but only store char * in it, when you could use std::string
  • you use C standard library for IO, when you could use C++ library ( std::stringstream would help here)
  • you input is line oriented and you use fscanf instead of fgets (or better getline as your question is tagged c++)

But the actual cause of your error is simply that you are storing a char * in your stack, that always point to the same char array, instead of allocating a new array for each word. So:

  • you find a word in letters
  • you store only the address of letters not its content
  • you erase letters with next word

and your stack contains n copies of the address of letters each pointing to the same array of last word.

You should either:

  • use malloc or strdup to allocate a new array for each word (the C way) - and consistently free each allocated array
  • use std::string , and better a stack<string> (the C++ way) to let the C++ library manage allocation and deallocation for you.

There can be good reasons to use C library functions in a C++ program (size or performance constraints in a program that already uses C code, assignement to do so), but unless it is the case, the high level C++ library is simpler to use with less risk of errors than the low level C one.

TL/DR: If you had used C++ library (getline, std::string, iostream, stringstream, stack) the library itself would have saved you from that error.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM