Unititialized structure definition [closed] - c

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
I am having trouble with structure definitions. I understand the syntax but can't use it correctly to make a working program. My assignment is to define a structure type element_t to represent one of the elements of the periodic table. Components should include atomic number, name, symbol, class, weight and a seven element array of integers for the number of electrons in each shell. The following are the components of an element_t structure for sodium.
11 Sodium Na alkali_metal 22.9898 2 8 1 0 0 0 0
Define and test I/O functions scan_element and print_element.
Here is my code... but no worky. I dont understand why the compiler says I haven't initialized element_t. Thanks in advance.
***Ended up with the following code, also added the appropriate loops and & signs although it is not shown below and everything worked fine. I was curious to know how the powerpoint slides in my class used {2 8 1 0 0 0 0} to populate the int array instead of a loop. The book I am using uses the loop method as well but I wanted to try the {} way of doing it. Thanks again.
#include <stdio.h>
#include <string.h>
typedef struct {
int atomic_num;
char* element_name; revised: char element_name[25];
char* element_symbol; revised: element_symbol[2];
char* element_class; revised: char element_class[25];
double atomic_weight;
int electrons[7];
} element_t;
int scan_element(); revised: element_t scan_element();
void print_element(element_t my_element);
int scan_element() {
element_t my_element;
printf("Enter Atomic Number> ");
scanf("%d", my_element.atomic_num);
printf("Enter Element Name> ");
scanf("%s", my_element.element_name);
printf("Enter Element Symbol> ");
scanf("%s", my_element.element_symbol);
printf("Enter Element Class> ");
scanf("%s", my_element.element_class);
printf("Enter Atomic Weight> ");
scanf("%lf", my_element.atomic_weight);
printf("Enter Electons in each shell> ");
scanf("%d", my_element.electrons);
print_element(my_element);
return 0;
}
void print_element(element_t my_element) {
printf("%d %s %s %s %lf %d \n",my_element.atomic_num,my_element.element_name, my_element.element_symbol,my_element.element_class,my_element.atomic_weight,&my_element.electrons);
}
int main()
{
scan_element(); revised: print_element(scan_element());
return 0;
}

I've identified some problems in your code:
1)When reading with scanf non-pointer types(like int or float), use the & operator. Scanf needs a pointer to your variable, not the variable itself.
2)If you declare your strings as dynamic (char*), be sure to use malloc to allocate memory for them. Otherwise declare them statically like char my_string[30].
3)Your scan_element function should return an element_t structure, not an int. Alternatively you could pass a pointer to an existing element_t structure and modify it in your function.
4)You cannot read/print a int array directly using scanf/printf. Every element must be read separately.
5)Your scan_element function shouldn't probably contain print_element :P
If you want to learn more about Console I/O in ANSI C, perhaps this article could be useful.
Here is the corrected code:
include <stdio.h>
#include <string.h>
typedef struct {
int atomic_num;
char element_name[30];
char element_symbol[3];
char element_class[30];
double atomic_weight;
int electrons[7];
} element_t;
element_t scan_element();
void print_element(element_t my_element);
element_t scan_element() {
int i = 0;
element_t my_element;
printf("Enter Atomic Number> ");
scanf("%d", &my_element.atomic_num);
printf("Enter Element Name> ");
scanf("%s", my_element.element_name);
printf("Enter Element Symbol> ");
scanf("%s", my_element.element_symbol);
printf("Enter Element Class> ");
scanf("%s", my_element.element_class);
printf("Enter Atomic Weight> ");
scanf("%lf", &my_element.atomic_weight);
for(i = 0; i<7; i++)
{
printf("Enter Electon - electron nr %d\n",i);
scanf("%d", &my_element.electrons[i]);
}
return my_element;
}
void print_element(element_t my_element) {
int i;
printf("%d %s %s %s %lf\n",
my_element.atomic_num,
my_element.element_name,
my_element.element_symbol,
my_element.element_class,
my_element.atomic_weight);
for(i = 0; i<7; i++)
{
printf("%d",my_element.electrons[i]);
}
puts("\n");
}
int main()
{
element_t val = scan_element();
print_element(val);
return 0;
}

