What am I getting wrong on malloc and realloc understanding? - c

I was trying to make an array that would resize whilst the program is running. I have come to knowledge of malloc and realloc functions but it seems I'm getting something wrong apparently. Here's the function that I wrote that creates an array based on how many cycles is the loop making.
int* flexibleArray() {
int *arrayFlex = NULL;
int number=0, cnt=0;
while (number!=-1) {
printf("\nInsert the variable: ");
scanf("%d", &number);
if (number==-1){
break;
}
cnt+=1;
arrayFlex = realloc(arrayFlex, cnt * sizeof(int));
arrayFlex[cnt-1] = number;
}
return arrayFlex;
}
I tried to read the documentation I found on the internet about it, I can't then retrieve the new array after the reallocation.
int *array;
array = flexibleArray();
int arraySize = (sizeof(array))/(sizeof(int));
for(int i=0; i<arraySize; i++) {
printf("%d ", array[i]);
}
basically this is where I'm testing the function to see if it does what it should.
I'm new to C, sorry guys.
Thanks

Something like this should do it.
int* flexibleArray() {
int *arrayFlex = NULL; // needs to be a pointer
int number=0, cnt=0;
while (number!=-1) {
printf("\nInsert the variable: ");
scanf("%d", &number);
if (number==-1){
break;
}
cnt+=1;
arrayFlex = realloc(arrayFlex, cnt * sizeof(int));
arrayFlex[cnt-1] = number;
}
return arrayFlex;
}
EDIT: fixed typos.

Related

I keep getting a segmentation fault and I can't find it! I think ive narrowed it down to a particular function

I say that it must be this function because it stops right after I enter an int and it doesn't read the print statement.
recipe** readAllRecipes(int numRecipes)
{
recipe** theRecipes = malloc(sizeof(recipe *) * numRecipes);
int i;
for(i = 0; i < numRecipes; i++)
{
scanf("%d", &theRecipes[i]->numItems);
printf("\n\n\t\t here in readAll for loop\n");
theRecipes[i] = readRecipe(theRecipes[i]->numItems);
}
return theRecipes;
}
Here's the problem:
scanf("%d", &theRecipes[i]->numItems);
theRecipise[i] is not initalized and you dereference it. Should allocate it first:
theRecipes[i] = malloc(sizeof(recipe));
scanf("%d", &theRecipes[i]->numItems);
but lower down I'm baffled by this:
theRecipes[i] = readRecipe(theRecipes[i]->numItems);

Passing Pointers to Pointers into Functions in C

