Why does the C program stop executing after providing 1 element? - c

I am writing a program to check whether a set is a proper subset of a set or not. I am dynamically allocating memory for both of the sets(arrays) but after I provide one element the program stops executing.
#include <stdio.h>
int setID(int arr[],int arr2[],int size,int size2)
{
int counter =0;
for (int i=0; i<size2;i++)
{
if (arr2[i] == arr[i])
{
counter++;
}
}
if (counter == (size2))
{
return 1;
}
else
return 0;
}
int main ()
{
printf("We are going to check if set A is a proper subset of B or not\n");
printf("Please provide the cardinal number of set A \n");
int a=0,b=0;
scanf("%d",&a);
int *p;
p =(int*) malloc(a*sizeof(int));
printf("Please provide the elements of Set A\n");
for (int i=0;i<a;i++)
{
scanf("%d",p[i]);
}
printf("Please provide cardinal number for set B\n");
scanf("%d",&b);
int *p1;
p1= (int*) malloc(b*sizeof(int));
for (int i=0;i<b;i++)
{
scanf("%d",&p1[i]);
}
printf("Please note that 0 is false and 1 is true\n");
printf("%d\n",setID(p,p1,a,b));
return 0;
}
**Also have I passed the arguments correctly in the function: printf("%d\n",setID(p,p1,a,b)); **

There is one error here
scanf("%d",p[i]);
which should be
scanf("%d", &p[i]);
and which is correct a few lines further down when you did this with p1. You say the program stops after providing one element and this is consistent with the error.
There may be other errors too as posted by others.