Related

C function to fill an array with strings from user input

I am stuck on a programming assignment in C. The user has to enter a number specifying the size of an array no bigger than 10 elements which will store the names of students. This must be done in a separate function from the main function called getNames. Each name can be up to 14 characters and getNames must be invoked from within the main function. Here is my code:
#include <stdio.h>
void getNames(char *a, int n){
int i;
for(i=0; i<n; i++){
printf("Enter a name: ");
scanf("%s", &a[i]);
}
}
void printNames(char *a, int n){
int i;
for(i=0; i<n; i++){
printf("%s\n", &a[i]);
}
}
void main(){
int num; //number of names in array 'names'
printf("Num of students: ");
scanf("%d", &num);
char names[num][15]; //each name is 14 characters plus
//a null character
getNames(names[num], num);
printNames(names[num], num);
}
The code compiles and runs without syntax errors but the array is not filled correctly. For example:
Num of students: 5
Enter a name: Jeb
Enter a name: Bob
Enter a name: Bill
Enter a name: Val
Enter a name: Matt
returns:
JBBVMatt
BBVMatt
BVMatt
VMatt
Matt
Clearly there is an issue writing to the array but I am not sure what it is.
For this assignment our professor was adamant that we cannot use any global variables. His wording was rather vague about how we should implement this. My first thought would be to move the for loop in getNames into the main function and just calling getNames repeatedly but I would like a solution that incorporates that into getNames. I'm new to C, having mostly dealt with Java so please bear with me. Any help would be appreciated.
If the code you have posted is exactly the code you are using, then it is invoking undefined behavior by accessing a memory location that your program does not own: getNames(names[num], num);.
Array indexing in C goes from 0 to n-1. (or from names[0]-names[num-1]) Same in other similar calls.
next issue is the function prototypes to accommodate;
char names[num][15];
The function needs to send the address of an array of arrays. See edits on code to show the difference.
Next issue are the following statements, see comments after each
getNames(names[num], num);//names[n] points to memory beyond what is owned.
//should point to address of beginning of memory &names[0]
printNames(names[num], num);//ditto
Working code example, see edits to explain:
//void getNames(char *a, int n){//change *a to either a[][15] or (*a)
void getNames(char a[][15], int n){
int i;
for(i=0; i<n; i++){
printf("Enter a name: ");
scanf("%s", a[i]);
}
}
//void printNames(char *a, int n){ //change *a to either a[][15] or (*a)
void printNames(char a[][15], int n){
int i;
for(i=0; i<n; i++){
printf("%s\n", a[i]);
}
}
void main(){
int num; //number of names in array 'names'
printf("Num of students: ");
scanf("%d", &num);
char names[num][15]; //each name is 14 characters plus
//a null character
//getNames(names[num], num);//names[n] points to memory beyond what is owned.
//printNames(names[num], num);//ditto
getNames(&names[0], num);
printNames(&names[0], num);
}
you can do following
Method
in main function call as below
getNames(names, num);
printNames(names, num);
and change the functions as below
void getNames(char (*a)[15], int n)
{
...
}
void printNames(char (*a)[15], int n)
{
...
}
Method , in main calls remain same
void getNames(char a[5][15], int n)
and
void printNames(char a[5][15], int n)
But instead of using hard values better to use #define row and col sizes

Structures and Strings in C

