Accessing structure array attributes without using pointers - c++

Is it possible to make a structure array variable and access structure attributes without using pointers? I tried doing it without a pointer and it is giving me an error.
#include<iostream>
#include<string>
using namespace std;
struct Student
{
string name;
string rollNo;
float GPA;
string department;
char section;
};
int main()
{
Student s1[10];
for (int i = 0; i < 10; i++)
{
cout << i + 1 << "Enter your name: ";
cin >> s1.name;
cout << "Enter roll num: ";
cin >> s1.rollNo;
}
return 0;
}
I am accessing attributes by placing a dot s1.rollNo gives an error.

s1 is an array of structs and needs to be accessed with an index: s1[i].name etc.

As said by others you need to access it like
s1[i].name
You could also access it like this
for(auto &s : s1){
cin >> s.name; //Do Whatever With Member
}

Related

Can you use "cin" with string?

I was taught that you have to use gets(str) to input a string and not cin. However I can use cin just fine in the program below. Can someone tell me if you can use cin or not. Sorry for my bad English. The program lets you insert 5 names and then print those names to the screen.
Here's the code:
#include <iostream>
#include <string.h>
using namespace std;
int main()
{
char **p = new char *[5];
for (int i = 0; i < 5; i++)
{
*(p + i) = new char[255];
} //make a 2 dimensional array of strings
for (int i = 0; i < n; i++)
{
char n[255] = "";
cout << "insert names: ";
cin >> n; //how i can use cin here to insert the string to an array??
strcpy(p[i], n);
}
for (int i = 0; i < n; i++)
{
cout << p[i] << endl; //print the names
}
}
You can indeed use something like
std::string name;
std::cin >> name;
but the reading from the stream will stop on the first white space, so a name of the form "Bathsheba Everdene" will stop just after "Bathsheba".
An alternative is
std::string name;
std::getline(std::cin, name);
which will read the whole line.
This has advantages over using a char[] buffer, as you don't need to worry about the size of the buffer, and the std::string will take care of all the memory management for you.
Use ws (whitespace) in getline() like getline(cin>>ws, name);
If numeric input is before the string then due to whitespace the first string input will be ignored. Therefore use ws like getline(cin>>ws, name);
#include <iostream>
using namespace std;
main(){
int id=0;
string name, address;
cout <<"Id? "; cin>>id;
cout <<"Name? ";
getline(cin>>ws, name);
cout <<"Address? ";
getline(cin>>ws, address);
cout <<"\nName: " <<name <<"\nAddress: " <<address;
}

C++ Storing a string into a class

