0

Why my program is printing incorrect values, not the supplied values? Any help would be much appreciated.

Data

title1=q, year1=1, title2=w, year2=2

Code

#include <iostream>
#include <string>
#include <sstream>
#include <vector>
using namespace std;
    
    
int getnumber ();

struct movies_t {
  string title;
  int year;
};

void printmovie (movies_t films);

int main ()
{
    
  int z=getnumber ();
  cout << "You will have to provide data for " << z << " films.\n";
  
  //movies_t films [z];
  vector<movies_t> films(z);
    
  string mystr;
  int n;

  for (n=0; n<z; n++)
  {
    cout << "Enter title: ";
    getline (cin,films[n].title);
    cin.ignore();
    cout << "Enter year: ";
    getline (cin,mystr);
    cin.ignore();
    stringstream(mystr) >> films[n].year;
    
  }

  cout << "\nYou have entered these movies:\n";
  for (n=0; n<z; n++)
    printmovie (films[n]);
  return 0;
}

void printmovie (movies_t films)
{
  movies_t * pmovie;
  pmovie = &films;

  cout << pmovie->title;
  cout << " (" << films.year << ")\n";
}

int getnumber ()
{
  int i;
  cout << "Please enter number of films: ";
  cin >> i;
  return i;
}

Output (obtained; incorrect)

Please enter number of films: 2
You will have to provide data for 2 films.
Enter title: q
Enter year: 1
Enter title: w
Enter year: 2

You have entered these movies:
 (0)
 (0)

Output (desired)

Please enter number of films: 2
You will have to provide data for 2 films.
Enter title: q
Enter year: 1
Enter title: w
Enter year: 2

You have entered these movies:
 q (1)
 w (2) 
