May I have some problem with memory allocated - c

I have this code and after the first write in the array(successful data write ) then we get null as message and I don't know why.
I have tried many things, please help me.
my code is:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct course {
int marks;
char *subject;
};
int main(int argc, char *argv[])
{
struct course *ptr;
int i, noOfRecords;
printf("Enter the number of records: ");
scanf("%d", &noOfRecords);
//Memory allocation for noOfRecords structures
ptr = (struct course *)malloc(noOfRecords * sizeof(struct course));
ptr->subject=(char*)malloc(20*sizeof(char));
for (i = 0; i < noOfRecords; ++i) {
printf("Enter the name of the subject and marks respectively:\n");
scanf("%s %d", (ptr + i)->subject, &(ptr + i)->marks);
}
printf("Displaying Information:\n");
for (i = 0; i < noOfRecords; ++i){
printf("%s\t%d\n", (ptr + i)->subject, (ptr + i)->marks);
}
return 0;
}

As stated in question comments, you need to allocate memory for ALL subject members, not just the first:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct course {
int marks;
char *subject;
};
int main(int argc, char *argv[])
{
struct course *ptr;
int i, noOfRecords;
printf("Enter the number of records: ");
scanf("%d", &noOfRecords);
//Memory allocation for noOfRecords structures
ptr = (struct course *)malloc(noOfRecords * sizeof(struct course));
for (i = 0; i < noOfRecords; ++i) {
printf("Enter the name of the subject and marks respectively:\n");
(ptr + i)->subject = (char*) malloc(20*sizeof(char));
scanf("%s %d", (ptr + i)->subject, &((ptr + i)->marks));
}
printf("Displaying Information:\n");
for (i = 0; i < noOfRecords; ++i) {
printf("%s\t%d\n", (ptr + i)->subject, (ptr + i)->marks);
}
return 0;
}
Also, I suggest you to:
Use a #define for subject max length
Always check user input or limit it (truncate or force to retype). You might get unexpected behaviors if user inserts more than 19 chars plus \0 for subject.
Use typedef struct {...} course;. It will be much easier to handle arrays.
Remember to free the memory you claimed.
As a result:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// From https://stackoverflow.com/a/17387990/2928168
#define MAX_SUBJECT "20"
typedef struct {
int marks;
char *subject;
} Course;
int main(int argc, char *argv[])
{
Course *courses;
int i, noOfRecords;
printf("Enter the number of records: ");
scanf("%d", &noOfRecords);
// Memory allocation for noOfRecords structures
courses = (Course *) malloc(noOfRecords * sizeof(Course));
for (i = 0; i < noOfRecords; ++i) {
printf("Enter the name of the subject and marks respectively:\n");
courses[i].subject = (char*) malloc(atoi(MAX_SUBJECT)*sizeof(char));
scanf("%" MAX_SUBJECT "s %d", courses[i].subject, &(courses[i].marks));
//fgets(courses[i].subject, sizeof(buf), stdin);
}
printf("Displaying Information:\n");
for (i = 0; i < noOfRecords; ++i) {
printf("%s\t%d\n", courses[i].subject, courses[i].marks);
free(courses[i].subject);
}
free(courses);
return 0;
}
Edit
You can even use the trick from https://stackoverflow.com/a/6671729/2928168 to increase performance:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_SUBJECT 20
#define Q(x) #x
#define QUOTE(x) Q(x)
#define MAX_SUBJECT_STR QUOTE(MAX_SUBJECT)
typedef struct {
int marks;
char *subject;
} Course;
int main(int argc, char *argv[])
{
Course *courses;
int i, noOfRecords;
printf("Enter the number of records: ");
scanf("%d", &noOfRecords);
// Memory allocation for noOfRecords structures
courses = (Course *) malloc(noOfRecords * sizeof(Course));
for (i = 0; i < noOfRecords; ++i) {
printf("Enter the name of the subject and marks respectively:\n");
courses[i].subject = (char*) malloc(MAX_SUBJECT*sizeof(char));
scanf("%" MAX_SUBJECT_STR "s %d", courses[i].subject, &(courses[i].marks));
//fgets(courses[i].subject, sizeof(buf), stdin);
}
printf("Displaying Information:\n");
for (i = 0; i < noOfRecords; ++i) {
printf("%s\t%d\n", courses[i].subject, courses[i].marks);
free(courses[i].subject);
}
free(courses);
return 0;
}