I made a topic a bit ago regarding structs. And I know that classes have the same concept as structs. How would I go about storing a string into the class?
This is the class
class studentType
{
public:
void setData(string, int);
string getName() const;
int getId() const;
private:
string name;
int sid;
};
void studentType::setData(string, int) {
name = ??;
sid = ??;
}
string studentType::getName() const {
return name;
}
int studentType::getId() const {
return sid;
}
The main consists of:
int main() {
studentType object, number;
cout << "enter name and code of item1: ";
cin >> object.setData() >> object.setData();
cout << "enter name and code for item2: ";
cin >> number.setData() >> number.setData();
system("pause");
return 0;
}
How would I fix the cin issue? I already have string defined in the header. And yes, I know using namespace std; isn't preferred but it's for simplicity
int id;
string name;
cout << "enter name and code of item1: ";
cin >> name >> id;
object.setData(name, id);
cout << "enter name and code for item2: ";
cin >> name >> id;
object.setData(name, id);
You should instead use a constructor for your class though:
class studentType {
public:
studentType(string name, int sid)
: name(name)
, sid(sid)
{ }
// ...
You can then initialize your objects with the correct name and ID:
cin >> name >> id;
studentType object(name, id);
But I suppose constructors will come up very soon in the tutorial or course you're currently doing.
cin >> object.setData() >> object.setData();
the >> operator doesn't call object.setData; it takes a reference and sets the reference contents to the extracted input. The expression object.setData() calls the function, which returns void. Of course, the >> operator cannot take a void argument. Also, there aren't enough arguments in the funcall because object.setData expects a string and an int.
You should do this:
std::string name;
int num;
cin >> name >> num;
object.setData(name, num);
Your setData function can be as such:
void studentType::setData(string name, int sid) {
this->name = name;
this->sid = sid;
}
And in your main():
First cin the values and then call the setData function, i.e.
int main(){
string name;
int code;
studentType object, number;
cout << "enter name and code of item1: ";
cin >> name >> code;
object = studentType();
object.setData(name, code);
// your remaining code
}
Just a note of caution:
If you use cin to get the name and code, the name can only be a single word. Say if you are writing a name of two words, the first word will be put in name and the second will be attempted to put in code.
In simpler terms, cin is space-delimited.
What you're looking for is std::getline(). I would use cin for getting your integers, but not for the strings. I would separate the user input like this. Like #Suhaib Ahmad said, cin is space-delimited. To get a string including spaces from stdin, use std::getline().
void studentType::setData(string n, int i) {
this->name = n;
this->sid = i;
}
-
int main(void) {
string n;
int i;
studentType object, number;
cout << "Enter name for item1: ";
getline(cin, n);
cout << "Enter code for item1: ";
cin >> i;
object = studentType(); // make sure you construct your studentType, I also recommend using a constructor function
object.setData(n, i);
cout << "Enter name for item2: ";
getline(cin, n);
cout << "Enter code for item2: ";
cin >> i;
number = studentType();
number.setData(n, i);
system("pause");
return 0;
}
The way you are using setData(), with no arguments given, as a place to store the cin input is incorrect. You would need to declare variables first, and then initialize your class with the variables.

How can i read different data type in a file? C++

This is Code of my project.. Now I want to store name in a String variable, then Gender in Char type variable and so on..
this code is storing first name in sepreate variable and last name in other variable..
how can i store then in different variables?
#include<iostream>
#include<string>
#include<fstream>
using namespace std;
int main()
{
string array[14][10];
ifstream read("file.txt");
if(read.fail())
cerr << "ërrier"<< endl;
for(int i=0;!read.eof();i++)
{
for(int j=0;j<10;j++)
{
read>> array[i][j];
cout<< array[i][j]<<" ";
}
cout<< endl;
}
read.close();
return 0;
}
this is file I want to read.. help me
I haven't known carefully your purpose. but if your purpose is store names and families in several string variable or other type,
you can use pointers:
std::string *name;
std::vector<std::string *> names;
for(int i=0;!read.eof();i++)
{
for(int j=0;j<10;j++)
{
name = new std::string;
read>> *name;
cout<< *name<<" ";
//this line help us to keep pointers, you can access to pointers,
names.pushback(name).
}
cout<< endl;
}

Returning a structure pointer

I'm quite new with c++ and need some help with the following code.
#include <iostream>
using namespace std;
struct student {
string name;
int age;
float marks;
};
struct student *initiateStudent(string , int , float);
int main ( ) {
int totalStudents = 1;
string name;
int age;
float marks;
cin >> totalStudents;
student *stud[totalStudents];
for( int i = 0; i < totalStudents; i++ ) {
cin >> name >> age >> marks;
stud[i] = initiateStudent(name,age,marks);
}
cout << stud[0]->name;
return 0;
}
struct student *initiateStudent(string name, int age, float marks)
{
student *temp_student;
temp_student->name = name;
temp_student->age = age;
temp_student->marks = marks;
return temp_student;
}
I need in the function initiateStudent return a struct pointer to the pointer array stud by passing the members name, age, marks.
I know that the problem sofar is the fact that temp_student is destroyed when I return to the main file.
So my question is how it could be done by just passing the members of the struct and then return back with information to the pointer array stud.
Thank you very much.
Semi-answer To explain the bad habits:
#include <string>
#include <iostream>
#include <vector>
//using namespace std; often injects subtle bugs. Use with caution
// read more here:
// http://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice
struct student
{
std::string name; // explicit namespacing reduces possibility of unwanted collisions
int age;
float marks;
//added constructor in place of initialization function.
student(std::string name, int age, float marks):name(name), age(age), marks(marks)
{
}
};
int main()
{
int totalStudents = 1;
std::string name;
int age;
float marks;
while (!(std::cin >> totalStudents)) // testing input for success
// Needed extra brackets caught by M.M
// teach me to not test even a throw-away example
{
std::cout << "must... have... good... input..." << std::endl;
cin.clear(); // clear the error and get rid of any other garbage the user may have input.
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
//student *stud[totalStudents]; illegal in C++
std::vector<student *> stud(totalStudents); // using dynamic array instead
for (int i = 0; i < totalStudents; )// i++ removed
{
if (std::cin >> name >> age >> marks) //testing input
{
stud[i] = new student(name, age, marks); // using constructor
i++; // and put here. Only increment if input is valid.
}
else
{
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
}
std::cout << stud[0]->name;
for (student * stu: stud) // cleaning up allocated memory
{
delete stu;
}
return 0;
}
One of the beauties of C++ is you rarely need to self-manage memory. In fact there are huge advantages in not doing it above and beyond not having to clean up after yourself.
#include <string>
#include <iostream>
#include <vector>
struct student
{
std::string name;
int age;
float marks;
student(std::string name, int age, float marks):name(name), age(age), marks(marks)
{
}
};
int main()
{
std::string name;
int age;
float marks;
std::vector<student> stud; // look ma! No pointer!
while (std::cin >> name >> age >> marks) //exits loop on bad input
{
stud.emplace_back(name, age, marks); // building directly in vector
// vector will size itself as needed.
}
std::cout << stud[0].name;
return 0;
}
One more caveat: >> is whiespace delimited. That means it stops when it finds whitespace (space, tab, end of line...) so a name of "John Jacob Jingleheimer-Shmidt" will go into name as "John". >> will then attempt to interpret "Jacob" as age, and that will not go so well.
the simple solution is to make your initiateStudent() creates temp_student on the heap (with new): and returns it. keep in mind heap allocated memory is not freed automatically so don't forget to free it later on yourself.
#include <iostream>
#include <string>
using namespace std;
struct student {
string name;
int age;
float marks;
};
struct student *initiateStudent(string , int , float);
int main ( ) {
int totalStudents = 1;
string name;
int age;
float marks;
cout << "Total student: ";
cin >> totalStudents;
cin.sync(); // very very important to not affect the next input (name)
student* stud = new student[totalStudents];
for( int i = 0; i < totalStudents; i++ )
{
cout << "Name: ";
getline(cin, name);
cin.sync();
cout << "age: ";
cin >> age;
cout << endl;
cout << "Marks: ";
cin >> marks;
cout << endl;
cin.sync();
stud[i] = *initiateStudent(name, age, marks);
}
cout << "Student 1: " << stud[0].name << endl;
delete[] stud;
stud = NULL;
return 0;
}
struct student *initiateStudent(string name, int age, float marks)
{
student *temp_student = new student;
temp_student->name = name;
temp_student->age = age;
temp_student->marks = marks;
return temp_student;
}

How to allow unlimited number of names for input?

#include <iostream>
using namespace std;
#include "ReadString.h"
void main()
{
int i ;
int NumNames=5;
char ** pNames;
int MaxNum = 10;
int more(0);
pNames = new char *[NumNames];
cout << "Enter names" << endl;
This is the part where I am having trouble. I tried in different way but didn't work out. I tried to make a loop unless the first character is an 'Enter Key'.
while(cin.get()!='\n')
{
for (i = more; i < NumNames; i++)
{
cout << (i + 1) << ") ";
pNames[i] = ReadString();
more = NumNames;
NumNames +=NumNames
}
}
Replace manually allocated dynamic array with some container which can grow dynamically, for example std::vector:
std::vector<std::string> names;
std::string name;
// read the names
while (cin >> name) {
names.push_back(name);
}