Stack around the variable was corrupted with pointer arithmetics - c

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.

Related

My c program keeps crashing and I do not know why

I am writing a program like hangman in c and I am trying to run it .The problem is that it's working fine until I give it a letter to quess the word but then it crashes with -1073741819 (0xC0000005). Can someone help me solve this, I think its something really small that I cant
see . Thank you for helping me!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void Rules(void);
void maskWord (char starword[], int size);
int playRound(char starword[], char answer[]);
void updateStarWord(char starword[], char answer[], char userguess);
int occurancesInWord(char userguess, char answer[]);
int c=0;
char answer[128];
int N;
int main()
{
int ch,size;
char starword[1000];
do
{
printf("---Welcome to Hangman!---\n");
printf("1.Start Game\n2.Instructions\n3.Exit\n");
scanf("%d",&ch);
if(ch>0&& ch<4)
{
switch(ch)
{
case 1:
maskWord(starword,size);break;
case 2:
Rules();break;
}
}
else
system("cls");
}
while(ch!=3);
return 0;
}
void Rules(void)
{
do
{
do
{
printf("\nThe word to guess is represented by a row of dashes representing each letter of the word.");
printf("\nRules may permit or forbid proper nouns, such as names, places, brands, or slang.");
printf("\nIf the guessing player suggests a letter which occurs in the word, the other player writes it in all its correct positions.");
printf("\nIf the suggested letter does not occur in the word, the other player draws one element of a hanged stick figure as a tally mark.\n");
}
while(getchar()!='\n');
}
while(getchar()!='\n');
}
void maskWord (char starword[], int size)
{
printf("Enter word to guess: ");
fflush(stdout);
scanf(" %s", answer);
int N = strlen(answer);
int mask[N];
for (int i=0; i < N; ++i)
{
mask[i] = 0;
}
playRound(mask,N);
}
int playRound(char starword[], char answer[])
{
// Loop over each round of guessing
int gameover = 0;
while (! gameover)
{
// Print word with *s for unguessed letters
printf("The word is : ");
for(int j=0; j < answer; ++j)
{
if (starword[j])
{
printf("%c", answer[j]);
}
else
{
printf("*");
}
}
printf("\n");
// Get player's next guess
char guess;
printf("\nGive a letter: ");
fflush(stdout);
scanf(" %c", &guess);
updateStarWord(starword,answer,guess);
}
}
void updateStarWord(char starword[], char answer[], char userguess)
{
// Mark true all mask positions corresponding to guess
int k;
for(k=0; k < answer; ++k)
{
if ((answer[k]) ==(userguess))
{
starword[k] = 1;
}
}
}
Your for loop doesn't make sense because the condition for terminating it is k < answer. You are comparing an integer (k) to a pointer (answer). The compiler should have warned you about this, so make sure your compiler warnings are turned on and you are paying attention to them. Pointers and integers are different things, and comparing them is almost never what you want to do.
If answer is null-terminated, you could probably replace that condition with answer[k]. Or maybe updateStarWord needs to take an argument that indicates the length of answer, and then the condition would be k < answer_length.

Hackerrank problem (Post Transition) (C) What's causing this seg fault?