Krantz
  • 1,424
  • 1
  • 12
  • 31
  • 2
    In each iteration of the loop, you set the film's year twice... I assume that's a mistake... `movies_t films [z];` is also not valid in c++ – ChrisMM Apr 20 '22 at 15:35
  • It sounds like you may need to learn how to use a debugger to step through your code. With a good debugger, you can execute your program line by line and see where it is deviating from what you expect. This is an essential tool if you are going to do any programming. Further reading: [How to debug small programs](http://ericlippert.com/2014/03/05/how-to-debug-small-programs/) and [Debugging Guide](http://idownvotedbecau.se/nodebugging/) – NathanOliver Apr 20 '22 at 15:35
  • 1
    the `cin.ignore()` after `std::getline` will throw away the first character of the next line, as you are only entering a single character the line will be empty – Alan Birtles Apr 20 '22 at 15:39
  • `movies_t films [z];` Change that to `std::vector films(z);`. As mentioned, the former is not valid C++. – PaulMcKenzie Apr 20 '22 at 15:39
  • Thanks, @PaulMcKenzie, but when I change ``movies_t films [z];`` to ``std::vector films(z);`` it gives error message: ``In function 'int main()': 22:4: error: 'vector' is not a member of 'std' 22:24: error: expected primary-expression before '>' token 22:33: error: 'films' was not declared in this scope 33:18: error: 'mystr' was not declared in this scope`` – Krantz Apr 20 '22 at 15:42
  • 1
    Minor point: get in the habit of initializing objects with meaningful values rather than default-initializing them and immediately overwriting the default values. In this case, that means changing `int z; z = getnumber();` to `int z = getnumber();`. – Pete Becker Apr 20 '22 at 15:45
  • Thanks, @Alan Birtles. I used ``cin.ignore();`` to address this issue: https://stackoverflow.com/questions/21567291/why-does-stdgetline-skip-input-after-a-formatted-extraction – Krantz Apr 20 '22 at 15:46
  • Thanks, @Peter Becker. Lesson learned. Program changed accordingly. – Krantz Apr 20 '22 at 15:47
  • Thanks, @ChrisMM: I have corrected the first mistake. Could you kindly help with the second mistake``movies_t films [z]; is also not valid in c++``? – Krantz Apr 20 '22 at 15:54
  • 1
    @Krantz -- Did you `#include `? – PaulMcKenzie Apr 20 '22 at 15:57
  • Thanks @PaulMcKenzie. After adding ``#include ``, it did not give that error, but still gives wrong results; now it gives: ``You have entered these movies: (0) (0)``. I have updated the code. Any thoughts? Sorry my stupid questions, I am coming from R, trying to use C++ to speed up my computations, so I might make basic mistakes in C++. Your understanding would be much appreciated. – Krantz Apr 20 '22 at 16:03
  • Is the input literally `"title1=q, year1=1, title2=w, year2=2"`? Are you trying to extract "q", "1", "w", and "2" from the aforementioned string? – David G Apr 20 '22 at 16:05
  • Thanks, @David G. The program must print: ``q (1) w (2)``. And the object ``films`` of the data structure ``movie_t`` must be assigned size dynamically; this and the other characteristics of the program are important for the actual program. – Krantz Apr 20 '22 at 16:12
  • @Krantz -- First, you shouldn't change the code in the post. If anything, add new code. Second, you would have had a much easier time with a `std::map`, where the `std::string` is the title, and then `int` is the year. – PaulMcKenzie Apr 20 '22 at 16:14
  • Thanks, @Blastfurnace. No, I am not going to delete after there are no more errors. It should help other people in the future. But if someone comments that this or that is incorrect, I feel I should correct the mistake. But if someone just writes the answer, then I will not correct any mistakes corrected in the answer. – Krantz Apr 20 '22 at 16:15
  • 1
    Is this a homework assignment? I guess the OP is asked to find the bug in given snippet. – Red.Wave Apr 20 '22 at 16:51
  • Not hw at all, @Red.Wave. I am past hw's. As I said above, sorry my stupid questions, I am coming from R, trying to use C++ to speed up my computations, so I might make basic mistakes in C++. Your understanding would be much appreciated. – Krantz Apr 20 '22 at 17:07
  • @Krantz As I am not convinced, I give you a short assignment: use this inputs: title1: Matrix year1:1999 title2: avatar year:2005. Please try this. – Red.Wave Apr 20 '22 at 17:13
  • @Krantz did you run the test. I promise you'll regret not doing it. – Red.Wave Apr 20 '22 at 17:18
  • @Red.Wave. In good faith I tested since you are insisting. The output is: ``You have entered these movies: (0) 999 (0)``. – Krantz Apr 20 '22 at 17:28
  • Took me a while to setup a usefull input sequence. After running the program, without caring about prompts input this:`3`<2*press enter>`_1800``_matrix``_1999``_avatar``_2005`<2*press enter> then review the screen. it does tell you a lot. – Red.Wave Apr 20 '22 at 18:48
  • Well. It terminates without performing its tasks. But you are not using it as expected. So, why should it behave as expected? – Krantz Apr 20 '22 at 18:54

1 Answers1

1

Make a function that gets the value after = in each token.

string getValue(string field) {
  auto pos = field.find('=');
  return field.substr(pos + 1, field.find(',') - pos - 1);
}

Then all you need to do is:

for (n = 0; n < z; n++) {
  string title, year;
  assert(cin >> title >> year);
  movies_t movie = {getValue(title), stoi(getValue(year))};
  films.push_back(movie);
}

To use assert you need #include <cassert> at the top.

Update:

You need to ignore spaces, so add this to your program:

struct ctype_ : std::ctype<char>
{
    static mask* make_table()
    {
        const mask* table = classic_table();
        static std::vector<mask> v(table, table + table_size);
        v[' '] &= ~space;
        v[','] |= space;
        return &v[0];
    }

    ctype_() : std::ctype<char>(make_table()) { }
};

And then do this just before the for loop:

cin.imbue(std::locale(cin.getloc(), new ctype_));

And then it should work.

2nd update:

for (n = 0; n < z; n++) {
  string title, year;
  cout << "Enter title: ";
  assert(cin >> title);
  cout << "Enter year: ";
  assert(cin >> year);
  movies_t movie = {getValue(title), stoi(getValue(year))};
  films[n] = movie;
}
David G
  • 94,763
  • 41
  • 167
  • 253