Not available memory unit - arrays

The idea is to restock certain product by getting stdin from user and compare it to string value of the array - for the product names
My function code
void free_restock(){
print_inventory();
printf("What do u want to restock: ");
char *temp_string_for_name;
scanf("%s", &temp_string_for_name);
printf("How much do u want to restock: ");
int temp_val_for_restock = 0;
scanf("%d", &temp_val_for_restock);
for(int i = 0; (strlen(INVENTORY_NAMES_ARRAY[i])) != 0; i++){
if(strcmp(temp_string_for_name, INVENTORY_NAMES_ARRAY[i]) == 0){
INVENTORY_AMOUNT_ARRAY[i] += temp_val_for_restock;
printf("Now u have %d from %s\n", INVENTORY_AMOUNT_ARRAY[i], INVENTORY_NAMES_ARRAY[i]);
break;
}
printf("%d", i);
}
}
Arrays initialization
#define MAX_SIZE_OF_ARRAYS 100
static int INVENTORY_AMOUNT_ARRAY[MAX_SIZE_OF_ARRAYS];
static char INVENTORY_NAMES_ARRAY[MAX_SIZE_OF_ARRAYS][MAX_SIZE_OF_ARRAYS];
My gdb error:
0x00007ffff7e01ecb in ?? () from /usr/lib/libc.so.6

Related

Nested structures and dynamic memory allocation

I am currently learning C and trying to create an app that allows students to input their name, address, student id and any subject id they have while at university (yes this is a task part of foundations of tech course). Basically the following code tries to create an array of students (that is unlimited in size) by using dynamic allocating memory. Further a student can have unlimited amounts of subjects (that is nested within the student subject and is dynamically allocated)
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
int main()
{
typedef struct {
char subjectID[10];
char subjectName[10];
float grades;
}subject;
typedef struct {
char name[10];
int id;
struct subject *enrol;
char address[100];
int status;
int totalSubject;
}student; // This structure is to act like an unlimited list of students
int option=0, q=0, j=0, k=0, p=0, delete=0, position=0;
int count=0; // keeps the count of numbers added
student * studentAddress;
studentAddress = NULL; //Init structure
studentAddress->enrol = NULL; // Init nested structure
int flag = 0; //variable to indicate whether the number to delete is found or not
while (1) // Life cycle of the app
{
printf("1 - Add new student\n");
printf("2 - Display all students\n");
printf("3 - Delete student by id \n");
printf("4 - Delete student by name \n");
printf("5 - Quit\n");
scanf("%d",&option);
switch (option)
{
case 1: studentAddress = realloc(studentAddress, sizeof(student)*(count+1)); //using realloc memory is requested for the new number
printf("Enter your name\n");
fflush(stdin);
gets(studentAddress[count].name);
fflush(stdin);
printf("Enter your id\n");
scanf("%d", &studentAddress[count].id);
printf("Enter your address\n");
fflush(stdin);
gets(studentAddress[count].address);
fflush(stdin);
int subjectCounter = 0;
subjectCounter = 0;
char subjectContinue[10];
for (p = 0; p < subjectCounter; p++)
{
studentAddress[count].enrol = (struct subject *)realloc(studentAddress[count].enrol, (sizeof(subject)*(subjectCounter+1)));
// studentAddress[count].enrol[subjectCounter] = (struct subject *)realloc(sizeof(subject)*(subjectCounter+1));
// Above is teacher paste
printf("What is the id of your subject %d\n", (subjectCounter+1));
fflush(stdin);
gets(studentAddress[count].enrol[subjectCounter].subjectID);
fflush(stdin);
printf("Would you like to add another subject id\n");
fflush(stdin);
gets(subjectContinue);
fflush(stdin);
if (strcmp(subjectContinue, "Y") == 0)
{
subjectCounter++;
}
studentAddress[count].totalSubject = subjectCounter;
}
count++;
printf("\n");
break;
case 2:
for (j=0; j<count; j++)
{
if(studentAddress[j].status != 0)
printf("%s\n %d\n %s\n", studentAddress[j].name, studentAddress[j].id, studentAddress[j].address);
for (q = 0; q < studentAddress[count].totalSubject; q++)
{
printf("%s", studentAddress[j].enrol[q].subjectID);
}
}
printf("\n");
break;
case 3: k=count;
flag=0;
printf("Type the id of the person record you want to delete\n");
scanf("%d", &delete);
for (j=0; j < count; j++)
{
if (delete == studentAddress[j].id)
{
strcpy(studentAddress[j].name, " ");
strcpy(studentAddress[j].address, " ");
studentAddress[j].id = 0;
studentAddress[j].status = 0;
flag = 1;
}
}
if(flag==0)
printf("id not in the list ...\n");
else
printf("Deletion successful ...\n");
printf("\n");
break;
case 4:
flag=0;
char deletChar[100];
printf("Type the name of the person record you want to delete\n");
fflush(stdin);
gets(deletChar);
fflush(stdin);
for (j=0; j < count; j++)
{
if (strcmp(deletChar, studentAddress[j].name)==0)
{
flag = 1;
strcpy(studentAddress[j].name, " ");
strcpy(studentAddress[j].address, " ");
studentAddress[j].id = 0;
studentAddress[j].status = 0;
flag = 1;
}
}
if(flag==0)
printf("name not in the list ...\n");
else
printf("Deletion successful ...\n");
printf("\n");
break;
return 0;
case 5:
return 0;
}
}
return 0;
}
I try running this code and get the error on line 68 and similar on line 95
subscript of pointer to incomplete type 'struct subject'
gets(studentAddress[count].enrol[subjectCounter].subjectID);
plus I get this note (from the compiler) below the error
forward declaration of 'struct subject' struct subject *enrol;
My tutor and lecture have both tried helping me, but they have had no success. They are like most of my code looks correct, but it will not work. Sorry I am new to stack overflow so if you want me to add more information please let me know.
The easiest way to solve this is to create a function.
struct student* allocate_student() {
struct subject* new_subject = allocate_subject();
struct student* new_struct = malloc(sizeof(struct student));
// initialize all fields, which will eventually include
new_struct->enrol = new_subject;
return new_struct;
}
This code fails to check for any error conditions. You should add that. In addition, allocate_subject() is also not defined. Considering the offered example, odds are good you can figure out how to write allocate_subject().
If you add in parameters, allocate_student() might be a bad method name. With enough parameters to construct any student, you might want to call it construct_student(...)

