Some problems with struct [closed] - c++

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
#include <iostream>
using namespace std;
struct student{
char name[10];
int grade;
};
int main() {
struct student s[10];
student s[0].name = "Jack";
cout<<s[0].name;
}
I want to create the struct type data student as an arraign. But when I did it like this, some errors appeared and I didn't know why.Following are the errors:
1.error: redefinition of 's' with a different type: 'student [0]' vs 'struct student [10]'
student s[0].name = "Jack";
^
2.note: previous definition is here
struct student s[10];
^
3. error: expected ';' at end of declaration
student s[0].name = "Jack";
^
;

char name[10];:
10 characters is too short for a name.
char assumes names are not outside ASCII or UTF-8, and it doesn't look like you're using a Unicode library.
Fixed-sized arrays for storing strings is not keeping with idiomatic C++.
Solution: use std::string or std::wstring - and use a Unicode library!
struct student s[10]
This is not idiomatic C++. The struct keyword is unnecessary. Just student s[10]; is sufficient.
Again, avoid fixed-sized arrays unless you know for certain you will be using 10 records. Use std::vector<student> instead.
You don't initialize the array, so the data-members will contain undefined/uninitialized data. Use = {0} to zero-out memory and/or define a student constructor.
student s[0].name = "Jack";
This won't compile. I think you meant to put just s[0].name = "Jack"
The assignment operator = is not defined (by default) for strings. Note that your struct's member type is char whereas a string literal is const char[N], so in reality you're assigning a pointer (due to Array Decay) to a char member. This is a meaningless operation.
Your main does not return a value. Use return EXIT_SUCCESS; on success. This is not strictly required, but I personally believe it's good practice to explicitly return a value.

Related

