How to generate a new function in C? - c

I want a function that could take input a single integer from the user with validation, lets call it input_single_int. Such a function would greatly simplify my code. If a user gives incorrect input, then the function should show error and again prompt the user to fill out the correct input. The problem is the validation part, different inputs require different validation. Even if I send a validation function, how do I send the different parameters required by the validation function through input_single_int?
I want this function to be generic, so that I could use it multiple places. In the code given, if I add a parameter in input_single_int to accomodate input of variable b, I would have to change check_a function also, which I don't want to do. I also don't want to use global variables.
The only way which I could think of achieving this is through a function that could generate another function. Something like this:
func generate_check_b(int a) {
return int check_b(int b) { return (b > 0 && b < a); };
}
Is such a thing possible in C?
#define MM_SHOW 8
#define MM_QUIT 9
int input_single_int(int *var, char msg[], int exit_on_eq, int secondary_check(int val)) {
int inp_status, error, temp;
char skip;
do {
error = 0;
printf("%s", msg);
inp_status = scanf("%d", &temp);
if (inp_status != 1) {
error = 1;
do {
scanf("%c", &skip);
if (exit_on_eq) {
if (skip == 'e') {
system("clear");
return MM_SHOW;
} else if (skip == 'q') {
system("clear");
return MM_QUIT;
}
}
} while (skip != '\n');
}
if (!secondary_check(temp)) {
error = 1;
}
} while (error && printf("Please give a correct input.\n"));
*var = temp;
return 0;
}
int check_a(int a) { return a > 0;}
int check_b(int b, int a) { return (b > 0 && b < a);}
int main() {
int a, b;
char amsg[] = "a should be more than 0: ";
char bmsg[] = "b should be more than 0 and less than a: ";
input_single_int(&a, amsg, 1, check_a);
input_single_int(&b, bmsg, 1, check_b);
return 0;
}

A common idiom is a pair of parameters; a function and an opaque context pointer; so a simple case could be something like:
int check_range(int a, void *p) {
int *range = p;
return a >= range[0] && a < range[1];
}
struct Set { int n; int *vals; };
int check_set(int b, void *p) {
struct Set *s = p;
int i;
for (i = 0; i < s->n && s->vals[i] != b; i++) {}
return i < s->n;
}
If you look at the blocks extension to C supported by clang & gcc, it isn't far different from this, except that it is more sugary and has some really scary side effects.

Related

How can I call with a int function in main function?

I have a requirement to insert something in the function main > my_isneg to call my_isneg function. How can I do it?
#include <unistd.h>
void my_putchar (char c)
{
write (1, &c, 1);
}
int my_isneg (int n)
{
if (n < 0) {
my_putchar (78); }
else {
my_putchar (80);
}
}
int main (void)
{
my_isneg();
}
It's somewhat unclear what you're asking, but maybe you want this:
...
// print 'N' 1 if the number n is strictly negative, print 'P' otherwise
int my_isneg(int n)
{
if (n < 0) {
my_putchar('N'); // use 'N' instead of 80 (it's more readable)
}
else {
my_putchar('P'); // use 'P' instead of 80
}
}
int main(void)
{
my_isneg(-1);
my_isneg(1);
my_isneg(2);
}
Output
NPP
Or maybe this, which matches the name my_isneg more closely:
...
// return 1 if the number n is strictly negative
int my_isneg(int n)
{
return n < 0;
}
int main(void)
{
if (my_isneg(-1))
my_putchar('N');
else
my_putchar('P');
if (my_isneg(1))
my_putchar('N');
else
my_putchar('P');
}
Output
NP

Segmentation Fault when returning integer