segmentation fault (core dumped) gcc ubuntu

I was trying to make a simple function to make a group of number that user enters them, using pointer of pointer but i keep getting this error and its hard to tell where the problem is, if there any other option to use something else that tells me where the problem is instead of this weird error.
#include <stdio.h>
void BuildGroub(int** group,int* count){
int i=0;
int j;
printf("Enter the size of the group \n");
scanf("%d", &*count);
while(*count != 0){
printf("Enter the %d number of the group:\n", i);
j=0;
scanf("%d", &**(group+i));
while(**(group+i)!=**(group+j)){
j++;
}
if(j==i){
i++;
count--;
} else{
printf("you have already entered this number please try again: \n");
}
}
}
int main(){
int count;
int group[100];
int *groupptr = &group;
BuildGroub(&groupptr,&count);
for(int i=0;i<count;i++){
printf("%d, ", group[i]);
}
return 0;
}
With this question, you do not need to use double pointer. If you want to learn how to use the double pointer, you can google then there are a ton of examples for you, for example, Double Pointer (Pointer to Pointer) in C.
In BuildGroub you decrease the count pointer
if(j==i){
i++;
count--;
}
, but in the condition of while loop, you compare the value that count pointer points to. it seems strange.
while(*count != 0)
Even if you change count-- to (*count)--, it will decrease the number of elements that you enter to 0 when you get out of the while loop, then in main function:
for(int i=0;i<count;i++){} // count is equal to 0 after calling BuildGroub function if you use (*count--) in while loop.
You should use a temp value for while loop function, for example:
int size = *count;
while(size != 0){
...
if (i == j) {
i++;
size--;
}
}
You should use, for example, group[i] instead of *(group+i). It will be easier to read your code.
The code complete:
#include <stdio.h>
void BuildGroub(int* group,int* count){
int i=0;
int j;
printf("Enter the size of the group \n");
scanf("%d", count);
int size = *count;
while(size != 0){
printf("Enter the %d_th number of the group:\n", i);
j=0;
scanf("%d", &group[i]);
while(group[i] != group[j]) {
j++;
}
if(j==i){
i++;
size--;
} else{
printf("you have already entered this number please try again: \n");
}
}
}
int main(){
int count;
int group[100];
int *groupptr = group;
BuildGroub(groupptr,&count);
for(int i=0;i<count;i++){
printf("%d, ", group[i]);
}
return 0;
}
The test:
./test
Enter the size of the group
5
Enter the 0_th number of the group:
1
Enter the 1_th number of the group:
2
Enter the 2_th number of the group:
2
you have already entered this number please try again:
Enter the 2_th number of the group:
3
Enter the 3_th number of the group:
3
you have already entered this number please try again:
Enter the 3_th number of the group:
4
Enter the 4_th number of the group:
5
1, 2, 3, 4, 5,
If you want to use a double pointer, you need to change your function like this:
void BuildGroub(int** group, int* count) {
int i = 0;
int j;
printf("Enter the size of the group \n");
scanf("%d", &*count); //I think this is redundant but works.
while (*count != 0) {
printf("Enter the %d number of the group:\n", i);
j = 0;
scanf("%d", (*group + i)); //The content of group + i
while ( *( *group + i) != *(*group + j)) { //the content of the content
j++;
}
if (j == i) {
i++;
(*count)--; //The content decrement
} else {
printf("you have already entered this number please try again: \n");
}
}
}
But you have a big problem in main and it is because you are using the parameter count to decrement until zero inside the function. So when the function finish, count value is zero and you don't print anything... You need to change this, using a internal variable to make the count, and finaly, setting the parameter to be using in main.

