Doesn't work function free and code always crashed - c

My code crash coz free() doesn't want to clear array. First of all i create array and add to there a numbers. After that i enter K (k < m) and creates new matrix MxK. k - amount of number of first array in line. And if the number are over , should fill in the rest matrix with zeros. I use while for reuse, but my code crash when i use big array and big matrix. With what it can be connected?
`int main() {
while(1){
int m,k;
printf("Enter size of array: ");
int res;
do
{
res=scanf("%d",&m);
if(res!=1)printf("it should be a number!");
}
while(res!=1);
int * a = (int*) malloc(m*sizeof(int));
int i;
for (i = 0; i < m; i++)
{
printf("a[%d] = ", i);
do
{
res=scanf("%d", &a[i]);
flush();
if(res!=1) printf("it should be a number!\n");
}
while(res!=1);
}
for (i = 0; i < m; i++)
printf("%d ", a[i]);
printf("\nEnter K: ");
do
{
res=scanf("%d",&k);
flush();
if(res!=1 || k>m) printf("k<m must be or enter number\n");
}
while(res!=1 || k>m);
int all=k*m;
for(i=m;i<all;i++)
{
a[i] = 0;
}
int j;
int n=0;
int s[i][j];
for(i=0;i<m;i++)
{
for(j=0;j<k;j++)
{
s[i][j] = a[n];
printf("%d ",s[i][j]);
n++;
}
printf( "\n" );
}
for(i=0;i<m;i++)
{
for(j=0;j<k;j++)
{
free(s[i][j]);
}
}
int povtor; ----- exit using break
char temp[10];
printf("Continue?(1 - No, everything - Yes): ");
gets(temp);
povtor = atoi(temp);
if (povtor == 1 ) break;
}
return 0;
}`

Your code has a lot of problems.
First, you can only free something that was allocated with malloc, calloc, or realloc. This doesn’t apply to s[i][j].
But that’s only one issue. You allocate a to hold m elements:
int * a = (int*) malloc(m*sizeof(int));
but then you try to write past the end of the array here:
int all=k*m;
for(i=m;i<all;i++)
{
a[i] = 0;
}
You need to resize a before attempting that, otherwise you are writing over memory you don’t own:
int *tmp = realloc(a, sizeof *a * all );
if ( !tmp )
{
// resize failed, exit with error
}
a = tmp;
for( i = m; i < all; i++ )
{
a[i] = 0;
}
Then there’s this:
int j;
int n=0;
int s[i][j];
What is the value of j at this point? For that matter, what is the value of i? Are you sure you don’t mean s[m][k]?

You are trying to free an int, and not a pointer : int s[i][j] is an array of array of int, hence s[][] is a int.
Even though, s is automatic memory allocated : basically, its a variable stored in the stack so you don't need to free it. Trying to free static variable results in crash. This question may help you.
By the way, you have a lot of uninitialized variable, resulting in conditionals jumps and possible crashs : for example, you declare int j without a value and after you use it to declare your array of array.
Finally, don't use gets. This function is dangerous, use fgets instead. I suggest you read the manual page of gets to understand why.

Related

Storing an array in C