I recently joined Stackoverflow community because I had to ask this question. I've been searching for possible explanations and solutions on the website but so far nothing enlightened me as I wanted. My error is probably caused by a very specific line of code. I'm trying to create a function that reads an array of struct votes, (struct contains integer member number, char *category, char *nominee) and copies all the votes that contain the same number and category to another array of struct. Basically to show all the repeated votes.
typedef struct
{
int member;
char *categ;
char *nom;
}Vote
Vote vote(int member, char *categ, char *nom)
{
Vote result;
result.member = member;
result.categ = categ;
result.nom = nom;
return result;
}
int votes_count(Vote *v, int n, Vote *v1)
{
int result = 0;
int *index = malloc(sizeof(int) * 1000);
int a = 0;
for (int i = 0; i < n; ++i)
{
for (int j = 0; j < n; ++j)
{
if (a == 0 && v[i].member == v[j].member && strcmp(v[i].categ, v[j].categ) == 0)
{
v1[result++] = vote(v[j].member, str_dup(v[j].categ), str_dup(v[j].nom));
index[a++] = j;
}
for (int b = 0; b < a; ++b)
{
if( a > 0 && v[i].member == v[j].member && strcmp(v[i].categ, v[j].categ) == 0 && j != index[b])
{
v1[result++] = voto(v[j].member, str_dup(v[j].categ), str_dup(v[j].nom));
index[a++] = j;
}
}
}
}
return result;
}
Afterwads, it returns the number of elements of new array that contains all repetitions. I want to use an array of ints to save all line indexes so that the function doesn't read and copy the lines it already accounted.
Sorry if the code is hard to understand, if needed I can edit to be more understandable. Thanks for any answears.
P.S: I'm portuguese, sorry in advance for grammar mistakes
if your only intention is to harvest the duplicates, you only need to compare to the elements that came before an element
you don't need the index[] array
For simplicity, I used two integer arrays, you should change them to your struct arrays, also change the compare function.
unsigned fetchdups(int orig[], int dups[], unsigned count)
{
unsigned this, that, ndup=0;
for (this=1; this<count; this++){
for (that=0; that<this; that++){
/* change this to your compare() */
if(orig[that] == orig[this]) break;
}
if (this == that) continue; /* no duplicate */
dups[ndup++] = this;
}
return ndup;
}

Customized sort in the order mentioned {2,3....9,A,B,C,D,1,E,F,0}