Double usage of scanf() depends on call order

I wrote a program in C which takes as an input a value and an ordered Array of integers and performs a ternary search to find the value(if it exists) inside the Array.
I have seen all the possible problems with the usage of scanf and the related topics here in Stackoverflow.
I have noticed that there is a difference if I call the 2 scanf functions in reverse order.
If I use the code as it is below. First read the value and after the array from the user, the program and scanf functions as expected.
printf("Enter the value to be searched in the Array: ");
int k;
scanf(" %d", &k);
printf("Type elements of A(sorted) separated by spaces (type 'end' to stop): ");
i = 0;
while(scanf("%d", &A[i]) == 1) {
i++;
}//while
Although if I use the scanf inputs in the reverse order the second scanf never stops to get user input and read values left in the buffer.
printf("Type elements of A(sorted) separated by spaces (type 'end' to stop): ");
i = 0;
while(scanf("%d", &A[i]) == 1) {
i++;
}//while
printf("Enter the value to be searched in the Array: ");
int k;
scanf(" %d", &k);
I cannot understand what is the difference in the calling order.
I have tried the solutions mentioned in the other threads but none worked.
Just as a reference here is the whole code(working as expected):
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int ternarySearch(int A[], int l, int r, int k){
int i;
int first,second;
if(l>r){
return -1;
}
i= (r - l)/3;
if(i==0){
i++;
}
first = i+l-1;
second = i*2+l-1;
if(A[first]==k){
return first;
}
else if(A[first]>k){
ternarySearch(A, l, first-1, k);
}
else
{
if(A[second]==k)
return second;
else
if(A[second]>k)
ternarySearch(A, first+1,second-1, k);
else
ternarySearch(A, second+1,r, k);
}
}
int main(){
const int maxarraylen = 1000;
int i;
int n;
int A[maxarraylen];
char string[250];
printf("Enter the value to be searched in the Array: ");
int k;
scanf(" %d", &k);
printf("Type elements of A(sorted) separated by spaces (type 'end' to stop): ");
i = 0;
while(scanf("%d", &A[i]) == 1) {
i++;
}//while
n=i-1;
//We assume the array is sorted otherwise we can use any sorting algorithm e.g. code from task1
scanf(" %d", &k);
int result;
result=ternarySearch(A, 0, n, k);
if(result==-1){
printf("The value was not found in the Array.\n");
}
else{
printf("The value was found in position no. %d.\n", result);
}
return 0;
}
Your problem is that you are not 'stepping over' your end input.
We can see this by doing an experiment using the following program:
#include <stdio.h>
#include <stdlib.h>
void main(void) {
FILE *f;
long f_pos;
int ret;
int i;
int data[5];
int data_last;
int search;
f = fopen("./input.txt", "r");
if (f == NULL) {
perror("fopen()");
return;
}
/* read in the values for the array */
data_last = -1;
for (i = 0; i < 5; i++) {
ret = fscanf(f, "%d", &(data[i]));
printf("fscanf(data[%d]): ret: %d\n", i, ret);
f_pos = ftell(f);
printf("ftell(): %ld\n", f_pos);
if (ret != 1) {
break;
}
data_last = i;
}
/* check that we read in at least one value */
if (data_last == -1) {
printf("no input data!\n");
return;
}
/* insert 'fix' here */
/* pre-load the 'search' with known garbage */
search = 987;
/* now read in the search value */
ret = fscanf(f, "%d", &search);
printf("fscanf(search): ret: %d\n", ret);
f_pos = ftell(f);
printf("ftell(): %ld\n", f_pos);
/* print out our info */
for (i = 0; i <= data_last; i++) {
printf("data[%d]: %d\n", i, data[i]);
}
printf("search for: %d\n", search);
return;
}
With the following data in input.txt:
123
456
end
456
The output is as follows:
fscanf(data[0]): ret: 1
ftell(): 3
fscanf(data[1]): ret: 1
ftell(): 7
fscanf(data[2]): ret: 0
ftell(): 8
fscanf(search): ret: 0
ftell(): 8
data[0]: 123
data[1]: 456
search for: 987
ftell() tells us where the file's cursor is, and in this case we can see that it is at byte 8... the e of the input line end.
It doesn't get past it, and thus the next attempt to read a number (%d) will fail too!
It's also a good idea to check the return values! We can see that the fscanf(&search) call has failed to read a number!
The solution is to insert this snippet just after we check that we recieved array values:
/* this is the 'fix' */
ret = fscanf(f, "end");
printf("fscanf(end): ret: %d\n", ret);
f_pos = ftell(f);
printf("ftell(): %ld\n", f_pos);