Context: I need to write a program that will accept inputs which will be stored into the array. Before storing in to the array, the inputted number must be checked if it already exists in the array or not. If it does not exist, it is stored into the array. If it exists, another input will be asked.
Now, my code will get inputs from the user, but the code will only work for the first input. It won't work for the second until the last input. Any pointers?
This is my code:
#include<stdio.h>
#define size 5
main()
{
int i;
arr[size];
input;
printf("This program will accept ");
printf("unique inputted numbers that will be stored");
printf(" in an array\n");
for(i = 0;i < size;i++)
{
printf("Enter input: ");
scanf("%d",&input);
if (unique(arr,input,i))
arr[i] = input;
else
i--;
//decrement i because ask for input again
}
for(i = 0;i < size;i++)
printf("%d ",arr[i]);
}
int unique(int arr[],int input,int i)
{
int n, z;
n = 0;
z = 1;
while(i > n)
{
if(arr[n] == input)
{
scanf("%d",&n);
z = 0;
break;
}
else
n=1;
break;
}
return z;
}
Your code is wrong at multiple levels:
The logic in the unique function is wrong.
Doing the scanf in the unique function is extremely bad design. The only thing unique should do is return 0 if input is already in the array.
You have used implicit variable declarations here: arr[size]; input;, it should be int arr[size]; int input;.
You should use descriptive variable names which makes your code easier to understand.
This is a working example (explanations in comments).
#include <stdio.h>
#define SIZE 5 // use capitals for macros (this is a convention)
int unique(int arr[], int value, int arrsize)
{
for (int i = 0; i < arrsize; i++)
{
if (arr[i] == value)
{
return 0; // value found in array
}
}
return 1; // value not found in array
}
void Test(int arr[], int arrsize, int value, int expected)
{
if (unique(arr, arrsize, value) != expected)
printf("Test failed for value %d\n", value);
}
void runtests()
{
int arr[] = { 1,2,3 };
Test(arr, 4, sizeof(arr) / sizeof(*arr), 1);
Test(arr, 1, sizeof(arr) / sizeof(*arr), 0);
Test(arr, 3, sizeof(arr) / sizeof(*arr), 0);
}
#define size 5
int main()
{
int i;
int arr[size]; // declare int variable
int input; // declare int variable
printf("This program will accept unique inputted numbers that will be stored in an array\n");
for (i = 0; i < size; i++)
{
printf("Enter input %d: ", i + 1);
scanf("%d", &input);
if (unique(arr, input, i)) // value already in the array?
arr[i] = input; // no => put it there
else
{ // yes => ask again
printf(" >> %d is already in the array\n");
i--;
}
}
for (i = 0; i < size; i++)
printf("%d ", arr[i]);
}
There are two more functions Test and runtests in this code. They are not called by this code, but they can be very useful for debugging. As an exercise try to understand why they can be useful during the debug phase of your code.
You're close, but overcomplicating it slightly.
Let's take a step back and think about this at a high level. You want to store unique inputs in the array, up to the size of the array. In pseudocode:
while array not full
prompt for and read next input
if input not already in array
store input
else
write a message
end if
end while
What's really key is that you only need one input statement - your unique function should only check for the presence of the input value in the array and return true or false. It shouldn't do any input of its own.
So your main loop is more like
while ( i < size )
{
fputs( "Gimme a number: ", stdout );
/**
* Break out of the loop if there's an error
* on input.
*/
if ( scanf( "%d", &input ) != 1 )
break;
if ( unique( arr, i, input ) )
arr[i++] = input;
else
printf( "%d already exists in the array, try again.\n", input );
}
All your unique function needs to do is cycle through the elements of the array. By calling unique with i instead of size it will only check array elements that have been written to so far and not bother with unassigned elements. This way you don't have to make sure that all of the array elements have been initialized to some known, out-of-band value that's guaranteed to compare unequal to any valid input.
You'll need to compile against C99 or later and include stdbool.h to use the bool type and the true and false constants.
#include <stdbool.h>
...
bool unique( int *arr, size_t size, int input )
{
bool result = true;
for( size_t i = 0; i < size && result; i++ )
if ( arr[i] == input )
result = false;
return result;
}
If you want to get really terse, you could directly assign the result of the Boolean expression to result:
for ( size_t i = 0; i < size && result; i++ )
result = (arr[i] == input);
but people will hit you. It's perfectly valid code, but a little eye-stabby, and most programmers aren't used to seeing Boolean expressions outside of an if, for, while, or switch statement control expression.
Finally, some suggestions:
Fix your formatting. The compiler doesn't care, but it makes it easier for other people to understand what you're trying to do and to spot mistakes.
The presence of main() in your code suggests you're using C89 or K&R C. C99 did away with implicit int declarations. You really should define main as either int main( void ) or int main( int argc, char **argv ). Furthermore, you should move to a compiler that supports later versions of C (C11 or C18).

How to break a while loop when it is false to a certain condition