I am currently implementing a logic to sort the alphanumerical numbers in the order as mentioned {2,3....9,A,B,C,D,1,E,F,0}. Is there a easy and a possible way to do this? I prefer only C programming.
The request is regarding the sort of the 1st nibble in the PI code of FM RDS stations. As Germany is the only country which supports 2 PI codes(D & 1), the order is maintained in this manner.
Thanks in advance guys.
You should write a function (e.g., int custom_compare(const void *p1, const void *p2); that defines this sorting order. That method will return 1 if p1 comes after p2, 0 if they are 'equal', and -1 if p1 comes before p2.
Then, write your sorting method and call your ordering function instead of comparing using operators. That is, instead of if (a < b), use if (custom_compare(&b, &a)).
Also, I created that function prototype above (specifically using pointers as the parameters) because it would work with the qsort library, which is a quicksort implementation that accepts a custom comparison function.
An Implementation
I decided to quickly do a implementation of what I suggested and a small test example.
#include <stdlib.h>
#include <stdio.h>
int custom_compare(const void *p1, const void *p2) {
char *param1 = (char*)p1;
char *param2 = (char*)p2;
int loc1 = 0;
int loc2 = 0;
char order[17] = "23456789ABCD1EF0";
int i;
for (i=0; i<17; i++) {
if (*param1 == order[i]) { loc1 = i; }
if (*param2 == order[i]) { loc2 = i; }
}
if (loc2 < loc1) {
return 1;
} else if (loc1 < loc2) {
return -1;
} else {
return 0;
}
}
void bubble_sort_string(char *string) {
if (!string || !string[0] || !string[1]) { return; }
int i;
int tail = 0;
char tmp;
while (string[tail]) { tail++; }
while (tail) {
i = 1;
while (i <= tail) {
if (custom_compare(&string[i-1], &string[i]) > 0) {
// swap
tmp = string[i];
string[i] = string[i-1];
string[i-1] = tmp;
}
i++;
}
tail--;
}
}
int main() {
char string[33] = "00FFEE11DDCCBBAA9988776655443322";
printf("old string: %s\n", string);
bubble_sort_string(string);
printf("new_string: %s\n", string);
return 0;
}
Output:
$ ./csort
old string: 00FFEE11DDCCBBAA9988776655443322
new_string: 2233445566778899AABBCCDD11EEFF00
$

Calculator in C using stack

I'm trying to create a calculator in c, which can calculate with priority and get right results for examples like these:
((5+5)/3)*3) -- > 9
((1+2) * 3) -- > 9
These examples my code below can calculate. But for something like this
(2+5) * (2+5), my program gives wrong answer.
I'm using 2 stacks. One for operators and one for numbers. It works on this principle:
follows:
((4 - 2) * 5) + 3 --> normal infix expression:
+ * - 4 2 5 3
Pseudo code:
Read + (an operation), push it onto the stack,
Read * (an operation), push it onto the stack,
Read - (an operation), push it onto the stack,
Read 4 (a number), the top of the stack is not a number, so push it onto the stack.
Read 2 (a number), the top of the stack is a number, so pop from the stack twice, you get 4 - 2, calculate it (2), and push the result (2) onto the stack.
Read 5 (a number), the top of the stack is a number, so pop from the stack twice, you get 2 * 5, push the result (10) onto the stack.
Read 3 (a number), the top of the stack is a number, so pop from the stack twice, you get 3 + 10, push the result (13) onto the stack.
Nothing left to read, pop from the stack and return the result (13).
Actual code:
#include <stdio.h>
#include<ctype.h>
#include<stdlib.h>
#include<string.h>
#define MAXSIZE 102
typedef struct
{
char stk[MAXSIZE];
int top;
}STACK;
typedef struct stack
{
int stk[MAXSIZE];
int itop;
}INT_STACK;
STACK s;
INT_STACK a;
void push(char);
char pop(void);
void display(void);
int main()
{
a.itop = 0;
char string[MAXSIZE],vyb,vyb2;
int cislo1,cislo2,vysledok;
while (gets(string) != NULL){
for(int j = strlen(string); j > 0; j--){
if(string[j] == '*' || string[j] == '/' || string[j] == '+' || string[j] == '-')
push(string[j]);
}
//display();
for(int j = 0; j < strlen(string); j++){
if(isdigit(string[j])&&!(a.itop)){
//display();
char pomoc[2];
pomoc[0] = string[j];
pomoc[1] = '\0';
int_push(atoi(pomoc));
}
else if(isdigit(string[j])&&(a.itop)){
cislo1 = int_pop();
vyb2 = pop();
char pomoc[2];
pomoc[0] = string[j];
pomoc[1] = '\0';
cislo2 = atoi(pomoc);
if(vyb2 == '+')
vysledok = cislo1+cislo2;
else if(vyb2 == '-')
vysledok = cislo1-cislo2;
else if(vyb2 == '*')
vysledok = cislo1*cislo2;
else if(vyb2 == '/')
vysledok = cislo1 / cislo2;
//printf(" v %d",vysledok);
int_push(vysledok);
}
}
printf("%d\n",int_pop());
}
}
/* Function to add an element to the stack */
void push (char c)
{
s.top++;
s.stk[s.top] = c;
//printf ("pushed element is = %c \n", s.stk[s.top]);
}
/* Function to delete an element from the stack */
char pop ()
{
char num = s.stk[s.top];
// printf ("poped element is = %c\n", s.stk[s.top]);
s.top--;
return(num);
}
int empty()
{
if (s.top == - 1)
{
printf ("Stack is Empty\n");
return (s.top);
}
return 1;
}
void display ()
{
int i;
if (!empty)
{
printf ("Stack is empty\n");
return;
}
else
{
printf ("\n The status of the stack is \n");
for (i = s.top; i >= 0; i--)
{
printf ("%c\n", s.stk[i]);
}
}
printf ("\n");
}
void int_push (int c)
{
a.itop++;
a.stk[a.itop] = c;
//printf ("pushed element is = %d \n", a.stk[a.itop]);
}
/* Function to delete an element from the stack */
int int_pop ()
{
int num = a.stk[a.itop];
// printf ("poped element is = %d\n", a.stk[a.itop]);
a.itop--;
return(num);
}
Is there any other way to create a calculator with priority, which can give good answers?
Thanks for your respond
Put breakpoints - you'll get the following expression:
+ + * 2 5 2 5. The problem with that, is your interpreter is interpeting this as (2+5+2)*5 instead of (2+5) * (2+5).
Well then, you might be wondering how to solve this. There's no simple single solution - you could either fix your own interpreter or build a whole new mechanic, because the way you build expressions just can't handle more then one pair of parthesises.
For example, you may want to calculate all the values in parnthesises before even building the expression seperatley, possibly using recursion in the case of parenthesiseception - however if you actually choose to use that method, you might want to change the way you work with the expressions entirely, because that's a different approach.
If you need me to show actual code examples to explain this further using parts of the code you made, just ask for it and i'll edit and provide what you need.
Either way, I really advise you to look up working with interpreters in general - you could really learn a lot about analysing strings and working with different inputs, and people even did similar stuff to yours with calculators before
EDIT: you asked for examples, so here you go - this is an example of a completely different method using recursion. This way, you handle a single pair of parenthesises at a time, and thus you won't have the problem you currently do. Note - the source i'm basing this on ( pretty much copy-pasted with edits from the thread and some personal comments ) is from codereview on stack exchange, you can see it here
if you're intrested.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void getInput(char * in) {
printf("> ");
fgets(in, 256, stdin);
}
int isLeftParantheses(char p) {
if (p == '(') return 1;
else return 0;
}
int isRightParantheses(char p) {
if (p == ')') return 1;
else return 0;
}
int isOperator(char p) {
if (p == '+' || p == '-' || p == '*' || p == '/') return p;
else return 0;
}
int performOperator(int a, int b, char p) {
switch(p) {
case '+': return a+b;
case '-': return a-b;
case '*': return a*b;
case '/':
if (b == 0) { printf("Can't divide by 0, aborting...\n"); exit(1); } // now we dont want the world to expload here do we.
return a/b;
default:
puts("Bad value in switch.\n"); // A replacement which was mentioned in the thread- better have a default response just in case something goes wrong.
break;
}
return 0;
}
char isDigit(char p) {
if (p >= '0' && p <= '9') return 1;
else return 0;
}
int charToDigit(char p) {
if (p >= '0' && p <= '9') return p - '0';
else return 0;
}
int isNumber(char * p) {
while(*p) {
if (!isDigit(*p)) return 0;
p++;
}
return 1;
}
int len(char * p)
{
return (int) strlen(p); // This was bugged in the source, so I fixed it like the thread advised.
}
int numOfOperands(char * p) {
int total = 0;
while(*p) {
if (isOperator(*p)) total++;
p++;
}
return total+1;
}
int isMDGRoup(char *p)
{
for(; *p; p++) // used to be a while loop in the source, but this is better imho. more readable, also mentioned on the thread itself.
{
if (!isDigit(*p) && *p != '/' && *p != '*') return 0;
}
return 1;
}
int getLeftOperand(char * p, char * l) {
// Grab the left operand in p, put it in l,
//and return the index where it ends.
int i = 0;
// Operand is part of multi-*/ group
if (isMDGRoup(p)) {
while(1) {
if (*p == '*' || *p == '/') break;
l[i++] = *p++;
}
return i;
}
// Operand is in parantheses (so that's how you write it! sorry for my bad english :)
if(isLeftParantheses(*p)) {
int LeftParantheses = 1;
int RightParantheses= 0;
p++;
while(1) {
if (isLeftParantheses(*p)) LeftParantheses++;
if (isRightParantheses(*p)) RightParantheses++;
if (isRightParantheses(*p) && LeftParantheses == RightParantheses)
break;
l[i++] = *p++;
}
// while (!isRightParantheses(*p)) {
// l[i++] = *p++;
// }
l[i] = '\0';
return i+2;
}
// Operand is a number
while (1) {
if (!isDigit(*p)) break;
l[i++] = *p++;
}
l[i] = '\0';
return i;
}
int getOperator(char * p, int index, char * op) {
*op = p[index];
return index + 1;
}
int getRightOperand(char * p, char * l) {
// Grab the left operand in p, put it in l,
//and return the index where it ends.
while(*p && (isDigit(*p) || isOperator(*p) ||
isLeftParantheses(*p) || isRightParantheses(*p))) {
*l++ = *p++;
}
*l = '\0';
return 0;
}
int isEmpty(char * p) {
// Check if string/char is empty
if (len(p) == 0) return 1;
else return 0;
}
int calcExpression(char * p) {
// if p = #: return atoi(p)
//
// else:
// L = P.LeftSide
// O = P.Op
// R = P.RightSide
// return PerformOp(calcExpression(L), calcExpression(R), O)
// ACTUAL FUNCTION
// if p is a number, return it
if (isNumber(p)) return atoi(p);
// Get Left, Right and Op from p.
char leftOperand[256] = ""; char rightOperand[256]= "";
char op;
int leftOpIndex = getLeftOperand(p, leftOperand);
int operatorIndex = getOperator(p, leftOpIndex, &op);
int rightOpIndex = getRightOperand(p+operatorIndex, rightOperand);
printf("%s, %c, %s", leftOperand, op, rightOperand);
getchar();
if (isEmpty(rightOperand)) return calcExpression(leftOperand);
return performOperator(
calcExpression(leftOperand),
calcExpression(rightOperand),
op
);
}
int main()
{
char in[256];
while(1) {
// Read input from user
getInput(in);
if (strncmp(in, "quit", 4) == 0) break;
// Perform calculations
int result = calcExpression(in);
printf("%d\n", result);
}
}