Cannot output an array in C programming?

I cannot seem to output a string or an integer array correctly in C programming.
My issue, is that the strings are stored in the array, I just cannot get them OUT of the array and to the output.
When I manually enter the positions (like Array[0]), it properly outputs.
However, the final loop fails to output any of my array entries.
Why is this happening?
Thanks in advance for all replies!
Here is the code:
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
#include <string.h>
main (void)
{
int memory_start;
int memory_end;
int num_jobs;
printf("Enter the starting memory location to be used : ");
scanf("%d", &memory_start);
printf("\nEnter the ending memory location to be used : ");
scanf("%d", &memory_end);
printf("\nHow many jobs will be assigned to the memory locations? \n");
scanf("%d", &num_jobs);
int mem_size = memory_end - memory_start;
int mem_size_init = memory_end - memory_start;
char names[10][20];
int sizes[num_jobs];
int mem_st[10];
int mem_end[10];
int x;
int y;
int z;
int temp_size = 0;
int prev_temp_size;
char temp_name[20];
for(x=0; x<num_jobs; x++)
{
prev_temp_size = prev_temp_size + temp_size;
printf("\nEnter the size of the program (size > 0): ");
scanf("%d", &temp_size);
if( mem_size >= temp_size && temp_size > 0)
{
printf("\nEnter a program name (20 chars): %s", names[1]);
scanf("%s", &temp_name);
if(strlen(temp_name) <= 20)
{
strcpy(names[x], temp_name);
// names[x] = temp_name;
sizes[x] = temp_size;
mem_size = mem_size - temp_size;
mem_st[x] = prev_temp_size + memory_start;
mem_end[x] = temp_size + mem_st[x];
}
else
{
printf("\nProgram name is too long. Please re enter data.");
x--;
}
}
else
{
printf("\nMemory Size not supported (not enough space remaining).\nPlease re-enter data with a plausible memory request.");
printf("\nMemory size remaining: %d", mem_size);
x--;
}
}
printf("\nYour data is as follows: \n");
printf("\nYour initial memory size is: %d", mem_size_init);
printf("\nYour unused memory size is: %d", mem_size);
for(y=0; y<num_jobs; y++)
{
printf("Program: %s", names[y]);
printf("\n", names[y], " memory size is as follows: \n", "memory start: %d", mem_st[y], " memory end: %d", mem_end[y]);
}
}
Here is the corrected code:
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
#include <string.h>
main (void)
{
int memory_start;
int memory_end;
int num_jobs;
printf("Enter the starting memory location to be used : ");
scanf("%d", &memory_start);
printf("\nEnter the ending memory location to be used : ");
scanf("%d", &memory_end);
printf("\nHow many jobs will be assigned to the memory locations? ");
scanf("%d", &num_jobs);
int mem_size = memory_end - memory_start;
int mem_size_init = memory_end - memory_start;
char names[10][20];
int sizes[num_jobs];
int mem_st[10];
int mem_end[10];
int x;
int y;
int z;
int temp_size = 0;
int prev_temp_size;
char temp_name[20];
for(x=0; x<num_jobs; x++)
{
prev_temp_size = prev_temp_size + temp_size;
printf("\nEnter the size of the program (size > 0): ");
scanf("%d", &temp_size);
if( mem_size >= temp_size && temp_size > 0)
{
printf("\nEnter a program name (20 chars): ");
scanf("%s", temp_name);
getchar();
if(strlen(temp_name) <= 20)
{
strcpy(names[x], temp_name);
sizes[x] = temp_size;
mem_size = mem_size - temp_size;
mem_st[x] = prev_temp_size + memory_start;
mem_end[x] = temp_size + mem_st[x];
}
else
{
printf("\nProgram name is too long. Please re enter data.");
x--;
}
}
else
{
printf("\nMemory Size not supported (not enough space remaining).\nPlease re-enter data with a plausible memory request.");
printf("\nMemory size remaining: %d", mem_size);
x--;
}
}
printf("\nYour data is as follows: \n");
printf("\nYour initial memory size is: %d", mem_size_init);
printf("\nYour unused memory size is: %d\n", mem_size);
for(y=0; y<num_jobs; y++)
{
printf("\nProgram: %s\n", names[y]);
printf("\nmemory size is as follows:\nmemory start: %d memory end: %d\n", mem_st[y], mem_end[y]);
}
}
Apart from changes in formatting the output, major changes are:
Removed the & in scanf("%s", &temp_name); because, the name of an array already returns a reference to its first element.
Added a getchar(); after scanf("%s", temp_name); because after reading in a string an extra \n remains in the stream, which causes the next scanf to fail.
This:
printf("\n", names[y], " memory size is as follows: \n", "memory start: %d", mem_st[y], " memory end: %d", mem_end[y]);
is not how a format specifier is prepared, all variables need to be placed at the end, after a single format specifier string.
The last loop is the issue.
for(y=0; y<num_jobs; y++)
{
printf("Program: %s", names[y]);
printf("\n memory size is as follows: ");
printf("\n memory start: %d memory end: %d", mem_st[y], mem_end[y]);
}
In C, the variables are given at the end of the printf. Also you are printing names two times, which i guess you don't want.