Related

How to add the array "Name" inside "Surname" by the indicated position number in C language?

Example:
name: John
surname: Smith
position: 2
result: JoSmithhn
Code:
#include <stdio.h>
#include <stdlib.h>
int main() {
char name[50] = "John";
char surname[50] = "Smith";
char result[50] = { 0 };
int pos;
printf("Position: ");
scanf_s("%d", &pos);
for (int i = 0; i < pos; ++i) {
result[i] = name[i];
}
for (int i = 0; i < surname[i]; i++) {
result[pos + i] = surname[i];
}
printf("%s\n", result);
system("pause");
return 0;
}
Be aware that result is as long as surname and name, so when they are together longer than 50 chars, you will lose data.
Something like this can implement your example without the need of for loops.
#include <stdio.h>
#include <string.h>
int main() {
char name[50] = "John";
char surname[50] = "Smith";
char result[100];
int pos;
printf("Position: ");
scanf("%d", &pos);
char buf[pos];
memcpy(buf, name, pos);
snprintf(result, 100, "%s%s%s\n", buf, surname, name + pos);
printf(result);
return 0;
}

Having a fatal error code - corrupted heap

New picture from an external compiler.. the exit code is ok?
enter image description here
This is the full code. I'm having a trouble program blows away after printing the wanted output to the screen. I guess it's a problem with the way I allocated memory for the array of structs, and the .name field of each struct in a for loop.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#define MAX_NAME_LEN 50
typedef struct stud
{
char *name;
int marks[4];
float avg;
}student;
student* Create_Class(int);
void Avg_Mark(student*);
void Print_One(student*);
void printExcellent(student*);
void main()
{
int size, i;
student *arr, *newArr;
printf("\nEnter the number of students: ");
scanf_s("%d", &size);
newArr = Create_Class(&size);
for (i = 0; i < size; i++)
{
printExcellent(newArr+i);
}
for (i=0;i<size;i++) free(newArr[i].name);
free(newArr);
_getch();
}
student* Create_Class(int size)
{
student *p;
char str[MAX_NAME_LEN];
int i, j;
p = (student*)calloc(size , sizeof(student));
if (!p)
{
printf("Memory allocation failure.");
exit(1);
}
for (i = 0; i < size; i++)
{
printf("Enter your name: ");
rewind(stdin);
gets(str);
p[i].name = (char*)calloc(strlen(str)+1,sizeof(char));
if (!(p[i].name))
{
printf("Memory allocation error!");
exit(1);
}
strcpy_s(p[i].name,50,str);
printf("Enter your marks: ");
for (j = 0; j < 4; j++)
{
scanf_s("%d", &p[i].marks[j]);
}
Avg_Mark(p + i);
}
return p;
}
void Avg_Mark(student* s)
{
int i, sum=0;
for (i = 0; i < 4; i++)
sum += s->marks[i];
s->avg = (float)sum / 4;
}
void Print_One(student* s)
{
printf("The average of %s is %.1f\n", s->name, s->avg);
}
void printExcellent(student* s)
{
if ((s->avg) > 85)
Print_One(s);
}
Gonna point out everything fishy I see for you:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#define MAX_NAME_LEN 50
typedef struct stud
{
char *name;
int marks[4];
float avg;
}student;
student* Create_Class(int);
void Avg_Mark(student*);
void Print_One(student*);
void printExcellent(student*);
void main()
{
int size, i;
student *arr, *newArr;
printf("\nEnter the number of students: ");
scanf_s("%d", &size);
// This is wrong. Remove the &...
newArr = Create_Class(&size);
for (i = 0; i < size; i++)
{
printExcellent(newArr+i);
}
for (i=0;i<size;i++) free(newArr[i].name);
free(newArr);
_getch();
}
student* Create_Class(int size)
{
student *p;
char str[MAX_NAME_LEN];
int i, j;
// Consider checking size for a sane value.
// Ok, allocate an array of students.
p = (student*)calloc(size , sizeof(student));
if (!p)
{
printf("Memory allocation failure.");
exit(1);
}
for (i = 0; i < size; i++)
{
printf("Enter your name: ");
// These 2 lines scare the heck out of me. I'd really do this differently.
// gets is the devil and the see:
// https://stackoverflow.com/questions/20052657/reversing-stdin-in-c
// for why this may not work well.
rewind(stdin);
gets(str);
// What if str is not a terminated string? Then 1 char of 0? Guess this is ok. Hope it doesn't overflow on the copy below though (consider fixed max size and not using a temporary)
p[i].name = (char*)calloc(strlen(str)+1,sizeof(char));
if (!(p[i].name))
{
printf("Memory allocation error!");
exit(1);
}
// Do a fast copy of up to 50 chars. I'd really want to verify this output to be sure it works.
strcpy_s(p[i].name,50,str);
printf("Enter your marks: ");
for (j = 0; j < 4; j++)
{
// Hope this inputs the way you want.
scanf_s("%d", &p[i].marks[j]);
}
// This should work, but I prefer more explicit pointers.
Avg_Mark(p + i);
}
return p;
}
void Avg_Mark(student* s)
{
// What if s is Null?
int i, sum=0;
// 4 is a magic number. Make this a constant.
for (i = 0; i < 4; i++)
sum += s->marks[i];
// This won't be as accurate as you want. Consider an integer solution.
s->avg = (float)sum / 4;
}
void Print_One(student* s)
{
// What if s is Null? What about s->name?
printf("The average of %s is %.1f\n", s->name, s->avg);
}
void printExcellent(student* s)
{
// What if s is Null?
if ((s->avg) > 85)
Print_One(s);
}
Note: While going through this code, I did not see any "red flags" except for the & on the size and perhaps the gets/rewind calls. I'd still add null asserts to your functions and also walk through it with a debugger to be sure that everything is as you expect. Honestly, there is enough going on here that I'd prefer the debugger help to my quick trace of the code while I was writing comments.
Update
If I change all your scanf_s to scanf() calls, replace your gets() / rewind() calls to a simple scanf("%s", str) call, and change your funky strcpy_s() function to a simpler strcpy() or strncpy() call, your program does not seem to crash for me. My money is that the strcpy_s() call is corrupting RAM while doing its "fast" copy.