I started learning C and I wrote a short program implementing structures. For now, it only has a structure and a short function that is supposed to fill one of the structures (several are stored in an array). Program gets all the values (currently only for one structure to help me see what's going on) and the problem starts in main, in
printf("%s", tablica[0].nazwa);
Because program stops responding (no errors or warnings before).
If I put:
printf("%d", tablica[0].x);
It will print the value I put as x, so I know there is some problem with string in printf (but I can't figure out why). It's probably easy, but I'm just a beginner.
#include <stdio.h>
#include <string.h>
struct struktura
{
char *nazwa;
double x, y, z;
};
int wczytaj(struct struktura tab[])
{
int i;
for ( i = 0; i<1; i++)
{
printf("Podaj nazwe: ");
scanf("%s", &tab[i].nazwa);
printf("Podaj x: ");
scanf("%i", &tab[i].x);
printf("Podaj y: ");
scanf("%i", &tab[i].y);
printf("Podaj z: ");
scanf("%i", &tab[i].z);
};
return 0;
}
int main(struct struktura* a)
{ int i;
struct struktura tablica[6];
int wyniki[6][6];
wczytaj(tablica);
printf("%s", tablica[0].nazwa);
}
Sorry for some names being in Polish, I can correct that, but I hope it doesn't blur the program).
You are using the wrong format specifiers for double types in
scanf("%i", &tab[i].x);
printf("%d", tablica[0].x);
and others. They should be
scanf("%lf", &tab[i].x);
printf("%f", tablica[0].x);
Also this string input
scanf("%s", &tab[i].nazwa);
should lose the & ampersand like this
scanf("%s", tab[i].nazwa);
but even so nazwa has no memory allocated to it. As suggested in comments you could get going with a fixed array like
struct struktura
{
char nazwa[30];
double x, y, z;
};
You have a very unsual signature for main, which is usually
int main(void)
or
int main(int argc, char *argv[])

Proper use of structures and pointers

I have to declare a vector with the "struct" type which, for every n students, it creates a value for the group that student belongs to (which is like a counter), their names and their grades.
The program has to output the name of the students with the highest grade found in these groups. I have to allocate the vector on the heap (I only know the theoretical explanation for heap, but I have no idea how to apply it) and I have to go through the vector using pointers.
For example if I give n the value 4, there will be 4 students and the program will output the maximum grade together with their names as shown here.
This will output Ana 10 and Eva 10.
I gave it a try, but I have no idea how to expand it or fix it so I appreciate all the help I can get with explanations if possible on the practical application of heap and pointers in this type of problem.
#include <stdio.h>
#include <stdlib.h>
struct students {
int group;
char name[20];
int grade;
};
int main()
{
int v[100], n, i;
scanf("%d", n);
for (i = 0; i < n; i++) {
v[i].group = i;
scanf("%s", v[i].name);
scanf("%d", v[i].grade);
}
for (i = 0; i < n; i++) {
printf("%d", v[i].group);
printf("%s", v[i].name);
printf("%d", v[i].grade);
}
return 0;
}
Here I was just trying to create the vector, nothing works though..
It appears, int v[100]; is not quite what you want. Remove that.
You can follow either of two ways.
Use a VLA. After scanning the value of n from user, define the array like struct students v[n]; and carry on.
Define a fixed size array, like struct students v[100];, and use the size to limit the loop conditions.
That said,
scanf("%d", n); should be scanf("%d", &n);, as %d expects a pointer to integer type argument for scanf(). Same goes for other cases, too.
scanf("%s", v[i].name); should better be scanf("%19s", v[i].name); to avoid the possibility of buffer overflow by overly-long inputs.
Even though you are asking for the number of students (groups) using scanf, you hardcoded the upper bound of this value using v[100]. So, I passed your input variable n (the number of students) to malloc in order to allocate the space you need for creating an array of n students.
Also, I used qsort to sort the input array v where the last element would be the max value. Here qsort accepts an array of structs and deference the pointers passed to the comp function to calculate the difference of the comparison.
Finally, I printed the sorted array of structs in the last loop.
#include <stdio.h>
#include <stdlib.h>
struct students {
int group;
char name[20];
int grade;
};
int comp(const void *a, const void *b)
{
return ((((struct students *)a)->grade > ((struct students *)b)->grade) -
(((struct students *)a)->grade < ((struct students *)b)->grade));
}
int main()
{
int n;
printf("Enter number of groups: ");
scanf("%d", &n);
printf("\n");
struct students *v = malloc(n * sizeof(struct students));
int i;
for(i = 0; i < n; i++)
{
v[i].group = i;
printf("\nName: ");
scanf("%s", v[i].name);
printf("Grade: ");
scanf("%d", &v[i].grade);
}
qsort(v, n, sizeof(*v), comp);
for(i = 0; i < n; i++)
{
printf("Group %d, Name %s, grade %d\n", v[i].group, v[i].name, v[i].grade);
}
return (0);
}
You need to replace the standalone array v[100], with an array of structs referencing your structure:
struct students v[100];
However, if you want to use malloc to allocate memory on the heap, you will need to do something like this:
struct students *students = malloc(n * sizeof(struct students));
/* Check void* return pointer from malloc(), just to be safe */
if (students == NULL) {
/* Exit program */
}
and free the requested memory from malloc() at the end, like this:
free(students);
students = NULL;
Additionally, adding to #Sourav Ghosh's answer, it is also good to check the return value of scanf(), especially when dealing with integers.
Instead of simply:
scanf("%d", &n);
A more safe way is this:
if (scanf("%d", &n) != 1) {
/* Exit program */
}
With all this said, your program could look something like this:
#include <stdio.h>
#include <stdlib.h>
#define NAMESTRLEN 20
typedef struct { /* you can use typedef to avoid writing 'struct student' everywhere */
int group;
char name[NAMESTRLEN+1];
int grade;
} student_t;
int
main(void) {
int n, i;
printf("Enter number of students: ");
if (scanf("%d", &n) != 1) {
printf("Invalid input.\n");
exit(EXIT_FAILURE);
}
student_t *students = malloc(n * sizeof(*students));
if (!students) {
printf("Cannot allocate memory for %d structs.\n", n);
exit(EXIT_FAILURE);
}
for (i = 0; i < n; i++) {
students[i].group = i;
printf("Enter student name: ");
scanf("%20s", students[i].name);
printf("Enter students grade: ");
if (scanf("%d", &(students[i].grade)) != 1) {
printf("Invalid grade entered.\n");
exit(EXIT_FAILURE);
}
}
printf("\nStudent Information:\n");
for (i = 0; i < n; i++) {
printf("Group: %d Name: %s Grade: %d\n",
students[i].group,
students[i].name,
students[i].grade);
}
free(students);
students = NULL;
return 0;
}

Expression must have class type error

I'm working on a homework assignment and I've hit a brick wall. I think I have all of the code that I need, I just need to get the program to compile. The object of the assignment is
Create a structure to hold student names and averages. The structure should contain a first name, last name and an integer grade average.
Then:
Write a program that will do the following:
1.) Create an array of pointers to these student structures.
2.) Prompt the user for names and averages.
3.) After you get the student’s information use malloc to provide the memory to store the information.
4.) Place the address of the student, returned by malloc, into the pointer array.
5.) AFTER the user indicates there are no more students:
Search the data entered and find the highest and lowest grade
average.
a)Print the name and grade for the highest grade
b)Print the name and grade for the lowest grade
c)Print the average of all grades entered
Here is my code:
#include "stdafx.h"
#include <string.h>
#include <stdlib.h>
#define SIZE 25
int enterStudents (int ePointArray[SIZE]);
void searchData (int *sPointArray, int *sHigh, int *sLow);
int calculateAvg (int, int *avgPointArray);
void printData (int, int *pHigh, int *pLow);
struct student
{
char firstName[20];
char lastName[20];
int average;
};
int main()
{
int pointArray[SIZE], high[3], low[3];
int i = 0, studentCounter, avgGrade;
for (i = 0; i < SIZE; i++)
pointArray[i] = 0;
studentCounter = enterStudents(pointArray);
searchData(pointArray, high, low);
avgGrade = calculateAvg(studentCounter, pointArray);
printData(avgGrade, high, low);
return 0;
}
int enterStudents (int ePointArray[SIZE])
{
char tempFname[20], tempLname[20], yesNo[2] = "y";
int tempAvg, counter = 0;
int *studPtr;
struct student aStud={"\0", "\0", 0};
while( counter < SIZE && strcmp(yesNo, "y")==0)
{
printf(" Enter first name: ");
scanf("%s", tempFname);
printf(" Enter last name: ");
scanf("%s", tempLname);
printf(" Enter grade average:");
scanf("%d", tempAvg);
strcpy(aStud.firstName, tempFname);
strcpy(aStud.lastName, tempLname);
aStud.average = tempAvg;
studPtr = malloc(sizeof(struct student));
ePointArray[counter] = *studPtr;
counter++;
printf("/n");
printf(" Do you have more students? yes or no:");
scanf("%s", yesNo);
}
return counter;
}
void searchData (int sPointArray[SIZE], int sHigh[3], int sLow[3])
{
int searchCounter = 0;
while( searchCounter = 0)
{
if( *sPointArray[searchCounter].average > *sPointArray[searchCounter+1].average)
{
sHigh[0] = &sPointArray[searchCounter].firstName;
sHigh[1] = &sPointArray[searchCounter].lastName;
sHigh[2] = &sPointArray[searchCounter].average;
}
if( *sPointArray[searchCounter].average < *sPointArray[searchCounter+1].average)
{
sLow[0] = &sPointArray[searchCounter].firstName;
sLow[1] = &sPointArray[searchCounter].lastName;
sLow[3] = &sPointArray[searchCounter].average;
}
searchCounter++;
}
}
int calculateAvg( int totalStudents, int avgPointArray[SIZE])
{
int sum = 0;
int avgCounter;
double overallAvg;
for( avgCounter = 0; avgCounter < totalStudents; avgCounter++)
sum = sum + *avgPointArray[avgCounter].average;
overallAvg = sum/totalStudents;
return overallAvg;
}
void printData (int pAverage, int pHigh[3], int pLow[3])
{
printf(" Highest Grade: %s %s %d", pHigh[0], pHigh[1], pHigh[3]);
printf("/n");
printf(" Lowest Grade: %s %s %d", pLow[0], pLow[2], pLow[3]);
printf("/n");
printf(" Average Grade: %d",pAverage);
}
The main chunk of problems come from the searchData function. In the if statements, every occurrence of *sPointArray and &sPointArray is underlined in red and the error reads
"Error: expression must have class type"
The same thing also happens in the calculateAvg function with *avgPointArray in the for loop. I know that the error is a fairly common problem for noobie C programmers (i.e myself) and that it generally has to do with writing the code as a function instead of a statement or something like that, but I can't for the life of me find where I have went wrong. Any help would be highly appreciated. I've been working at this for so long my vision is blurring.
Also, for anyone who solves this in like two seconds and wants proof that I'm a true idiot, there is an error in the enterStudents function where it says StudPtr = malloc(sizeof...). The error shows under the assignment symbol and says
"Error: a value of type "void*" cannot be assigned to an entity of type "int*".
I understand this concept in theory, but some advice for how to fix it would be highly appreciated.
Thank you in advance for any help.
You declare the sPointArray as an array of integers, but use it as an array of structures.