I'm working on a class project and I'm still learning C.
The goal is to ask the user how many items are available for sale today, and then ask them to enter those items one-by-one to new lines, and have them be entered into an array of strings.
Then print the array as a list to show the available items.
We cannot use statically declared arrays, and must use only pointers.
The functions here are required. I am required to have the get_items() function modify the array rather than return a result.
I'm having a lot of trouble making get_items() work. Anything I try either ends up with "exited, segmentation fault" or printing (NULL) when I go to print the items of the array.
Any suggestions to make this work would be greatly appreciated.
char* get_item() {
char *item = calloc(61,sizeof(char));
scanf(" %[^\n]",item);
return item;
}
void get_items(char ***items, int *num_items){
int i;
printf("Enter the %d available items one to a line: \n",*num_items);
for(i = 0; i < *num_items; i++) {
**(items+i) = get_item();
}
}
int main(void) {
char **items=NULL; /* this is the pointer for the start of the ingredients array */
int num_items = -1,
int i;
printf("How many available items do we have today? ");
scanf("%d",&num_items);
items = calloc(num_items,sizeof(char*));
get_items(&items,&num_items);
printf("Available items today are: \n");
for(i = 0; i < num_items; i++) {
printf("%i. %s\n",i+1,*(items+i));
}
In get_items, **(items+i) should be *(*items+i) or (*items)[i].
However, get_items has too many levels of pointer dereferencing. The following is simpler:
void get_items(char **items, int num_items){
int i;
printf("Enter the %d available items one to a line: \n",num_items);
for(i = 0; i < num_items; i++) {
*(items+i) = get_item(); // or more readable: items[i] = get_item();
}
}
The call to get_items from main would then need to be changed to the following:
get_items(items,num_items);
The original prototype void get_items(char ***items, int *num_items) suggests that some of the code in main should have been done in get_items instead:
void get_items(char ***items, int *num_items){
int i;
printf("How many available items do we have today? ");
scanf("%d",num_items);
*items = calloc(*num_items,sizeof(char*));
printf("Enter the %d available items one to a line: \n",*num_items);
for(i = 0; i < *num_items; i++) {
*(*items+i) = get_item();
}
}
Then main can be reduced to the following:
int main(void) {
char **items=NULL; /* this is the pointer for the start of the ingredients array */
int num_items = -1,
int i;
get_items(&items,&num_items);
printf("Available items today are: \n");
for(i = 0; i < num_items; i++) {
printf("%i. %s\n",i+1,*(items+i));
}
}

Creating a int * with malloc and then use realloc when full

In a function I created am I trying to allocate a int array dynamically to store some index values.
First I create the int * with the malloc function and then let the loop store som values in it and increament the pointer each time.
The problem I run in to starts when I try to use the realloc to increase the memory allocation.
When I do this VS tells me it runs in to undefined behaviour and breaks the program.
The code looks like this
void showAvailable(CabinHolder *holder, Booking *booking)
{
system("cls");
printf("Choose cabin number \n");
printf("Start week: &d \t End week: %d", booking->rentPeriod[0], booking->rentPeriod[1]);
printf("------------------------------------------\n");
int memory = 5;
int *indexOfCabin = (int *)malloc(sizeof(int)*memory);
int counter = 1;
for (int i = 0; i < CABINS; i++)
{
if (counter == memory)
{
memory *= 2;
int *expanded = realloc(indexOfCabin, (memory * sizeof(int)));
indexOfCabin = expanded;
expanded = NULL;
}
if (booking->cabin->typeOfCabin == holder->arrofCabin[i].typeOfCabin)
{
printf("%d. \t Cabin with number %d \t cost: %d per week\n", counter, holder->arrofCabin[i].nr, holder->arrofCabin[i].cost);
counter++;
indexOfCabin = &i;
indexOfCabin++;
}
}
free(indexOfCabin);
system("pause");
}
When I debugg in VS i also se that my pointer indexOfCabin seems to be undefined inside the if statement, which I don't understand.
What have I missed here?
Okay after some help in the comment section I solved the problem with this edited code segment.
void showAvailable(CabinHolder *holder, Booking *booking)
{
system("cls");
printf("Choose cabin number \n");
printf("Start week: %d \t End week: %d\n", booking->rentPeriod[0], booking->rentPeriod[1]);
printf("------------------------------------------\n");
int memory = 5;
int *indexOfCabin = malloc(sizeof(int)*memory);
int counter = 1;
int items = 0;
int choice = 0;
for (int i = 0; i < CABINS; i++)
{
if (counter-1 == memory)
{
memory *= 2;
indexOfCabin = realloc(indexOfCabin, (memory * sizeof(int)));
}
if (booking->cabin->typeOfCabin == holder->arrofCabin[i].typeOfCabin)
{
printf("%d. \t Cabin with number %d \t cost: %d per week\n", counter, holder->arrofCabin[i].nr, holder->arrofCabin[i].cost);
counter++;
indexOfCabin[items++] = i;
}
}
free(indexOfCabin);
system("pause");
}
First: Problem was indexOfCabin = &i throws away the memory you allocated, and puts the address of i into the pointer instead of what I wanted to do. Now we store the index in i in the pointer.
Second: indexOfCabin can be used like an array, e.g. indexOfCabin[counter] = i;. But counter needs to start at 0, and should be incremented after being used. And indexOfCabin should not be incremented

Stack around the variable was corrupted with pointer arithmetics

With the code below, I'd always run into "Stack around the variable 'UserCode' was corrupted.
If I'm not mistaken, when I do userCode = (char*)malloc(sizeof(char)*N);, shouldn't it create an "array" with size of char*n ? I'm guessing my issue is either with my declaration of an array, or my pointer arithmetic.
Any help would be highly appreciated.
#include "stdafx.h"
#include <math.h>
int userPrompt1() {
int numOfAlphabets = 0;
printf("Please enter a number from 1 to 8 to choose how many alphabets you want\n");
scanf_s(" %d", &numOfAlphabets);
if (numOfAlphabets > 8 || numOfAlphabets < 0) {
printf("Sorry! Invalid number entered. Try again. \n");
numOfAlphabets = userPrompt1();
}
return numOfAlphabets;
}
int userPrompt2() {
int numOfLetters = 0;
printf("Please enter the number of letters you want to guess\n");
scanf_s(" %d", &numOfLetters);
if (numOfLetters < 0) {
printf("Sorry! Invalid number entered. Try again. \n");
numOfLetters = userPrompt2;
}
return numOfLetters;
}
int tryCalculator(int K, int N) {
int tries = 0;
tries = 1 + ceil(N * log2(K));
return tries;
}
void codeGenerator(char codeGuessIn[], char letters[], int size) {
for (int i = 0; i < size; i++) {
int rando = rand() % size;
codeGuessIn[i] = letters[rando];
printf(" %c", codeGuessIn[i]);
}
printf("\n");
}
void codeChecker(char codeGuessIn[], char generatedCode[], int size) {
int correctAlphabets = 0;
for (int i = 0; i < size; i++) {
if (codeGuessIn[i] == generatedCode[i]) {
correctAlphabets++;
}
}
printf(" %d in correct place \n", correctAlphabets);
}
void getUserCode(int size, char *userCode[]) {
for (int i = 0; i < size; i++) {
printf("Please enter letter #%d \n", i+1);
getchar();
scanf_s(" %c", &userCode[i]);
}
}
int main(void)
{
char letters[8] = { 'A','B','C','D','E','F','G','H' };
char *generatedCode; //array to hold generated code
char *userCode; // array to hold generated code.
int K = userPrompt1(); //how many different alphabets in code
int N = userPrompt2(); //how many letters in code
int tries = tryCalculator(K, N);
//int gameEnd = 1;
userCode = (char*)malloc(sizeof(char)*N);
generatedCode = (char*)malloc(sizeof(char)*N);
codeGenerator(generatedCode, letters, N);
getUserCode(N, &userCode);
//codeChecker(userCode, generatedCode, N);
return 0;
}
void getUserCode(int size, char *userCode[]) {
scanf_s(" %c", &userCode[i]);
Here, userCode[i] is a char * (pointer-to-char), &userCode[i] is a char ** (pointer-to-pointer-to-char), and scanf("%c") expects a char *. A good compiler would warn about that.
I think what you meant to do here is something like:
void getUserCode(int size, char *userCode) {
scanf_s(" %c", &userCode[i]);
}
int main(void) {
char *userCode = malloc(N);
getUserCode(N, userCode);
}
The printf(), getchar(), scanf() combination here reeks of the bad habits created by scanf: you're discarding the first character entered by the user because you're relying on an extra character in the input buffer.
See http://c-faq.com/stdio/scanfprobs.html and read full lines of input with fgets() instead of using scanf().
Also,
int userPrompt2() {
int numOfLetters = 0;
...
numOfLetters = userPrompt2;
}
You're assigning a function pointer to an int. (A normal compiler should warn about this.) If the idea here is to call the function again to repeat the prompt in case the user enters something silly, it's probably a better idea to use a loop instead of a recursive call anyway.

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