C strcmp segmentation fault

#include <string.h>
#include<stdio.h>
#include<stdlib.h>
typedef struct bank
{
char an;
char name;
char type;
int bal;
};
int main()
{
int i=0,n;
printf("Enter the number of accounts\n");
scanf("%d",&n);
struct bank a[n];
printf("Enter the details of the users\n");
for(i=0;i<n;i++)
{
scanf("%s%s%s%d",a[i].an,a[i].name,a[i].type,&a[i].bal);
}
printf("The details of the users are\n");
for(i=0;i<n;i++)
{printf("%s\n%s\n%s\n%d\n\n",a[i].an,a[i].name,a[i].type,a[i].bal);}
char atype[10];
printf("Enter the type of account you want to search\n");
scanf("%s",atype);
char typ[10];
char s[]="savings";
char c[]="current";
int result,res1,res2;
result = strcmp(atype,s);
if(result == 0)
{
for(i=0;i<n;i++)
{
typ[10] = a[i].type;
res1 = strcmp(typ,s);
if(res1 == 0)
{
printf("%s\n%s\n%s\n%d\n\n",
a[i].an,a[i].name,a[i].type,a[i].bal);
}
printf("\n");
}
} else
{
for(i=0;i<n;i++)
{
typ[10] = a[i].type;
res2 = strcmp(typ,c);
if(res2 == 0)
{
printf("%s\n%s\n%s\n%d\n\n",
a[i].an,a[i].name,a[i].type,a[i].bal);
}
printf("\n");
}
}
}
so basically ik its my homework but i did everythimg and i still cannot resolve the segmentation fault.please help
i think its something to do with strcmp() function but oh well
i checked all the sources but couldnt really find any fix.
any help would be appreciated.
For starters:
This
typ[10] = ...
accesses typ one past its valid memory. This invokes undefined behaviour, so anything can happen from then on.
In C array indexing is 0-based. So for char[10] the highest allowed index would be 9. Access the 1st element would be done by using 0.
You have made 2 mistakes here .
First your struct bank declaration was wrong. You forgot to declare name an and type as string. You declared it as just character(char).It should be like :-
struct bank
{
char an[100]; // assuming 100 is max size of input strings
char name[100];
char type[100];
int bal;
};
second you cannot do typ[10] = a[i].type; you should use strcpy() Something like this :-
strcpy(typ,a[i].type);
So this corrected code will work :-
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
struct bank // change made 1
{
char an[100];
char name[100];
char type[100];
int bal;
};
int main()
{
int i = 0, n;
printf("Enter the number of accounts\n");
scanf("%d", &n);
struct bank a[n];
printf("Enter the details of the users\n");
for (i = 0; i < n; i++)
{
scanf("%s%s%s%d", a[i].an, a[i].name, a[i].type, &a[i].bal);
}
printf("The details of the users are\n");
for (i = 0; i < n; i++)
{
printf("%s\n%s\n%s\n%d\n\n", a[i].an, a[i].name, a[i].type, a[i].bal);
}
char atype[10];
printf("Enter the type of account you want to search\n");
scanf("%s", atype);
char typ[10];
char s[] = "savings";
char c[] = "current";
int result, res1, res2;
result = strcmp(atype, s);
if (result == 0)
{
for (i = 0; i < n; i++)
{
strcpy(typ,a[i].type); // change made 2
res1 = strcmp(typ, s);
if (res1 == 0)
{
printf("%s\n%s\n%s\n%d\n\n",
a[i].an, a[i].name, a[i].type, a[i].bal);
}
printf("\n");
}
}
else
{
for (i = 0; i < n; i++)
{
strcpy(typ,a[i].type); // change made 3
res2 = strcmp(typ, c);
if (res2 == 0)
{
printf("%s\n%s\n%s\n%d\n\n",
a[i].an, a[i].name, a[i].type, a[i].bal);
}
printf("\n");
}
}
}
So your mistake was not with strcmp()

