medication createMedication(char name[], float concentration, int quantity, float price)
{
medication m;
strcpy(m.name, name);
m.concentration = concentration;
m.price = price;
m.quantity = quantity;
return m;
}
I get the uninitialized local variable "m" used error for line 10(where the strcpy() function is) and I don't know why.
The header file that it's using is:
#pragma once
typedef struct {
char* name;
float concentration;
int quantity;
float price;
}medication;
medication createMedication(char name[], float concentration, int quantity, float price);
char* getName(medication *m);
float getConcentration(medication *m);
int getQuantity(medication *m);
float getPrice(medication *m);
And the whole file:
#include <stdlib.h>
#include "medication.h"
#include <string.h>
#include <stdio.h>
#pragma warning(disable : 4996)
medication createMedication(char name[], float concentration, int quantity, float price)
{
medication m;
strcpy(m.name, name);
m.concentration = concentration;
m.price = price;
m.quantity = quantity;
return m;
}
char* getName(medication* m)
{
return m->name;
}
float getConcentration(medication* m)
{
return m->concentration;
}
float getPrice(medication* m)
{
return m->price;
}
int getQuantity(medication* m)
{
return m->quantity;
}
void toString(medication m, char str[])
{
sprintf(str, "Medication %s: Concentration:%f , Price:%f ,Quantity:%d", m.name,m.concentration,m.price,m.quantity);
typedef struct {
char* name;
float concentration;
int quantity;
float price;
}medication;
Here you have declared the char pointer vaiable "name" but you you haven't allocated memory for this pointer. So it may be pointing to some garbage value or address. You have to allocate memory before copying any data to this pointer "name". After declaration of "m" variable you have to allocate memory for "name" pointer.
medication m;
m.name = (char *)malloc(size);
name variable inside medication struct is culprit in this case.
in G++ this code works fine. but Visual Studio Compiler does not work.
I have changed char *name to char name[256 {or any size}].
This should work
Related
I created a program that uses arrays and array pointers to store a user's animal name, category of animal, and age. But when I run it, there is a segmentation fault after I type the name age and category. I was wondering if someone could guide me in how to fix it, I am very new to C programming.
This is the task I am supposed to complete:
Write a program that defines an animal data type, with an animal name, age, and category (cat, dog, etc.), as well as an animal array type that stores an array of animal pointers. Your program will prompt the user to enter the data for as many animals as they wish. It will initialize a dynamically allocated animal structure for each animal, and it will store each animal in an instance of the animal array structure. Your program will then print all the animal information to the screen. You will upload your C program as one file.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct {
char *name;
char *category;
int age;
} AnimalType;
typedef struct {
AnimalType basicInfo;
AnimalType *arr[];
} AnimalArrayType;
void initAnimal(char *n, char *c, int a, AnimalArrayType *ar);
void printAnimal(const AnimalArrayType *stuPtr);
int main() {
AnimalArrayType *array;
int numAn;
char name[20];
char category[20];
int age;
printf("Please enter the number of animals you want to input: ");
scanf("%d", &numAn);
array = calloc(numAn, sizeof(AnimalArrayType));
for (int i=0; i<numAn; ++i) {
printf("Enter animal name: ");
scanf("%s", name);
printf("Enter their category: ");
scanf("%s", category);
printf("Enter age: ");
scanf("%d", &age);
initAnimal(name, category, age, array + I);
}
printf("\n LIST:\n");
for (int i=0; i<numAn; ++i) {
printAnimal(array + I);
}
return 0;
}
void initAnimal(char *n, char *c, int a, AnimalArrayType *ar)
{
strcpy(ar->basicInfo.name, n);
strcpy(ar->basicInfo.category, c);
ar->basicInfo.age = a;
}
void printAnimal(const AnimalArrayType *stuPtr)
{
printf("Animal: %s, Category: %s age %d\n",
stuPtr->basicInfo.name, stuPtr->basicInfo.category,
stuPtr->basicInfo.age);
}
The char *name and char *category fields in the AnimalType struct are being initialized to NULL (from the call to calloc()), but you don't allocate any char[] memory for them to point at afterwards, so you end up crashing in initAnimal() when it tries to copy data into those fields using strcpy().
You need to either:
change those fields into char[] arrays instead of char* pointers:
typedef struct {
char name[20];
char category[20];
int age;
} AnimalType;
allocate memory for them to point at, such as from strdup():
typedef struct {
char *name;
char *category;
int age;
} AnimalType;
...
void initAnimal(char *n, char *c, int a, AnimalArrayType *ar)
{
ar->basicInfo.name = strdup(n);
ar->basicInfo.category = strdup(c);
ar->basicInfo.age = a;
}
Don't forget to free() anything you dynamically allocate when you are done using it.
I have an object allocated on the heap. The object will be destroyed from the heap, but I need to preserve it, preferably through copying it and saving the pointer to it.
An example
#include <stdio.h>
#include <stdlib.h>
struct Human
{
int age;
char sex;
float height;
float weight;
};
struct Human *human;
void create_human(int age, char sex, float height, float weight)
{
struct Human *A = (struct Human *) malloc(sizeof(struct Human));
A->age = age;
A->sex = sex;
A->height = height;
A->weight = weight;
// copy A and save the pointer to the copy in the global variable
free(A);
}
int main()
{
create_human(22, 'M', 1.90, 100.0);
printf("Age: %d\tSex: %c\tHeight %.2f\tWeight %.2f\n", human->age, human->sex, human->height, human->weight);
}
Here I need to copy the object A points to and make human point to the copy.
human = (struct Human *) malloc(sizeof(struct Human));
memcpy(human, A, sizeof(struct Human));
If there were pointers to other structs inside Human, this would be slightly more complex!
Edit:
More elegant solution suggested by StoryTeller in comments:
human = (struct Human *) malloc(sizeof(struct Human));
*human = *A;
You probably want something like this:
no more obscure copying into a global variable (avoid global variables whenever possible)
no more cast for malloc
free called once we're done with the created human and not before
#include <stdio.h>
#include <stdlib.h>
struct Human
{
int age;
char sex;
float height;
float weight;
};
struct Human *create_human(int age, char sex, float height, float weight)
{
struct Human *A = malloc(sizeof(struct Human)); // no need to cast
A->age = age;
A->sex = sex;
A->height = height;
A->weight = weight;
return A;
}
int main()
{
struct Human *human = create_human(22, 'M', 1.90, 100.0);
printf("Age: %d\tSex: %c\tHeight %.2f\tWeight %.2f\n", human->age, human->sex, human->height, human->weight);
free(human);
}
If you absolutely want to copy your human into a global variable, you can still do it:
...
struct human *globalhuman;
...
int main()
{
globalhuman = create_human(22, 'M', 1.90, 100.0);
printf("Age: %d\tSex: %c\tHeight %.2f\tWeight %.2f\n", globalhuman ->age, globalhuman ->sex, globalhuman ->height, globalhuman ->weight);
free(globalhuman );
}
Recently, I took a subject called Data structure. I've created a program to try out my knowledge but don't know why the program did not work. I can't figure it out so I post it here to ask for solution. I hope people can help me. I am newbie here. So please ignore my opinion if my opinion is found annoying.
#include <stdio.h>
int main()
{
struct Book
{
char title[50];
int year;
float price;
};
int i;
struct Book books[50];
books[0].title="Bullshit";
books[0].year=132;
books[0].price=146.9;
books[1]=(struct Book){"Money",1344,189.4
};
for(i=0;i<2;i++)
{
printf("Book Title is : %s\n",books[i].title);
printf("Book Year is %d\n",books[i].year);
printf("Book price is %3.2f\n",books[i].price);
printf("\n\n");
}
}
1 I would make declaration of struct rather outside main than inside
2 Try changing char title[50] to char *title
#include <stdio.h>
struct Book {
char *title;
int year;
float price;
};
int main() {
int i;
struct Book books[50];
books[0].title = "Bullshit";
books[0].year = 132;
books[0].price = 146.9;
books[1] = (struct Book) {"Money", 1344, 189.4
};
for (i = 0; i < 2; i++) {
printf("Book Title is : %s\n", books[i].title);
printf("Book Year is %d\n", books[i].year);
printf("Book price is %3.2f\n", books[i].price);
printf("\n\n");
}
}
Why it didn't worked before?
In c arrays are not assignable by = operator.
You could do something like instead title[0] = 'B'; title[1] = 'u', etc....(or use strcpy which does it for you).
char *x is not really an array, it's just pointer to single char.
If we write x = "abc", we are telling the compiler: set x to 'a', next byte to 'b', next to 'c', and next to 0(not '0', just zero).
And when you do printf("%s",x), the printf function prints chars from the place in memory specified by x until it see 0 byte.
char *x = "abcd";
char *y = x;
while(*y != 0){ // this loop acts like printf("%s",x);
printf("%c",*y);
y++;
}
See also this and this question.
Or if you are using c++, not c, use std::string:
#include <cstdio>
#include <string>
struct Book {
std::string title;
int year;
float price;
Book(std::string t, int y, float p) {
title = t;
year = y;
price = p;
}
};
int main() {
int i;
Book books[50];
books[0].title = "Bullshit";
books[0].year = 132;
books[0].price = 146.9;
books[1] = Book(std::string("Money"), 1344, 189.4);
for (i = 0; i < 2; i++) {
printf("Book Title is : %s\n", books[i].title.c_str());
printf("Book Year is %d\n", books[i].year);
printf("Book price is %3.2f\n", books[i].price);
printf("\n\n");
}
}
this
books[0].title="Bullshit";
is not valid. title is defined as char[50]. Either do
strcpy(books[0].title, "BS");
This will copy the bytes of BS to title. Or do
struct Book
{
char *title;
int year;
float price;
};
...
books[0].title = strdup("BS");
This sets title up as a pointer to a char string. strdup will allocate space for the string and copy BS to that space. You will have to free that allocated space.
Or - the best. Use std::string
struct Book
{
std::string title;
int year;
float price;
};
....
books[0].title = "BS";
And as a final thought - life goes better with std::vector instead of raw arrays
This is my code in which if student marks is greater than 85,scholarship status will be changed to sanctioned, but after updating it is not printing
#include<stdio.h>
#include<string.h>
struct scholor
{
char name[25];
int sem;
int marks;
char status;
};
void sanction(int m, char *s)
{
if(m>85)
{
char p[15]="sanctioned";
char *r;
r=p;
while(*r!='\0')
{
*s=*r;
s++;
r++;
}
*s='\0';
}
}
int main()
{
struct scholor s1;
scanf("%s%d%d%s",&s1.name,&s1.sem,&s1.marks,&s1.status);
sanction(s1.marks,&s1.status);
printf("%s",s1.status);
}
status is a single char but you are storing a string into it, effectively doing out of bounds access (undefined behaviour). Change it to an array and then you'll be able to copy.
struct scholor
{
char name[25];
int sem;
int marks;
char status[128];
};
and adjust the calls and passing (since status is an array now -- its name gets converted into a pointer t its first element when passed to functions):
scanf("%s%d%d%s",s1.name,&s1.sem,&s1.marks,s1.status);
sanction(s1.marks,s1.status);
printf("%s",s1.status);
Other suggestions:
1. Use a standard prototype for main such as: int main(void)
2. You could usr strcpy to copy the string as opposed to doing it yourself.
Your struct should have status as a character array not a character .Moreover when you scanf an array dont write & before because the name itself points to the assdress of the first element.Your corrected program is :
struct scholor
{
char name[25];
int sem;
int marks;
char status[16];
};
void sanction(int m, char *s)
{
if(m>85)
{
char p[15]="sanctioned";
char *r;
r=p;
while(*r!='\0')
{
*s=*r;
s++;
r++;
}
*s='\0';
}
}
int main()
{
struct scholor s1;
scanf("%s%d%d%s",s1.name,&s1.sem,&s1.marks,s1.status);
sanction(s1.marks,s1.status);
printf("%s",s1.status);
}
Does anyone know why the code below does not work with chars? It works with ints but when I want to use char to initialize structure it fails and gives a warning like:
warning: assignment makes integer from pointer without a cast
I don't know what this warning means.
#include <stdio.h>
#include <stdlib.h>
struct complex {
int re;
int im;
char name;
};
struct complex initialize (int k, int l, char nazwa)
{
struct complex x;
x.re = k;
x.im = l;
x.name= nazwa;
return x;
}
int main ()
{
struct complex e;
struct complex f;
int a;
int b;
char o;
int c;
int d;
char p;
a=5;
b=6;
o="t";
e = initialize (a, b, o);
c=8;
d=3;
p="u";
f=initialize (c, d, p);
printf("c1 = (%d,%d)\nc2 = (%d,%d)\n name 1=%s name 2=%s\n", e.re , e.im, f.re, f.im, e.name, f.name);
return 0;
}
"u" is not a char. it is a string. a char array. you want 'u' instead. But then you will have only one-character names, and you will need to replace the %s in printf with %c.
Unless you really want a string, and if so change your char in the struct to be const char*. The same goes the function parameter:
struct complex {
int re;
int im;
const char* name;
};
struct complex initialize (int k, int l, const char* nazwa) {
...
}
const char* o;
const char* p;
Note that you can initialize variables, and structs. your code can be like this:
void print_complex(int n, struct complex c) {
printf("c %d = (%d,%d)\n", n, c.re , c.im);
printf("name=%s\n", c.name);
}
int main () {
struct complex e = { 5, 6, "t" };
struct complex f = { 8, 3, "u" };
print_complex(1, e);
print_complex(2, f);
return 0;
}