Trouble storing the size of each array I have in C

I'm having trouble storing the size of each array the user inputs. I need to do this so that I can run different calculations on each set. This is what I'm trying to do now, but it keeps throwing a segmentation fault, and I don't know what I'm doing wrong. The other thing I thought of doing was essentially make one more memory spot with malloc and just store the sizes in another array at the end of the data set arrays. Anyway, here's the code that is giving me a segmentation fault.
int construct_data_sets(int *sets[], int count) {
int set_size;
int j;
j = 0;
printf("Enter the number of elements in data set %d: ", count+1);
scanf(" %d", &set_size);
sets[count] = (int*)malloc((sizeof(int) * set_size));
if (sets[count] == NULL){
printf("Malloc failed!\n");
}
printf("Enter the data for set %d: ", count+1);
while ((j + 1) <= set_size)
{
scanf(" %d", &sets[count][j]);
j++;
}
return set_size;
}
And here's the main, I think the segmentation fault gets thrown when I call construct_data_sets().
int main() {
int command = 0, data_set, set_desired, array_size;
int number = prompt_num_sets();
int *sets[number], i = 0, *sizes[number];
while (i < number)
{
array_size = construct_data_sets(sets, i);
*sizes[i] = array_size;
i++;
}
//printf("The size of the 3rd data set is %d", *sizes[3]);
printf("Data at [data_set][1] = %d\n", sets[data_set-1][1]);
set_desired = select_data_set(number);
while (command != 7) {
printf("Choose what you would like to do:\n");
printf("1. Find the minimum value.\n");
printf("2. Find the maximum value.\n");
printf("3. Calculate the sum of all the values.\n");
printf("4. Calculate the average of all the values.\n");
printf("5. Sort the values in ascending order.\n");
printf("6. Select a different data set.\n");
printf("7. Exit the program.\n");
scanf(" %d", &command);
if (command == 7) {
exit_program();
} else if (command == 6) {
change_term(number, sets);
}
printf("====================================\n");
}
}
Any weird printf statements you may see are just me trying to make sure things are doing what they're supposed to. Let me know if you need more information from me. Thanks.
You have multiple bugs in your code and several stylistic issues. Have you tried running the code in the debugger to see exactly where things are crashing? Have you tried narrowing the code down to a smaller problem?
Your sizes array should have an element type of int instead of int *. You are dereferencing uninitialized memory since you have not allocated anything for the pointers. Your data_set variable is also uninitialized so the array access into sets is also undefined.
You should initialize all of your variables immediately upon definition. Also I would change your code to declare only one variable per statement. The current code is quite difficult to read.
I would also change your initial while loop into a for loop.
Here's a working version that doesn't crash; although, since you haven't included all of the code, I don't know if there are other parts that are broken. I've also had to remove the references to the undefined functions:
#include <stdio.h>
#include <stdlib.h>
int construct_data_sets(int *sets[], int count) {
int set_size;
int j;
printf("Enter the number of elements in data set %d: ", count+1);
scanf(" %d", &set_size);
sets[count] = (int *) malloc((sizeof(int) * set_size));
if (sets[count] == NULL) {
fprintf(stderr, "Malloc failed!\n");
exit(-1);
}
printf("Enter the data for set %d: ", count+1);
for (j = 0; j < set_size; ++j) {
scanf(" %d", &sets[count][j]);
}
return set_size;
}
int main(int argc, char *argv[]) {
int command = 0;
int number = 1;
int *sets[number], i, sizes[number];
for (i = 0; i < number; ++i) {
sizes[i] = construct_data_sets(sets, i);
}
printf("Data at [0][1] = %d\n", sets[0][1]);
while (command != 7) {
printf("Choose what you would like to do:\n");
printf("1. Find the minimum value.\n");
printf("2. Find the maximum value.\n");
printf("3. Calculate the sum of all the values.\n");
printf("4. Calculate the average of all the values.\n");
printf("5. Sort the values in ascending order.\n");
printf("6. Select a different data set.\n");
printf("7. Exit the program.\n");
scanf(" %d", &command);
if (command == 7) {
return 0;
} else if (command == 6) {
return 0;
}
printf("====================================\n");
}
return 0;
}

Resources