I'm trying to create a program with a loop that prompts the user to enter data in the array elements

I'm trying to create a program with a loop that prompts the user to enter data in the array elements. And when the user no longer can enter data, print to screen the data entered in a last in, first out order.
And this is my attempt...
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
struct Name_Age
{
char Name[10];
int Age;
};
void printMe(struct Name_Age info)
{
printf("Name: %s\n", info.Name);
printf("Age: %d\n", info.Age);
}
int main()
{
int size = 0, i = 0, j = 0;
struct Name_Age * array_ptr = (struct Name_Age*)malloc((size + 1)* sizeof(struct Name_Age));
struct Name_Age myInfo = *array_ptr;
printf("Enter size of array: ");
scanf("%d\n", size);
for (i = 0; i < size; ++i)
{
printf("Enter Name: \n");
scanf("%s\n", myInfo.Name);
printf("Enter Age: \n");
scanf("%d\n", myInfo.Age);
}
printMe(myInfo);
return 0;
};
First, scanf("%d", &size) replace scanf("%d\n", size), put &size instead of size as argument(You need an address), and put the malloc things after this line of code, because you need an exact size value before malloc. Same thing with all the scanf stuffs.
As you want to print out all your input names and ages in order, I changed your code like this:
#include <stdio.h>
#include <stdlib.h>
struct Name_Age
{
char Name[10];
int Age;
};
void printMe(struct Name_Age *infoList, int size)
{
int i;
for (i = size-1; i >= 0; --i)
{
printf("Name: %s\n", infoList[i].Name);
printf("Age: %d\n", infoList[i].Age);
printf("\n");
}
}
int main()
{
int size, i;
printf("Enter size of array: ");
scanf("%d", &size);
struct Name_Age * array_ptr = (struct Name_Age*)malloc(size* sizeof(struct Name_Age));
for (i = 0; i < size; ++i)
{
printf("Enter Name: \n");
scanf("%s", array_ptr[i].Name);
printf("Enter Age: \n");
scanf("%d", &array_ptr[i].Age);
}
printMe(array_ptr, size);
return 0;
}
Try to test and compare with your code, questions are welcome.
You can use fgets to read strings and cast the string to digits with atoi. The storage is not complete, but with my changes you can read to structs and specify the size of the loop (TODO: Save a list of structs so that you actually can print a list of structs that you have specified.)
#include <stdio.h>
#include <stdlib.h>
struct Name_Age {
char Name[10];
int Age;
};
void printMe(struct Name_Age info) {
printf("Name: %s\n", info.Name);
printf("Age: %d\n", info.Age);
}
int main() {
int size = 0, i = 0, j = 0;
struct Name_Age *array_ptr = malloc((size + 1) * sizeof(struct Name_Age));
struct Name_Age myInfo = *array_ptr;
printf("Enter size of array: ");
char tmp[10];
fgets(tmp, 10,stdin);
size = atoi(tmp);
for (i = 0; i < size; ++i) {
printf("Enter Name: ");
fgets(myInfo.Name, 10,stdin);
printf("Enter Age: ");
fgets(tmp, 10,stdin);
myInfo.Age = atoi(tmp);
}
printMe(myInfo);
return 0;
};
Test
$ ./a.out
Enter size of array: 2
Enter Name: Superman
Enter Age: 25
Enter Name: Batman
Enter Age: 27
Name: Batman
Age: 27
See also this question about fgets fgets how to read int
Obviously using fgets() is a much better approach, but making the fewest amount of changes as possible to your code and still achieving your result is the following:
#include <stdio.h>
#include <stdlib.h>
struct Name_Age
{
char Name[10];
int Age;
};
void printMe(struct Name_Age *info);
int main(void)
{
int size, i;
struct Name_Age *array_ptr;
printf("Enter size of array: ");
scanf("%d", &size);
array_ptr = malloc(size * sizeof *array_ptr);
for (i = 0; i < size; ++i)
{
printf("Enter Name: ");
scanf(" %s", array_ptr[i].Name);
printf("Enter Age: ");
scanf("%d", &array_ptr[i].Age);
printf("\n");
}
for (i = 0; i < size; ++i)
printMe(&array_ptr[i]);
return 0;
}
void printMe(struct Name_Age *info)
{
printf("Name: %s\n", info->Name);
printf("Age: %d\n", info->Age);
}
Note that passing the struct by pointer to the function should be faster, note that you don't need the myInfo struct; you can just directly modify the elements of the array. Note the space before %s in the scanf() line, this is to discard any whitespace (including \n), this is done automatically for %d so it is only necessary for your strings (technically not the first iteration of the loop, but it doesn't fail if no whitespace is found). If you have any questions about why I made the changes I did, please feel free to comment on this answer!
example of fix
//struct Name_Age myInfo = *array_ptr;//Not necessary
printf("Enter size of array: ");
scanf("%d", &size);//remove `\n`, add `&`
//To ensure after the size has been determined
struct Name_Age * array_ptr = (struct Name_Age*)malloc(size * sizeof(struct Name_Age));//Cast is not necessary in C
for (i = 0; i < size; ++i)
{
printf("Enter Name: \n");
scanf("%s", array_ptr[i].Name);//remove `\n`
printf("Enter Age: \n");
scanf("%d", &array_ptr[i].Age);//need `&`
}
for (i = 0; i < size; ++i)
printMe(array_ptr[i]);

conflicting types for allocArray

guys I'm trying to compile my program in c but I'm getting this error (conflicting types for allocArray)?
Here is my code:
#include <stdio.h>
#include <stdlib.h>
int number(int);
char *allocArray(int);
int main ()
{
printf("Enter a number: ");
int userNumber;
scanf("%d", &userNumber);
int m= number(userNumber);
printf("\nThe number is %d", m);
printf("\n");
printf("*****************************************************\n");
printf("The array is %s", alloArray(5));
}
int number(int n)
{
int num = n;
return num;
}
char *alloArray(int num)
{
char *addr;
addr = (char *) malloc(num);
//addr = char[num];
return addr;
}
You've misspelt allocArray as alloArray (twice, in fact).

Resources