Bubble sorting an array with nulls in C

I'm trying to create a bubble sort with nulls in the middle in C.
The code works ok when the array is ordered in a way so the nulls are at the end of the array (hense the "continue" condition works).
My array looks like this: [John,David,NULL,Grace,NULL,NULL]
on which I run this function:
void SortContacts(char * people[]) {
int i,j;
char *tempswap;
for (i=0; i<storage-1; i++) {
for (j=0; j<storage-i-1; j++) {
if (people[j+1]==NULL) {
continue;
}
if (strcmp(people[j],people[j+1]) > 0) {
tempswap = people[j];
people[j] = people[j+1];
people[j+1] = tempswap;
}
}
}
}
When executing with the NULL in the middle of the array the exe crashes.
You cannot strcmp a NULL value. Although you are guarding against a strcmp of people[j+1] being NULL, you don't check people[j].
Try the following (untested), which simply provides a strcmp function which treats a NULL like "".
int
strcmpwithnull(const char *a, const char *b)
{
return strcmp(a?a:"", b?b:"");
}
void SortContacts(char * people[]) {
int i,j;
char *tempswap;
for (i=0; i<storage-1; i++) {
for (j=0; j<storage-i-1; j++) {
if (strcmpwithnull(people[j],people[j+1]) > 0) {
tempswap = people[j];
people[j] = people[j+1];
people[j+1] = tempswap;
}
}
}
}
If you want a NULL to be treated as greater than any other string, then try (again untested):
int
strcmpwithnull(const char *a, const char *b)
{
if (a == b)
return 0; /* handles 2 NULLs and two strings at the same location */
else if (!a)
return 1;
else if (!b)
return -1;
else
return strcmp(a, b);
}
If you want them to be less than any other string (including the empty string), swap the return 1 and return -1.
Here is the problem
if (people[j+1]==NULL)
{
continue;
}
You need to check both j and j+1
Also consider What if you have a NULL in the head of the array ? or you have 2 NULLs one after another
So you need also to check the j not only the j+1
you should also check thejisn't null
You want to end up with the nulls at the right of the array. This can be achieved by making nulls strictly greater than any string. You have to encode this into the comparison function.
int cmp(const char *x, const char *y)
{ if(x == 0) return 1;
if(y == 0) return -1;
return strcmp(x, y);
}

Resources