1

I am teaching myself C/C++ at the moment, and I got the exercise (from the book I am reading) to write a program that could make an output like this:

Enter your first name: Flip
Enter your last name: Fleming
Here’s the information in a single string: Fleming, Flip

Using Structures. But my output comes out like this:

Enter your first name: Flip
Enter your last name: Fleming
Here’s the information in a single string: , 

Here is the code. It's fairly short and simple so it shouldn't be hard to read :)

#include <iostream>
#include <cstring>

using namespace std;

struct Person {
    char* firstName;
    char* lastName;
};

char* getName(void);

int main() {
    Person* ps = new Person;
    cout << "Enter your first name: ";
    char* name;
    name = getName();
    ps->firstName = name;
    cout << "Enter your last name: ";
    char* lastname;
    lastname = getName();
    ps->lastName = lastname;
    cout << "Here's the information in a single string: "
            << ps->lastName << ", " << ps->firstName;
    delete ps;
    delete name;
    delete lastname;

    return 0;
}

char* getName() {
    char temp[100];
    cin >> temp;
    cin.getline(temp, 100);
    char* pn = new char[strlen(temp) + 1];
    strcpy(pn, temp);

    return pn;
}
OmniOwl
  • 5,477
  • 17
  • 67
  • 116

4 Answers4

5

First, there's no such thing as C/C++. You're mixing them, which is wrong. Since you're using C++ headers/new/using, I'll assume you want C++, so here's how you fix your code:

  • replace all char* and char[] with std::string
  • get rid of dynamic allocation

So, some changes would be:

struct Person {
    std::string firstName;
    std::string lastName;
};

or

Person ps;
Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
  • To learn about the past and why we do as we do now instead. A lot of the C stuff is used for Hardware access (as far as I understand) any way, so learning about it is not a bad thing...If you want to interface with other languages (like Java that I know a great deal of) I often see that C is being used to write a Hardware interface for Java to use. – OmniOwl Oct 30 '12 at 11:44
  • 2
    @Vipar I'm not saying you shouldn't learn C. I'm saying you shouldn't learn them at the same time, or even remotely think they are the same language. – Luchian Grigore Oct 30 '12 at 11:46
  • Where did I give you the impression that I am mixing them up? – OmniOwl Oct 30 '12 at 11:47
  • 2
    @Vipar, well, you wouldn't say "I'm teaching myself Java/C++" and then ask a C++ question, would you? The fact that you mentioned C indicates to us that you think you can take what you've learned in C and apply it to C++, which is not true in 90% of the time. Doing so will, in fact, hinder you progress in C++. – avakar Oct 30 '12 at 11:52
  • 1
    @Vipar: you are learning an unholy mess of a mix of the two languages. Learning C is great, and learning C++ is fine. Learning C/C++ is horrible. And your code gives the impression that you are mixing them up. What you have won't compile as C, and it will make a C++ programmer puke. It is a mix of the two languages. Despite what you might believe, you are not "learning both". You are learning neither. – jalf Oct 30 '12 at 11:54
  • You could learn both, as long as you don't confuse them. Sadly, you have to have experience to recognize the _essential_ differences. – sehe Oct 30 '12 at 11:58
  • @jalf Right. You don't even know, how I am learning the language(s) at the moment. So far I have not learned how to write C code. I have learned how C code looks like and how we do it in C++ instead and why we do it like that now. I will probably pick up a book at some point that strictly teaches C. – OmniOwl Oct 30 '12 at 11:59
  • @sehe Kind words. Thank you :) – OmniOwl Oct 30 '12 at 11:59
  • @VIpar: you have shown us a code sample which is not C, and is horrible C++ with a lot of C idioms mixed in. It is possible to learn both, and while I wouldn't recommend it, it is even possible to learn both *at the same time*. But it requires, first of all, quality teaching materials. The book you are using is doing a horrible job of teaching you C++ – jalf Oct 30 '12 at 12:00
  • 1
    @jalf: Describing the guy's code as horrible isn't the least bit constructive. If you think he needs better teaching materials please suggest some. – Component 10 Oct 30 '12 at 12:33
  • @Component10 exactly how constructive is your comment, then? ;) I at least told him to find different teaching materials, which leaves him in a better position than he was before. Whining about other people's comments isn't going to help the OP in *any* way, is it? But if it makes you happy, [here](http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list) is the list of actually *good* books about C++. – jalf Oct 30 '12 at 13:20
  • 1
    Quit fighting in my answer! :P – Luchian Grigore Oct 30 '12 at 13:24
  • @jalf And hey, what do you know, the book you told me to burn is on the list :P – OmniOwl Oct 30 '12 at 16:19
3

You are using:

cin >> temp;
cin.getline(temp, 100);

You probably overwrite what you already have with empty string at the end of a line.

Use just one of them.

If you'll stick with using cin >> you may consider setting width() to prevent buffer overflow.