I've been trying to solve this problem on hackerrank
https://www.hackerrank.com/challenges/post-transition
but my code seems to yield a segmentation fault when I try to run it.
I've gone over it a couple dozen times already and have compared it to other people's solution and I still can't wrap my head around what I might be doing wrong.
Here is the error message I'm getting :
Reading symbols from Solution...done.
[New LWP 1602418]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Core was generated by `./Solution'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0 send_all_acceptable_packages (source=source#entry=0x16eeec8,
source_office_index=0, target=target#entry=0x16eeee0,
target_office_index=<optimized out>) at Solution.c:58
58 int src_pk_count = (source->offices[source_office_index].packages_count);
Here is my code
#include <stdlib.h>
#include <string.h>
#define MAX_STRING_LENGTH 6
struct package
{
char* id;
int weight;
};
typedef struct package package;
struct post_office
{
int min_weight;
int max_weight;
package* packages;
int packages_count;
};
typedef struct post_office post_office;
struct town
{
char* name;
post_office* offices;
int offices_count;
};
typedef struct town town;
void print_all_packages(town t)
{
printf("%s:\n",t.name);
//offices loop
for(int i=0;i<t.offices_count;i++)
{
printf("\t%i:\n",i);
//packages loop
for(int j=0;j<t.offices[i].packages_count;j++)
{printf("\t\t%s\n", t.offices[i].packages[j].id);}
}
}
void send_all_acceptable_packages
(town* source, int source_office_index, town* target, int target_office_index)
{
int trg_pk_count = (target->offices[target_office_index].packages_count);
int src_pk_count = (source->offices[source_office_index].packages_count);
//weight condition
int min_w = (target->offices[target_office_index].min_weight);
int max_w = (target->offices[target_office_index].max_weight);
for(int i=0;i<src_pk_count;i++)
{
int pckg_w = (source->offices[source_office_index].packages[i].weight);
if ((pckg_w >= min_w) && (pckg_w <= max_w))
{
target->offices[target_office_index].packages = realloc (target->offices[target_office_index].packages, sizeof(package)* (trg_pk_count+1));
(target->offices[target_office_index].packages_count)++;
(source->offices[source_office_index].packages_count)--;
target->offices[target_office_index].packages[(trg_pk_count)]= source->offices[source_office_index].packages[i];
for(int x=0; x<(src_pk_count-1);x++)
{
source->offices[source_office_index].packages[i+x] = source->offices [source_office_index].packages[i+x+1] ;
source->offices[source_office_index].packages= realloc(source->offices [source_office_index].packages, sizeof(package)*((source->offices [source_office_index].packages_count)));
}
}
}
}
town town_with_most_packages(town* towns, int towns_count)
{
//count
int town_pkcount[towns_count];
for(int i=0;i<towns_count;i++)
{
town_pkcount[i]=0;
int sum=0;
for(int j=0;j<towns[i].offices_count;j++)
{
sum+= towns[i].offices[j].packages_count;
}
town_pkcount[i]=sum;
}
//find max
int max=-1 , max_index;
for(int i=0; i<towns_count;i++)
{
if (town_pkcount[i]>max)
{
max = town_pkcount[i];
max_index=i;
}
}
return towns[max_index];
}
town* find_town(town* towns, int towns_count, char* name)
{
int town_index=-1;
for(int i=0; i<towns_count; i++)
{
if(strcmp(name,towns[i].name)==0)
{town_index = i;}
break;
}
return(&towns[town_index]);
}
int main()
{
int towns_count;
scanf("%d", &towns_count);
town* towns = malloc(sizeof(town)*towns_count);
for (int i = 0; i < towns_count; i++) {
towns[i].name = malloc(sizeof(char) * MAX_STRING_LENGTH);
scanf("%s", towns[i].name);
scanf("%d", &towns[i].offices_count);
towns[i].offices = malloc(sizeof(post_office)*towns[i].offices_count);
for (int j = 0; j < towns[i].offices_count; j++) {
scanf("%d%d%d", &towns[i].offices[j].packages_count, &towns[i].offices[j].min_weight, &towns[i].offices[j].max_weight);
towns[i].offices[j].packages = malloc(sizeof(package)*towns[i].offices[j].packages_count);
for (int k = 0; k < towns[i].offices[j].packages_count; k++) {
towns[i].offices[j].packages[k].id = malloc(sizeof(char) * MAX_STRING_LENGTH);
scanf("%s", towns[i].offices[j].packages[k].id);
scanf("%d", &towns[i].offices[j].packages[k].weight);
}
}
}
int queries;
scanf("%d", &queries);
char town_name[MAX_STRING_LENGTH];
while (queries--) {
int type;
scanf("%d", &type);
switch (type) {
case 1:
scanf("%s", town_name);
town* t = find_town(towns, towns_count, town_name);
print_all_packages(*t);
break;
case 2:
scanf("%s", town_name);
town* source = find_town(towns, towns_count, town_name);
int source_index;
scanf("%d", &source_index);
scanf("%s", town_name);
town* target = find_town(towns, towns_count, town_name);
int target_index;
scanf("%d", &target_index);
send_all_acceptable_packages(source, source_index, target, target_index);
break;
case 3:
printf("Town with the most number of packages is %s\n", town_with_most_packages(towns, towns_count).name);
break;
}
}
return 0;
}
keep in mind that the structs and the main function were already pre-written
The seg fault seems to have something to do with the send_all_acceptable_packages function
Also keep in mind that the seg fault happens after entering this line of input
2 B 0 A 1
which triggers case 2 in main
case 2:
scanf("%s", town_name);
town* source = find_town(towns, towns_count, town_name);
int source_index;
scanf("%d", &source_index);
scanf("%s", town_name);
town* target = find_town(towns, towns_count, town_name);
int target_index;
scanf("%d", &target_index);
send_all_acceptable_packages(source, source_index, target, target_index);
break;
where you can see that the return value from the find_town function is used as input for the send_all_acceptable_packages function which leads me to believe the fault lies within one of these two functions
Please help me identify the issue here, I'd appreciate your input.
The loop in the following will never iterate:
town* find_town(town* towns, int towns_count, char* name)
{
int town_index=-1;
int i = 0;
for(i=0; i < towns_count; i++)<-warning points here (i++)
{
if(strcmp(name,towns[i].name)==0)
{ town_index = i;}
break;<- cause of warning
}
return(&towns[town_index]);
}
I see the following warning from my debugger:
150, 31 warning: will never be executed
The break statement guarantees the loop will never iterate.
You probably intended for it to be inside the if() statement
town* find_town(town* towns, int towns_count, char* name)
{
int town_index=-1;
int i = 0;
for(i=0; i < towns_count; i++)
{
if(strcmp(name,towns[i].name)==0)
{
town_index = i;
break;
}
}
return(&towns[town_index]);
}
A few additional items to look at:
int main(void); is the minimum prototype for the main function in C ( not int main())
code does not check the returns of function(s) that should always be checked (eg scanf()).
It would be better to limit the input length for the calls to scanf() to prevent overflows, i.e. with #define MAX_STRING_LENGTH 6, the user is limit to some very short names, but if city is entered as "Dallas" scanf("%s", towns[i].name); program will overflow. Write it as scanf("%(MAX_STRING_LENGTH-1)s", towns[i].name); to limit user input to a legal length.
Suggest changing #define MAX_STRING_LENGTH 6 to a more realistic value.
Memory leaks. Code frees none of the memory created. Use call to free() once for each call to malloc()
use printf() prior to each scanf() to list instructions for user input. (eg: printf("enter town name\n"); )

Accessing and inputting elements into a dynamic array of structs in C

I am trying to access different elements in my dynamic struct array however I can't seem to access any other element in the array besides the first.
C file
#include <stdio.h>
#include <stdlib.h>
#include "tuples.h"
void createTuple();
int main() {
createTuple();
return 0;
}
void createTuple(){
int numOfTup;
printf("How many tuples would you like to create:\n");
scanf(" %d", &numOfTup);
tuple_t *tuples;
tuples = malloc(numOfTup * sizeof(char) * sizeof(int) * 3);
if (tuples == NULL){
printf("Memory allocation failed");
exit(EXIT_FAILURE);
}
for (int j = 0; j < numOfTup; ++j) {
printf("Enter an identifier for the Tuple: \n");
scanf(" %c", &tuples[j].identifier);
printf("TUPLE: %c\n",tuples[j].identifier);
for (int i = 0; i < 4; ++i) {
printf("Enter the value for the tuple (C:I:I:I)\n");
if (i == 0) {
scanf(" %c", &tuples[j].val0);
} else if (i == 1) {
scanf(" %d", &tuples[j].val1);
} else if (i == 2) {
scanf(" %d", &tuples[j].val2);
} else if (i == 3) {
scanf(" %d", &tuples[j].val3);
}
}
}
}
Header file for the struct
#ifndef TASK2_TUPLES_H
#define TASK2_TUPLES_H
struct tuple{
char identifier[100];
char val0;
int val1;
int val2;
int val3;
};
typedef struct tuple tuple_t;
#endif //TASK2_TUPLES_H
I can't seem to access the struct at tuples[j] because whenever I try to run it it only saves the first set of elements.
Also whenever inputting the identifier the compiler skips the loop and does not allow me to enter any elements into the struct.
Thanks.
For starters, the statement:
tuples = malloc(numOfTup * sizeof(char) * sizeof(int) * 3);
//always ==1 why? why?
Should look more like:
tuples = malloc(numOfTup * sizeof(*tuples));
and:
scanf(" %c", &tuples[j].identifier);//wrong format specifier for string
^^^ ^ //and address of ( & ) operator not needed for string.
Should be:
scanf("%s", tuples[j].identifier);
^^ ^
There are several issues with your code:
You allocate nowhere near enough memory. If your tuple identifier is 100 chars, you should allocate at least 101 * sizeof(char) + 3*sizeof(int) bytes of memory. In practice, this might not suffice because the compiler might pad the struct to better align with memory. Thus, the real size might be greater. The safe thing to do is to allocate sizeof(tuple_t) bytes
Your scanf function to read the identifier reads a char, not a string. use %s to read string. Also, scanf expects pointers to already allocated objects of the type specified by their corresponding format specifier, in our case, %s is a string, so the type should be char *. Thus, the parameter should be tuples[j].identifier, rather than &tuples[j].identifier
Overall:
#include <stdio.h>
#include <stdlib.h>
#include "tuples.h"
void createTuple();
int main() {
createTuple();
return 0;
}
void createTuple(){
int numOfTup;
printf("How many tuples would you like to create:\n");
scanf(" %d", &numOfTup);
tuple_t *tuples;
tuples = malloc(numOfTup * sizeof(tuple_t));
if (tuples == NULL){
printf("Memory allocation failed");
exit(EXIT_FAILURE);
}
for (int j = 0; j < numOfTup; ++j) {
printf("Enter an identifier for the Tuple: \n");
scanf("%s", tuples[j].identifier);
printf("TUPLE: %s\n",tuples[j].identifier);
for (int i = 0; i < 4; ++i) {
printf("Enter the value for the tuple (C:I:I:I)\n");
if (i == 0) {
scanf(" %c", &tuples[j].val0);
} else if (i == 1) {
scanf(" %d", &tuples[j].val1);
} else if (i == 2) {
scanf(" %d", &tuples[j].val2);
} else if (i == 3) {
scanf(" %d", &tuples[j].val3);
}
}
}
}

C scanf in loop continues automaticly without input

I'm trying to get input in an array, I expect input like the following.
5 (Number of the second dimensions in the array)
2 (Number of the first dimensions in the array)
So we get an array deeln[2][5] in this example. I try to get it with the following code:
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
bool isinarray(int val, int *arr, int size){
int countimp;
for (countimp=0; countimp < size; countimp++) {
if (arr[countimp] == val)
return true;
}
return false;
}
int main(void){
int k, d, ci, cj, ck, ta;
//get input
scanf("%i", &k);
scanf("%i", &d);
int deeln[d][k], temp[k];
for(ci = 0; ci < d; ci++){
printf("d= %i, ci= %i \n", d, ci);
scanf("%s", temp);
for(cj = 0; cj < k; cj++){
deeln[ci][cj] = temp[cj*2]-'0';
}
}
//loop while.
}
But i've got a problem, whenever i try to input, the program runs automaticly without getting any input when it loops around the third scanf for the 2nd or 3rd time. So then i'm not able to input anything.
What to do? Has it something to do with pointers or am i using scanf wrong?
UPDATE:
If I enter a printf after printf("cj is nu %i \n", cj); then the output also just came after the loop was going its own way. and not before i should give more input, using the third scanf.
The solution of my question was quite easy. I found it after thinking of my input. The problem was that in the input, as described, there were spaces. Somehow scanf can't handle with spaces, unless you use some other syntax. But my solution is to just use fgets instead of scanf where I wanted to get the input. So the new and working code is as follows:
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
bool isinarray(int val, int *arr, int size){
int countimp = 0;
for (countimp=0; countimp < size; countimp++) {
if (arr[countimp] == val)
return true;
}
return false;
}
int main(void){
int t, k = 0, d = 0, ci = 0, cj = 0, ta = 0;
//get input
scanf("%i", &k);
scanf("%i", &d);
char temp[20];
int deeln[d][k];
memset(deeln, 0 , sizeof(deeln));
memset(temp, 0 , sizeof(temp));
for(ci = 0; ci < d; ci++){
fgets(temp, 20, stdin);
for(cj = 0; cj < k; cj++){
ta = cj*2;
deeln[ci][cj] = temp[ta]-'0';
}
}
//loop while.
return 1;
}
Thanks for helping everbody, even though we all didn't came to this. But I hope it will help others!
Two places to look:
1)
cj = 0;//initialize cj before using here
scanf("%i", &temp[cj]);//temp is both an array, and an int. Fix your format specifier,
//and use an index operator - temp[?] (not sure I am using the right index)
2)
deeln[ci][cj] = temp[cj*2]-'0'; //fix your logic here (array index will be exceeded)
An example of working code...
int main(void){
int k, d, ci, cj, ck, ta;
//get input
scanf("%i", &k);
scanf("%i", &d);
int deeln[d][k], temp[k];
for(ci = 0; ci < d; ci++){
printf("d= %i, ci= %i \n", d, ci);
for(cj = 0; cj < k; cj++){
if(scanf("%i", &temp[cj]) != EOF)
{
deeln[ci][cj] = temp[cj]-'0';
}
else deeln[ci][cj] = -1;
}
}
getchar();
//loop while.
}
you can play with the index of temp[cj] to make it what you actually want, but I assume you are intending to read from stdin, then populate deeln[][] with that value, for each scanf.
If you want to parse a string containing spaces and digets, "1 3 8 5 3", you could use strtok()
But your code as it is is not reading a string in, it is reading integers.
This is not perfect, you will have to do some debug, but will illustrate strtok(). You have to enter spaces between each digit after indices are selected: i.e.:
3
3
4 6 8
2 4 7
1 2 8
int main(void){
int k, d, ci, cj, ck, ta;
//get input
scanf("%i", &k);
scanf("%i", &d);
char inStr[d][k*5]; //space for up to k 3 digit numbers with 1 space each
char *buf=0;
int deeln[d][k], temp[k];
for(ci = 0; ci < d; ci++){
printf("d= %i, ci= %i \n", d, ci);
if(scanf("%s ", inStr[ci]) != EOF)
{
buf = strtok(inStr[ci], " ");
cj = 0;
while(buf && (cj < k))
{
deeln[ci][cj] = atoi(buf);
cj++;
}
}
}
//getchar();waits for user input, pauses execution
}

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