Best way to resize/size arrays while the program is running

I am trying to take in array which contains some integer values/string values from the user, and not sure how long the array is going to be.. If i intitalise like array[500], i know it is a poor solution and poor programming skills.. How do i improve this?
Sample code below:
int main(void){
int t=0;
char str[200];
int count[20];
printf("Please enter the number of test cases(between 1 to 20):");
scanf("%d",&t);
for ( int i = 1; i<=t;i++)
{
printf("Please enter each of %i test case values:",i);
gets(str);
//set_create(str);
printf("\n");
}
for(int i = 0;i<t;i++)
{
prinf("%i",count[i]);
printf("\n");
}
return 0;
}
The code above is wrong definitely.. Need some help to improve the code...Thanks
Edited code:
int main(void){
int T=0;
int *count;
printf("Please enter the number of test cases(between 1 to 20):");
scanf("%d",&T);
count = malloc(T * sizeof *count);
for ( int i = 1; i<=T;i++)
{
printf("Please enter each of %i test case values:",i);
fgets(count);
printf("\n");
}
return 0;
}
Just use a pointer and malloc / realloc memory as needed. Don't use gets - it's unsafe and no longer in the standard. Use fgets instead.
For example, if you don't know how many count elements you need:
int *count;
scanf("%d", &t);
count = malloc(t * sizeof *count);
In such situation you can allocate memory for array in heap with functions malloc/calloc or on the stack with function alloca() (in header "alloca.h");

Resources