in setID :
for (int i=0; i<size2;i++)
{
if (arr2[i] == arr[i])
{
counter++;
}
...
you suppose the size of arr is >= the size of arr2, but this is not mandatory because you read their size rather than to use the same when you allocate the arrays and read their values
if size < size2 (a < b in main) you go out of arr (p in main), the behavior is undefined

Related

Segmentation Fault linear search algorithm

This algorithm is a linear search algorithm that finds the desired value. But when I compile this code, gives the segmentation fault in if(dizi[i]==aranan) this line. How can I solve this ?
#include <stdio.h>
int N,i,aranan;
int ArrayBastir(int *dizi,int N)
{
printf("My numbers\n");
for(int i =0; i<N;i++)
{
printf("%d\n", dizi[i]);
}
}
int findValue()
{
printf("The value you want to search");
scanf("%d",&aranan);
}
int Output(int *dizi,int N,int aranan)
{
for(int i =0; i<N;i++)
{
if(dizi[i]==aranan)
{
printf("%d number %d. found in queue \n", aranan,i+1);
}
}
}
int main() {
int N;
int aranan;
printf("Please enter how many numbers you want to enter");
scanf("%d", &N);
int dizi[N];
for(int i =0; i<N;i++)
{
scanf("%d", &dizi[i]);
}
ArrayBastir( dizi, N);
findValue(aranan);
Output(*dizi,N,aranan);
return 1;
}
Linear Search algorithm
You have two objects defined as:
int aranan;
Once is defined at file scope (a global), and one is defined within the scope of main.
When findValue(aranan) is called, a copy of the uninitialized value of aranan within the scope of main is passed to findValue. findValue is lacking a prototype, having not declared its arguments, so this is ignored.
findValue scans a value into the file scope aranan, but when Output(*dizi, N, aranan) is called it uses the value of aranan defined within main. aranan within main was never initialized, and thus this causes Output to search for an indeterminate value.
Additionally, *dizi is an int, when Output expects an int * as its first argument.
ArrayBastir and Output are also defined as each returning an int, which they do not do.
You should not ignore the return value of scanf, as it indicates the number of successful conversions, or a negative value on failure (EOF). In a program this small, you can get away with writing a simple wrapper function for reading integers, that just exits the program if the user enters something invalid.
main returning nonzero generally indicates your program failed. main is special - it is the only non-void function where you can omit a return statement. If main reaches the end of execution without an explicit return, it is treated as though it returned 0.
The issues above can be mitigated by avoiding the use of global variables, and by turning up your compilers warning level to catch obvious type mismatches.
For GCC or Clang, use -Wall -Wextra, and possibly -Werror.
For MSVC, use /Wall, and possibly /Wx.
Minimally refactored:
#include <stdio.h>
#include <stdlib.h>
int get_int(void)
{
int x;
if (1 != scanf("%d", &x)) {
fprintf(stderr, "Invalid input.\n");
exit(EXIT_FAILURE);
}
return x;
}
void ArrayBastir(int *dizi, int N)
{
printf("My numbers\n");
for (int i = 0; i < N; i++) {
printf("%d\n", dizi[i]);
}
}
void Output(int *dizi, int N, int aranan)
{
for (int i = 0; i < N; i++) {
if (dizi[i] == aranan) {
printf("Found <%d> at position %d.\n", aranan, i);
}
}
}
int main(void)
{
printf("Please enter how many numbers you want to enter: ");
int N = get_int();
int dizi[N];
for (int i = 0; i < N; i++) {
dizi[i] = get_int();
}
ArrayBastir(dizi, N);
printf("Enter the value you want to search for: ");
int aranan = get_int();
Output(dizi, N, aranan);
}

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.

Can I 'return' a result from the main variable?

So I have this exercise where I need to show the N first prime numbers, but I need to specifically create a function to know if the number is a prime number
#include <stdio.h>
#include <stdlib.h>
int prime(int num){
int cont,i,j=0,b;
b=num;
do{
j++;
i=0;
for(cont=1;cont<j;cont++){
if(j%cont == 0)
i++;
}
if(i == 1){
return(j);
c=j;
b--;
}
} while (b > 0);
}
int main(){
int *v,n,cont;
do{
printf("Input an integer: ");
scanf("%d",&n);
} while (n <= 0);
v = (int *)malloc(n * sizeof(int));
for(cont=0;cont<n;cont++){
v[cont] = prime(n);
}
for(cont=0;cont<n;cont++){
printf("%d ",v[cont]);
}
}
The problem with the way i've done this is that the variable J is aways being set to 0 when i call the function again, i've tried to set something like c=j so when the program return to the prime function it would have the 'previous' j value but it gets a weird random number. So I wanted to know if is there a way to 'return' the result in the main function to the prime function, i couldn't find anything that helped me, not that i could understand at least
Your function prime() is not working as intended and there are many other errors -
1) Since smallest prime is 2, variable cont should start from 2.
2) scanf need not be in a loop in this case
3) Enter values in v only when cont is confirmed a prime.
See this function prime2( not optimize though for clarity):
bool prime2(int n)
{
for(int i = 2 ; i<n-1;i++)
if( n% i == 0) return false;
return true;
}
int main(){
int *v,n,cont,cc=0;
printf("Input range: ");
scanf("%d",&n);
v = malloc(n * sizeof(int));
for(cont=2;cc<n;cont++){
if( prime2(cont) == true )
{
v[cc] = cont;
cc++;
}
}
for(cont=0;cont<n;cont++){
printf("%d ",v[cont]);
}
delete v;
}
Output:

Undefined reference error to function that is actually defined in C

