You are getting a segmentation because your program has undefined behaviour. There is an error in your code which your compiler is not required to diagnose; it instead generates a binary which can do anything, including random crashes.
Depending on user input, your problems are starting with the use of atoi in this line:
for(int i=0;i<atoi(argv[1]);i++)
First of all, your program can obviously only work if the user enters "4", which makes me wonder why you need user input anyway. Chances are that you wanted to write new student[atoi(argv[1]] in the line above.
Nevertheless, atoi is a dangerous function and should almost never be used. As documentation says:
If the converted value falls out of range of corresponding return
type, the return value is undefined.
Which means that you will never know if the user entered a harmless number like "1" or something like "10000000000000000000000000", which is probably larger than the maximum int value on your machine.
What's possibly worse:
If no conversion can be performed, 0 is returned.
Which means you will never know if the user entered "abc" or "0".
std::stoi is a safe, modern alternative which allows you to perform error checking.
Still, let's assume that the user simply enters a "4".
We then enter into the loop body and encounter the following line:
cin>>*(*(sptr+i)).name;
Readability issues aside, what's happening here is:
i is still 0, so you get (sptr+0), which is equal to (sptr).
sptr is dereferenced to obtain a reference to a student object.
- You try to dereference the
name pointer of the student object.
The latter step finally results in undefined behaviour, because the name pointer was not initialised. You must not do this. All the rest of your program has been rendered invalid at this point.
Getting this right with bare pointers is extremely difficult. You could add user input asking for the size of each name, so that you can allocate enough memory before reading the name. Or you could employ an even more complex approach using low-level member functions of std::istream.
Fortunately, you don't have to do any of this. This is C++: use std::string, std::vector and std::getline. Use C++ and not C if you want to write C++ and not C, and all your problems will disappear:
#include <iostream>
#include <string>
#include <vector>
#include <exception>
struct student
{
std::string name;
};
int main(int argc, char* argv[])
{
try
{
if (argc == 2)
{
std::vector<student> students(std::stoi(argv[1]));
for (auto&& student : students)
{
std::getline(std::cin, student.name);
}
for (auto&& student : students)
{
std::cout << student.name << "\n";
}
}
}
catch (std::exception const& exc)
{
std::cerr << exc.what() << "\n";
}
}
This program has defined behaviour; it will not crash with wrong input, and it will allow names with spaces in them. It is also easier to read, does not use any pointers on the outside, and it handles memory automatically, smarter and faster than manual code.
name. Usestd::stringinstead ofchar*.pand indexi, the expression*(p + i)is equivalent top[i]. So instead of doing*(sptr+i)in your loop, just dosptr[i].namein the input/output.