Vyktor
  • 20,559
  • 6
  • 64
  • 96
  • This solved my problem. Thank you! Also thank you for the width() advise. – OmniOwl Oct 30 '12 at 12:00
  • @Vipar my personal opinion is that you should go what [Luchian Grigore](http://stackoverflow.com/a/13138217/1149736) suggested though. – Vyktor Oct 30 '12 at 12:04
2

No no no, wayyyy too complicated. Use real C++ idioms. The program could be as simple as this:

#include <string>
#include <iostream>

int main()
{
    std::string firstName, lastName;

    if (!(std::cout << "Your first name: "  &&
          std::getline(std::cin, firstName) &&
          std::cout << "Your last name: "   &&
          std::getline(std::cin, lastName)     ))
    {
        std::cerr << "Error: unexpected end of input!\n";
        return 0;
    }

    std::cout << "You are " << firstName << " " << lastName << ".\n";
}

As a variation on the theme, you could put each getline in a loop until the user inputs a non-empty line:

std::cout >> "Your first name: ";
for ( ; ; )
{
    if (!(std::getline(std::cin, firstName))
    {
        std::cerr << "Error: unexpected end of input.\n"; 
        return 0;
    }
    if (!firstName.empty())
    {
        break;
    }
    std::cout << "Sorry, please repeat - your first name: ";
}
Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • 2
    @Vipar: Hence here's a tip how to use it right! :-) Note: No pointers. No `new`. Never an unguarded input operation. – Kerrek SB Oct 30 '12 at 11:48
  • Yeah, and I appreciate the gesture. But since I am new at this, I should be allowed some slack. I was asked to use structures just to try and work with structures. The fact that I now have a multitude of solutions that don't use structures, don't solve the problem. Again, it's a nice gesture, but it doesn't solve my problem or explain why my code didn't work. – OmniOwl Oct 30 '12 at 11:53
  • @Vipar you are allowed all the slack you want (pro tip: try to use as little as possible). We're not denying you valuable information too. Win - win - win, all around :) – sehe Oct 30 '12 at 11:57
  • @Vipar: Well, just stick the strings into a struct if you want. But that's just a minor detail. Getting the input operation right is a far more serious issue (and done wrong in the currently accepted answer). There are hundreds of questions here on SO that could have been avoided entirely if people performed correct input operations. – Kerrek SB Oct 30 '12 at 12:41
2

First, the immediate problem is that you read twice from std::cin: first with operator>>, and then with getline. Pick one or the other.

But let's simplify your code a bit. There are simply too many sources of error. Pointers are tricky because they might point to the wrong thing, or you might forget to delete objects, or delete them twice. C-style char arrays as strings are bad because, well, they're not strings, and they don't behave like strings.

So let's use the standard library's string class:

#include <iostream>
#include <string>

struct Person {
    std::string firstName;
    std::string lastName;
};

std::string getName(void);

int main() {
    Person ps;
    cout << "Enter your first name: ";
    std::string name = getName();
    ps.firstName = name;
    cout << "Enter your last name: ";
    std::string lastname = getName();
    ps.lastName = lastname;
    cout << "Here's the information in a single string: "
            << ps.lastName << ", " << ps.firstName;
}

std::string getName() {
    std::string temp;
    std::getline(cin, temp);
    return temp;
}

This is a fairly simple, almost mechanical substitution, basically just replacing char* by std::string, and removing the bits that are no longer necessary.

Of course, as pointed out in a comment, I've omitted all forms of error checking, which a real program should definitely do.

jalf
  • 243,077
  • 51
  • 345
  • 550
  • Instead of flaming me (which you basically did in the comment section), you come with valuable input that actually helps me a lot more. I appreciate it a lot. You used my code, and kept the solution within using structures. Thank you. – OmniOwl Oct 30 '12 at 12:03
  • 1
    Since this is an educational question, we should point out that an unguarded input operation like your `getline` is actually a serious programming error. – Kerrek SB Oct 30 '12 at 12:39
  • 1
    @Vipar: To be precise, it is undefined behaviour to access `temp` in the last statement if the input operation on the line above failed. – Kerrek SB Oct 30 '12 at 12:50
  • @Vipar: I didn't flame you. I pointed out that the code was really bad, and that the book which taught you to write that kind of code is really bad. :) – jalf Oct 30 '12 at 13:22
  • @jalf The book didn't really teach me to code this in any specific way. It taught me the syntax and did show a few examples (which look a lot better than what I present, I know) of how certain concepts etc. Just like when I learned Java, optimizing and learning when something is safe or not, came later. I expect it to be the same in this case, hence why I don't pay much detail to it in the first place. Since it's been asked so much, the book is called "C++ Primer Plus (6th edition)" which was recommended by many, many people for people who already knew Java (apparently). – OmniOwl Oct 30 '12 at 16:15
  • ps is not a pointer, so you need to change your ->'s into .'s. – bstamour Oct 30 '12 at 17:56