I was trying to make a program where if I enter an integer, the program would find out the bigger number and subtract it by the smaller number. This part, I got it.
The problem is, the infinite loop part.
I tried to get type in two integers keep on printing with the while loop, and break when at least one character is typed in.
For example, if I type in 2 #, it would break.
But I couldn't find the write place to get the break; within the code and therefore whenever I enter a character it would keep on creating an infinite loop.
Is there any way to create a break in this code? I humbly ask for advice...
The following is the code which I couldn't put the break
(By the way, the reason I did the condition in while as sizeof(i)==4 || sizeof(j)==4 was to make it so it would only enter an integer, since the size of an integer is 4)
int main()
{
int i, j;
int result;
while (sizeof(i)==4 || sizeof(j)==4){
printf("type in two integers : ");
scanf("%d %d", &i, &j);
if (i < j) {
result = j - i;
}
else if (j < i){
result = i - j;
}
printf("%d\n", result);
}
return 0;
}
The bottom code is the one I tried to put break but failed (it kept creating an infinite loop)...
int main()
{
int i, j;
int result;
while (sizeof(i)==4 || sizeof(j)==4){
if (sizeof(i) == 4 || sizeof(j) == 4) {
printf("type in two integers : ");
scanf("%d %d", &i, &j);
if (i < j) {
result = j - i;
}
else if (j < i) {
result = i - j;
}
printf("%d\n", result);
}
else
break;
}
return 0;
}
and here's a code where I got rid of the sizeof and used while(1), though there wasn't much change in the fact that the break didn't work...
int main()
{
int i, j;
int result;
while (1){
printf("type in two integers : ");
scanf("%d %d", &i, &j);
if (i < j) {
result = j - i;
}
else if (j < i) {
result = i - j;
}
printf("%d\n", result);
}
return 0;
}
You can't use sizeof(i) to do run-time checks! This is a compile-time constant that, in your case (32-bit integers) will always evaluate to 4.
In order to check that two valid integers have been given, you can check the return value of the scanf function (it gives the number of fields successfully scanned):
#include <stdio.h>
int main()
{
int i, j;
int result;
while (1) {
printf("type in two integers : ");
if (scanf("%d %d", &i, &j) != 2) break; // Break here if we didn't get two integers
if (i < j) {
result = j - i;
}
else if (j < i) {
result = i - j;
}
printf("%d\n", result);
}
return 0;
}
Feel free to ask fir further clarification and/or explanation.
Drop the whole concept of endless loop with break inside if.
Make a condition for the loop based on the return value of scanf(), that is practically what it is designed for.
#include <stdio.h>
int main()
{
/* always init everything */
int i=0, j=0;
int result=0;
printf("type in two integers : ");
while (2==scanf("%d %d", &i, &j))
{
if (i < j) {
result = j - i;
}
else /* removed second if, to have a meaningful result for i==j */
{
result = i - j;
}
printf("%d\n", result);
printf("type in two integers : ");
}
return 0;
}
I'd probably actually use do {...} while (...) with a variable storing the return value of scanf()for being used in the loop condition. I'd consider it more elegant for not having to copy the print, but I kept it closer to your code structure.
More comments on your code:
as explained in comments, sizeof() works differently than you seem to think; it is static and does not change at runtime and hence cannot be used in a loop condition
with while (sizeof(i)==4 || sizeof(j)==4){if (sizeof(i) == 4 || sizeof(j) == 4){/* a */} else {/* b */}, b cannot ever be reached, because the conditions of while and if are identical
check the possible outcomes of the if conditions inside the loop, you are leaving the one with i==j undefined and return an uninitialised value
always init all variables as a habit
for a good MRE include the include lines
On your request, here is a proposal for the do-while alternative:
#include <stdio.h>
int main()
{
/* always init everything */
int i=0, j=0;
int result=0;
int iScanned=0;
do
{
printf("type in two integers : ");
iScanned=scanf("%d %d", &i, &j); /* keep the return value for loop */
if (i < j) {
result = j - i;
}
else /* removed second if, to have a meaningful result for i==j */
{
result = i - j;
}
if(2==iScanned) printf("%d\n", result); /* if to avoid awkward last output */
} while (2==iScanned);
return 0;
}

Question regarding allocating memory for array, sorting and numbers only in C programming

I have a program that I would like to dynamically allocate an array that gets filled by the user through the terminal argument line in Linux. After the user enters the numbers, the array of numbers should be sorted.
#include <stdio.h>
#include <stdlib.h>
int main(){
int i;
int array[100];
int count = 0;
while(1){
printf("please enter a number: \n");
scanf("%d", &i);
if(i == 0){
for (int k = 0; k < count -1; k++) {
if(array[k] <= array[k + 1]){
int temp = array[k];
array[k] = array[k+1];
array[k+1] = temp;
}
}
for (int j = 0; j < count; ++j)
{
printf("%d ", array[j]);
}
printf("\n");
break;
} else {
array[count] = i;
count++;
}
}
}
This only sorts the array if I type the numbers in low to high, but if I enter the numbers from high to low eg. 4, 3, 2 and then 1, it prints 2, 3, 1 and then 4, instead of the 1,2,3,4 that it does if I type it that way.
I don't want to initialize the array with 100, I just can't get it to work if I don't initialize it. I want it to be increased if necessary.
Thank you :)
Errors/Deviations from the proposed program:
As mentioned, you want to use command line arguments - You need main(argc,*argv[]) instead of main().
For dynamic allocation you need malloc/calloc but instead of that you have used static array.
Your code shows you are not clear about concept of sorting, leave the program aside and use a pen and paper first to clear that.