Difficulties on atributting a array to another [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
I'm having a problem when i try to use a char[20] array and put it's "content" into another array of same size.
struct book{
char author[20];
char title[20];
};
book library [100];
void removebook(){
for (cont; cont<=quantidade; cont++){
cont2=(cont+1);
// HERE is where all goes downhill ↓↓↓↓↓↓↓↓↓↓↓
library[cont].author = library[cont2].author
}
the error i get is [Error] invalid array assignment
the intention is make a author name written on library[4].author overwrite library[3].author
like:
library[4].author=Mark;
library[3].author = library[4].author;
now whatever was on library[3].author was overwritten with mark
You can't copy an array with operator=. You can fix your problem using modern C++
#include <array>
#include <cstddef>
// #include <list>
#include <string>
// #include <vector>
struct book{
std::string author;
std::string title;
};
std::array<book, 100> library; // or std::vector<book> library;
// or std::list<book> library;
void removebook(std::size_t idx) {
for (std::size_t cont = idx; cont < library.size() - 1; ++cont){
std::size_t cont2 = cont + 1;
library[cont] = library[cont2];
}
}
Probably you can replace the body of removebook with a function from algorithm like std::remove or a method like std::vector::erase or std::list::erase depending on how you implement it, e.g. for std::array<book, 100> library
#include <array>
#include <cstddef>
#include <string>
struct book{
std::string author;
std::string title;
};
std::array<book, 100> library;
void removebook(std::size_t idx) {
std::copy(library.begin() + idx + 1, library.end(), library.begin() + idx);
library.back() = book{};
}
When your attribute is defined as traditional C char array, your = operator between two traditional C char array will try to assign the right side first array address to the left side argument because library[cont].author is actually contains a constant char address in the memory.
The line:
library[cont].author = library[cont2].author;
Actually tries to take library[cont2].author value, which is constant char address, and assign it to library[cont].author which is also constant char address (which cause the failure). Even if it would work, it wouldn't done what you want it to.
The closest way to archive what it would done if it worked, is to define author as char*. Assume we allocated a memory for this attribute in every member of the library. The same line of code, would make all of the pointers to contains the same memory address, and now you can see how much troubles it would done.
The solution can be use std::string as mentioned in #ThomasSablik answer or as #Peter mentioned std::array<char, 20>.

Is there anyway for the array at the end of class to work? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
I got an array at the end of my class and i don't know how to use it.
the bus[10] is so hard to understand. I don't know why it can access driver and what does empty() function really do.
#include "conio.h"
#include "stdio.h"
#include "iostream.h"
#include "string.h"
#include "graphics.h"
#include "stdlib.h"
#include "dos.h"
static int p=0;
class a
{
char driver[10];// driver
public:
void install();// for installing
}bus[10];//here we declare the number of buses we can have.
void a::install()
{
cout<<"Enter bus no: ";//ques
cin >> bus[p].driver;// what does this mean
bus[p].empty();//what does this mean
p++;
}
This is syntax for defining a type, and an instance of that type, at the same time.
For example:
struct Foo {} foo;
is the same as:
struct Foo {};
Foo foo;
So your example defines the type a, and also creates an array of 10 as called bus.
It would be more clearly written thus:
class a
{
char driver[10];
public:
void install();
};
a bus[10];
In this manner we can now more easily see that you've created a global array called bus, which you can use like you'd use any other array.
Since p is zero (to begin with), bus[p] just gives you the "first" a object in the array (to begin with). As p is increased, subsequent buses are accessed.
So, this:
cin >> bus[p].driver;
reads into the driver member of the pth bus.*
And this:
bus[p].empty();
means nothing, because a does not have a member function called empty().
* Well, the p+1th bus, because array indices begin at zero but English doesn't!
P.S. You can do funny (read: stupid) things with this syntax!
This is a very strange looking code, probably from an old workbook.
I could help you with achieving the action that you want, but it's hard to understand anything from this snippet.
Wrong: As far as I remember adding a identifier at the end of an unnamed struct gave it a name just like the usual approach.
struct {
float x, y;
} Point;
//is equal to
struct Point {
float x, y;
}
However I'm not familiar with the array syntax you provided.
I suppose std::cin >> bus[p].driver is meant to read the "name" that the char[10] driver field is. But using a char array here is troublesome and it's much better to replace it with std::string and shortening it to 10 characters after input.
The empty() method is often used as a container function returning boolean and telling the programmer whether the container is empty or not. Here however this function is undeclared and the code won't compile either way.
Not to mention that non-const variables placed out of function scope, like the static int p = 0, are a grave mistake.
Not true: In conclusion this is a very messy code and without the knowledge of what you want to achieve nobody could help you here.
See the answer below for better explanation.

dynamic memory allocation to a struct type [duplicate]

This question already has answers here:
c++ memory error when using malloc/realloc/free on std::string
(2 answers)
Closed 4 years ago.
I am trying to allocate memory to structure dynamically but i am getting error while allocation the memory dynamically
#include <string>
using namespace std;
#define MAX_GRADES 5
typedef struct _Student
{
string id;
string name;
double grades[MAX_GRADES];
double average;
}Student;
Student *update_list;
int main()
{
Student *n = (*Student) malloc(sizeof(n));
return 0;
}
main.cpp: In function ‘int main()’:
main.cpp:26:24: error: expected primary-expression before ‘)’ token
Student *n = (*Student) malloc(sizeof(Student));
^
TL;DR version
Use
Student *n = new Student;
instead of
Student *n = (*Student) malloc(sizeof(n));
Explanation
This is a typo
Student *n = (*Student) malloc(sizeof(n));
^ wrong side.
You want
Student *n = (Student*) malloc(sizeof(n));
^ needs to be here.
This will compile. Normally I would leave a comment and vote to close but there are two things wrong with this solution that you'll find at runtime.
n is a pointer. sizeof(n) will give the size of a pointer which is guaranteed to be shorter than a string (unless the string implementation is incredibly awesome and doing things I can't even imagine). You would want sizeof(*n) to get the size of a Student if the next point didn't render this point useless.
std::string is a fairly complex class. It is only valid if at least one of its many constructors successfully initializes the class. malloc is a C function. C doesn't know what a constructor is, so no string constructor is run. This leaves id and name ticking time bombs waiting to blow your program up. Do not malloc a C++ class unless you know the class is a POD type or will be using placement new before use.
Use new here or do not dynamically allocate at all.
Student *n = (*Student) malloc(sizeof(n));
(*Student) is not a type, you want (Student*). Also, sizeof n gives the size of a pointer on your system, not the size needed for one or more Students. Correct way:
Student *n = (Student*) malloc(sizeof(*n));
However, as pointed out in the answer of user4581301, your Student is not POD so you have to use new to ensure constructors are being called:
Student *n = new Student;
or, if you want more than one Student
Student *n = new Student[42];
Please remember that all memory allocated using new must be deallocated using delete and all memory allocated using new[] with delete[].
But the use of raw owning pointers is considered bad practice and should be avoided in favour of smart pointers like std::unique_ptr<> and std::shared_ptr<> or containers:
The C++-way would be using std::vector<Student>.
Also, there is no reason to use a typedef for a structure in C++.
There are three mistakes in your code:
The cast right before malloc should be (Student *): this is the correct type of n, i.e., a pointer to Student.
The size to allocate is sizeof(Student): sizeof(n) would give you the size of a pointer, most probably too small for Student.
Most important: you should never use malloc to allocate memory for a struct which contains a complex object like a string. You must use instead new, see the discussion here.
A correct code would be
#include <string>
using namespace std;
#define MAX_GRADES 5
struct Student
{
string id;
string name;
double grades[MAX_GRADES];
double average;
};
Student *update_list;
int main()
{
Student *n = new Student;
delete n;
return 0;
}
I have added a delete n at the end: it is not necessarily to run the code correctly, but it is a good practice to not forget to delete the allocated memory.
Even better, rather than using a #define to fix the size of the array grades you should use a template parameter: in this way MAX_GRADES does not propagate in all the following code. Finally, in general it is better to avoid using namespace std; in the header part. This is because, if you ever split the declaration of Student in a separate header file, than every code file which include such a header will "inherit" the using namespace std; which could, possibly, collide with other included headers.
In summary an even better version of your code is
#include <string>
template <unsigned int MAX_GRADES>
struct Student
{
std::string id;
std::string name;
double grades[MAX_GRADES];
double average;
};
Student<5> *update_list;
int main()
{
Student<5> *n = new Student<5>;
delete n;
return 0;
}
The problem is in this part of the code:
int main()
{
Student *n = (*Student) malloc(sizeof(n));
return 0;
}
Understanding that '*' operator is an indirection operator in C++ would help in identifying the problem.
https://msdn.microsoft.com/en-us/library/caaw7h5s.aspx
You are not trying to extract value of Student structure, instead you are trying to type cast void * returned from malloc. Correct way to do it is:
Student *n = new Student (correct C++ way of doing things - using new operator)
This will give you a pointer to dynamically created Student structure. If you intend to create a dynamic array of Student, you would do:
Student *n = new Student[5]
Depending on your usage, you might want to consider an easy and C++ STL way of doing as: std::vector<Student> or std::list<Student>.
Look up for STL (Standard Template Libraries) in C++ and you should be able to get more details.
If you are in c++, don't use "malloc" to allocate memory if you can use "new":
Student* student = new Student();
In addition to allocating space, "new" will also call the struct's constructor which will allow for initialization. The syntax is also less error-prone.
You'll also notice my variable naming. In my example I chose "student" instead of "n" because it's more descriptive to the reader.

How to move address of a string to a function in c++ [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
I was trying to send the address of a string to a function in C++ I'm but facing problems like in the code below:
#include<iostream>
#include<string>
using namespace std;
void try2(string *a){
cout<<a[2];
}
int main(){
string a;
getline(cin,a);//string length is greater than 10
try2(&a);
}
I am doing the same that we do for string in C. But I don't have that much idea about C++. Please suggest and describe how string behaves in C++.
You can pass a string into a function as an argument and take a string reference as a parameter in the function. But you need to understand that a string isn't an array, it is an object of the string class. The reason you can use indexing on a string is because the [] operator is overloaded for the string class.
What you were doing above is passing a pointer. For it to work the way you had done it your function would have to dereference the pointer:
#include<iostream>
#include<string>
using namespace std;
void try2(string *a){
cout<<(*a)[2];
return;
}
int main(){
string a;
getline(cin,a);//string length is greater than 10
try2(&a);
}
This would allow you to print the third character of the string object passed by reference to the function.
Note: don't use try as a function name as it is already reserved by many languages for the try-catch block syntax and can confuse the compiler.
You are accessing an single string as array of strings, which it is not. If you are trying to access the 2nd char of the string you have to dereference it first and then access the char like this:
#include<iostream>
#include<string>
using namespace std;
void try(string *a){
cout<<(*a)[2];
}
int main(){
string a;
getline(cin,a);//string length is greater than 10
try(&a);
}
This is because in c++ arrays and pointer are very close to each other.
*a and a[0] are almost the same which means using a[2] on a pointer isd the same as using *(a+2).
You have to keep in mind that you are not using an c-string here bit an c++-std::string which is an object and not an simple memory structure like in c.
So you first have to dereference the object before you can use it's overloaded []-operator to acess it's members (chars in this case).

whats the exact return of value in " " in c? is it a pointer? [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions concerning problems with code you've written must describe the specific problem — and include valid code to reproduce it — in the question itself. See SSCCE.org for guidance.
Closed 9 years ago.
Improve this question
I know that "Ali" is char array with 4 character: 'A' 'l' 'i' NULL
What i wanna know is the return value of it.
for example strcpy needs two pointer as input. why is the code below working:
char mstr[10]={};
strcpy(mstr,"Working...");
but this is not :
char *names[5]={"Ali","Reza","Hassan","Ahmad","Mohammad"};
"Ali" is a pointer to 'A' character or not?!
problem fixed!!! (i cant understand why?! i just add something to print them!) :
#include <stdio.h>
#include <conio.h>
#include <string.h>
int main()
{
char mstr[10]={};
strcpy(mstr,"Working...");
char *names[5]={"Ali","Reza","Hassan","Ahmad","Mohammad"};
int i;
//print :
for(i=0;i<5;i++)
{
puts(names[i]);
}
getch();
return 0;
}
I think i find out what happened here. my second code is completely correct in C. I was compiling it as a c++ file (it was a cpp file)
By the way error was : [Error] invalid conversion from 'char' to 'const char*' [-fpermissive]
C++ has different rules and by default it defined 5 const char arrays not char arrays.
I think it was the answer.
In C, this declaration:
char *names[5]={"Ali","Reza","Hassan","Ahmad","Mohammad"};
is perfectly legal, but potentially dangerous. It defines names as an array of 5 char* pointers, each of which points to the first character of a string literal. The problem is that attempting to modify a string literal has undefined behavior (string literals aren't const for historical reasons). So this declaration allows you to do something like:
names[0][0] = 'E'; /* rename Ali to Eli? */
with no complaint from the compiler; it's likely to crash during execution. (A compiler is permitted, but not required, to warn about this.)
The above should be written as:
const char *names[5]={"Ali","Reza","Hassan","Ahmad","Mohammad"};
which makes names an array of 5 pointers to const (read-only) char.
As for why the code is not working for you, it's because you attempted to compile it as C++ (which you mentioned only in a commment). C++ is a different language than C, and has different rules. (In C++ the conversion is permitted but deprecated.) If you want to ask about C++, please post a new question with the C++ tag -- and be sure to clearly show the exact error message in the body of the question, not buried in a comment.
Study the following - perhaps it will help:
#include <stdio.h>
#include <strings.h>
int main(int argc, char **argv)
{
char mstr[11]; /* must be **11** elements in size to hold "Working..." */
char *names[5]={"Ali","Reza","Hassan","Ahmad","Mohammad"};
int i;
strcpy(mstr, "Working...");
printf("Print #1 - mstr='%s'\n", mstr);
for(i = 0 ; i < sizeof(names)/sizeof(names[0]) ; ++i)
printf("Print #2 - names[%d] = '%s'\n", i, names[i]);
}
Share and enjoy.
Strings in C are pointers to char (= char *). The value of "foo" is, as you said, a pointer. The reason your second example doesn't work is that char *names[5] is a pointer to char * (= char **). It's not a string, it's an array of strings, and since arrays are pointers, it's a pointer to a string. Since strings are arrays (= pointers) of characters, it's a pointer-to-a-pointer-to-char.