I wrote this program to build a number diamond. The issue is that when I compile the program, it throws the error
build2.c:(.text+0x5): undefined reference to `get_input'
collect2: error: ld returned 1 exit status
I've tried for hours to figure out what exactly the problem is (e.g. if there is a spelling mistake or something similar), but the function call looks identical. I have attempted to rename it, write it as both a prototype and as an implementation, and nothing seems to work. Is there an issue that I'm not seeing?
//Define prior to main
int is_valid(int);
int get_input(void);
void print_pattern(int);
//Main
int main(void){
int diamond_size;
//diamond_size = get_input();
//value from get imput method used for diamond size
print_pattern(get_input());
return 0;
}
void print_pattern(int size){
int length, num, i, j;
//beginning of new diamond
printf("\n");
//Define each integer to work in layout of diamond
//First for loop fans out
for(i=1; i <= size; i += 2){
length = size-i+1;
num = 1;
printf("%*s", length," ");
for(j = 0; j < i; j++){
printf("%d ", num);
num++;
}
printf("\n");
}
//second for loop fans in
for(i=size-2; i >= 1; i -= 2){
length = size-i+1;
num = 1;
printf("%*s", length," ");
for(j = 0; j < i; j++){
printf("%d ", num);
num++;
}
printf("\n");
}
int is_valid(int value){
int rem;
//uses remainder to determine if it is odd or even; an even number will not have a reaminder in this case
rem = value % 2;
if (rem == 0){
printf("You've entered a even number. Please try again.\n");
return (0);
}
//greater than 9 cnd
if (value > 9){
printf("You have entered a number greater than 9. Please try again.\n");
return (0);
}
//less than 1 cnd
if (value < 1){
printf("You have entered a number less than 1. Please try again.\n");
return (0);
}
return (1);
}
int get_input()
{
int cont, number, valid;
cont = 1;
while (cont = 1)
{
printf("Enter an odd number less than 9 and greater than 0 < ");
scanf("%d", &number);
valid = is_valid(number);
if (valid == 1)
{
cont = 0;
}
}
return number;
}
}
You seem to have nested functions; this is (a) a non-standard GCC extension, and (b) I presume the scope of the nested get_input() function is the enclosing function, not the file scope. The solution is to move get_input() to file scope. At the end of print_pattern() add an extra }, and delete the final } at the end of the file.
Also, please format your code - most IDEs these days have options to tidy it up, and with correct indentation you may have seen your problem earlier.
Oh, and as a bonus bug fix, you also have in get_input():
while (cont = 1)
This will always be true - use this instead:
while (cont == 1)
The function print_pattern is not terminated at proper place but instead at the very end of the file:
void print_pattern(int size){
...
... end of the loop
}
... more functions
...
... end of print_pattern
}
This results into defining nested functions instead of global level.
It's generally good habit to indent the blocks, in which case you would realized the mistake very quickly.

Advance calculator for finding the mode of a set of numbers

I am currently working on a project for school in which I need to program a calculator to determine the mode of a set of numbers. The parameters are the numbers have to be between 1 and 30. Have to check whether the user inserts a number within that range and that the number must be validated as an integer. I have most of it done except my main issues are the for loop in inputing the numbers and validating them and making sure my mode function works. Any suggestions in fixing the issue with the loop? Also I must use a mode function in order to calculate the mode does the one I'm using work well or is there a better way in going about it?
#include <stdio.h>
#include <string.h>
#include <math.h>
int mode(int *num, int size);
int main(int n, char **p) {
int modearray[], size, i;
printf("What is the size of the Array?");
scanf("%d", &size);
for (i=0; i<modearray[size]; i++) {
printf("Enter an integer value (1 to 30): ");
scanf("%d", modearray[i]);
if (modearray[i] < 1 || modearray[i] > 30) {
printf("Please enter a value within the range");
scanf("%d", modearray[i])
}
else if (sscanf(p[i], "%i", &a[i]) != 1) {
printf("ERROR\n");
return -1;
}
}
}
//used the mode function code frome http://www.dreamincode.net/forums/topic/43713- pointers-and-modefunction/
int mode(int *num, int size) {
int currentnum = (*num);
int count = 0;
int modenum = -1;
int modecount = 1;
for (int x=0; x<size; x++) {
if (currentnum==(*num + x)) count ++;
else {
if(count > modecount) {
modenum = currentnum;
// modecount = count;
x--;
}
currentnum=*(num + x);
count = 0;
}
}
}
As Charlie and user2533527 have already indicated, there are errors in the OP code, and they have offered suggestions regarding those errors. There are a few others that I have noted in my edit of your original code below, that without addressing, the code did not build and/or run. So, if you are interested, look at the inline comments at the bottom of this post to see some corrections to your original code.
This answer is focused on validation of input, per your stated objective ( Have to check whether the user inserts a number within that range and that the number must be validated as an integer ) Specifically it appears you need to verify that the numbers input fall within a range, AND that they all be an integers.
If you move all of the validation steps into one function, such as:
int ValidateInput(char *num)
{
if(strstr(num, ".")!=NULL) return FLOAT;
if (atoi(num) < 1) return SMALL;
if (atoi(num) > 30) return LARGE;
return VALID;
}
then the main user input loop can be easily executed to include specific errors, if any, or continue with data collection by using a switch() statement, such as:
status = ValidateInput(number);
switch(status) {
case VALID:
modearray[i] = atoi(number);
printf("Enter an integer value %d: (1 to 30): ", i+2);
break;
case FLOAT:
printf("float detected, enter an integer");
i--;//try again
break;
case SMALL:
printf("value too small, enter value from 1 to 30");
i--;//try again
break;
case LARGE:
printf("value too large, enter value from 1 to 30");
i--;//try again
break;
default:
//do something else here
break;
}
Altogether, this approach does not use the mode function, rather replaces it with ValidateInput() which ensures only numbers that are integers, and within the stated range are included in the modearray varible.
EDIT to include searching for mode (highest occurring number within group)
My approach will do three things to get mode
sort the array,
walk through the sorted array tracking count of the matches along the way.
keep the highest string of matches.
To do this, I will use qsort() and looping in the mode() function.
int mode(int *num, int size) {
int count = 0;
int countKeep=0;
int modenum = -1;
qsort(num, size, sizeof(int), cmpfunc);
//now we have size in ascending order, get count of most occuring
for (int x=1; x<size; x++)
{
if(num[x-1] == num[x])
{
count++;
if(count > countKeep)
{
countKeep = count;
modenum=num[x];
}
else
{
count = 0;
}
}
}
return modenum;
}
Here is the complete code for my approach: (This code will capture the mode of a string of numbers with only one mode. You can modify the looping to determine if the string is multi-modal, or having two equally occuring numbers)
#include <ansi_c.h> //malloc
//#include <stdio.h>//I did not need these others, you might
//#include <string.h>
//#include <math.h>
int ValidateInput(char *num);
int mode(int *num, int size);
int cmpfunc (const void * a, const void * b);
enum {
VALID,
FLOAT,
SMALL,
LARGE
};
int main(int n, char **p)
{
int *modearray, size, i;
int *a;
char number[10];
int status=-1;
int modeOfArray;
printf("What is the size of the Array?");
scanf("%d", &size);
modearray = malloc(size*sizeof(int));
a = malloc(size);
printf("Enter an integer value 1: (1 to 30): ");
for (i=0; i<size; i++)
{
scanf("%s", number);
//Validate Number:
status = ValidateInput(number);
switch(status) {
case VALID:
modearray[i] = atoi(number);
printf("Enter an integer value %d: (1 to 30): ", i+2);
break;
case FLOAT:
printf("float detected, enter an integer");
i--;//try again
break;
case SMALL:
printf("value too small, enter value from 1 to 30");
i--;//try again
break;
case LARGE:
printf("value too large, enter value from 1 to 30");
i--;//try again
break;
default:
//do something else here
break;
}
}
modeOfArray = mode(modearray, size);
getchar();//to view printf before execution exits
}
int ValidateInput(char *num)
{
if(strstr(num, ".")!=NULL) return FLOAT;
if (atoi(num) < 1) return SMALL;
if (atoi(num) > 30) return LARGE;
return VALID;
}
int mode(int *num, int size) {
int count = 0;
int countKeep=0;
int modenum = -1;
qsort(num, size, sizeof(int), cmpfunc);
//now we have size in ascending order, get count of most occuring
for (int x=1; x<size; x++)
{
if(num[x-1] == num[x])
{
count++;
if(count > countKeep)
{
countKeep = count;
modenum=num[x];
}
else
{
count = 0;
}
}
}
return modenum;
}
int cmpfunc (const void * a, const void * b)
{
return ( *(int*)a - *(int*)b );
}
Assuming that the question is about crashing after the scanf in to array:
int main(int n, char **p) {
int *modearray, size, i;
printf("What is the size of the Array?");
scanf("%d", &size);
modearray = malloc(size * sizeof(int)); //imo size of int is 4 so u can replace with
for (i=0; i<modearray[size]; i++) {
printf("Enter an integer value (1 to 30): ");
scanf("%d", modearray[i]);
if (modearray[i] < 1 || modearray[i] > 30) {
printf("Please enter a value within the range");
scanf("%d", &modearray[i])
}
else if (sscanf(p[i], "%i", &a[i]) != 1) {
printf("ERROR\n");
return -1;
}
}
}

Resources