C Convert string to integer using arrays

I'm making a program where user enters grades (1 to 5) and then the grade gets added to array for later inspection. When user enters letter "s", the program closes. When ran my program crashes, why?
#include <stdio.h>
#include <stdlib.h>
int i;
int grade[50];
char *num[20];
int enter();
int enter()
{
for (i=0; i<10; i++) {
printf("\nEnter grade:\nPress [s] to close program\n");
scanf("%s",&num[i]);
if (strcmp(num[i],"s") == 0) {
break;
} else {
grade[i] = atoi(num[i]);
}
}
}
int main()
{
enter();
for (i=0; i<10; i++) {
printf("\n%d",grade[i]);
}
return 0;
}
remove ' * ' from num[20] declaration, as you are declaring 20 character string pointers, so reading and comparing values with num[i] will cause error.
Besides, you just nead a simple string to get the grade.
The reason why program crashed is that num is a pointer array, the element of num can not pointer to valid memory which used to store the string you inputed.
you can change char *num[10] to char num[10][12] and 'scanf("%s", &num[i])to scanf("%s", num[i]), and that everything will be OK.
Of course, you can use malloc to dynamic alloc memory for each element in num, like:
`for(i = 0; i < 10; i ++){
num[i] = (char*)malloc(sizeof(char) * 12);
}
`
Even thought, you must change scanf("%s", &num[i]) to scanf("%s", num[i]);
Finally, you can not forget to free the memory you just dynamic malloc.

Read value from adress with pointers - C programming

In my program, I want to input some numbers until I input 0. When I input 0, the program must stop and show the numbers in order. It's almost finish but I have one problem. I must not use an array, it's forbidden .
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
int main()
{
int number;
int *ptr;
int i = 0, j = 0;
ptr = &number;
number = (int*)malloc(2000);
do{
printf("Enter a number : ");
scanf("%d",ptr);
printf("\n######\n");
printf("%d. number = %d \t%p\n",i+1,*(ptr),(ptr+i));
printf("\n######\n");
i++;
} while(((number)) != 0);
printf("\n!!!!############!!!!\n");
for(j = 0 ; j < i; j++){
number=number+j;
printf("%d. number = %d \t%p\n",j+1,(number),&(number));
}
return 0;
}
You code has a number of problems. I think you tried something too challenging for your level of understanding right now.
You should learn about pointers from the beginning and make sure you understand the * and & operators. Try writing some small simple programs so you have a good grasp on them.
From there you can move on to scanf and malloc, since they rely on heavily pointers.
Here is a working version of your code:
int main()
{
int* number; // this is should be a pointer
//int *ptr;
int i = 0, j = 0;
//ptr = &number;
number = (int*)malloc(2000);
do{
printf("Enter a number : ");
// scan an integer into the ith place in memory
// after the address pointed to by "number"
scanf("%d",number+i); //number+i is already an address, don't use &
printf("\n######\n");
printf("%d. number = %d \t%p\n",i+1,*(number+i),number+i);
printf("\n######\n");
i++;
// need to use a -1 since we incremented i
}while(*(number+i-1) != 0);
printf("\n!!!!############!!!!\n");
for(j = 0 ; j < i; j++){
//=number+j;
printf("%d. number = %d \t%p\n",j+1,*(number+j),number+j);
}
return 0;
}

Resources