How do I use this statement more efficiently - c

Is there a way for me to write below code in lesser characters?
if (num == 1 || num == 2 || num == 3 || num == 4|| num == 5)
{
printf("Enter number you want to convert:\n");
scanf("%d", &a);
}
else
{
goto quit;
}
Like in SQL we use:
if (num in 1,2,3,4,5)
or like in some imaginary language if we could use something like:
if num in [1-5]

If the num can be compared in a range like 1 to 5 can simply write
if (num >= 1 && num <= 5)
{
///.....
}
This is mentioned in other comments and answers. But if the numbers you need to compare are not in a range then the code can be complicated. For me, the simpler way is :
if (num == 1 || num == -2 || num == 3 || num == 10 || num == 5)
{
//......
}
But there is another way to write code like SQL(mentioned in the question). Using variable argument can implement a function : 
is_equal(total number of arguments with num variable, num , list of numbers need to compare ..))
This can provide similar code to if (num in 1,2,3,4,5)
#include <stdio.h>
#include <stdarg.h>
int is_equal(int count,...) {
va_list valist;
int ret = 0 ;
int num ;
/* initialize valist for num number of arguments */
va_start(valist, count);
/* access all the arguments assigned to valist */
for (int i = 0; i < count; i++) {
if(i == 0) num = va_arg(valist, int) ;
else{
if(num == va_arg(valist, int))
ret = 1 ;
}
}
/* clean memory reserved for valist */
va_end(valist);
return ret;
}
int main() {
int num = 12 ;
printf("%d\n" , is_equal(5 ,num , 1, 2, 3, 4)) ;
printf("%d\n" , is_equal(4 ,num, 1, 2, 3)) ;
printf("%d\n" , is_equal(6 ,num, 1, 2, 3, 4, 12)) ;
printf("%d\n" , is_equal(8 ,num, 1, 2, 3, 4, 7, -14, 12)) ;
printf("%d\n" , is_equal(9 ,num, 1, 2, 3, 4, 7, -14, -12 , 120)) ;
}
Output :
0
0
1
1
0

Use relational comparison operators to check if a number is within the lower and upper bounds of a range:
if (num >= 1 && num <= 5)
{
printf("Enter number you want to convert:\n");
scanf("%d", &a);
}
else
{
goto quit;
}

or use switch:
switch (num)
{
case 1:
case 2:
case 3:
case 4:
case 5:
printf("Enter number you want to convert:\n");
scanf("%d", &a);
break;
default:
goto quit;
}

Related

Why is my program only printing my last number instead of all of the input numbers?

The problem I was given to solve is "The number of students who will take the exam is entered from the keyboard, and then the IDs of all the students who will take the exam are entered. The program should divide the students into three groups: students with IDs ending in the digits 0, 1, and 2, students with IDs ending in the digits 3, 4, 5, and students with IDs ending in the digits 6, 7, 8, 9 .The program should print the IDs for each group, in the same order as they were entered. The maximum number of students that can be entered is 1000.".
The code that I can come up with is
#include <stdio.h>
int main() {
int n,br,gr1,gr2,gr3;
scanf("%d",&n);
for (int i = 0; i < n; ++i) {
scanf("%d", &br);
if (br % 10 == 0 || br % 10 == 1 || br % 10 == 2)
{
gr1 = br;
}
else if (br % 10 == 3 || br % 10 == 4 || br % 10 == 5)
{
gr2 = br;
}
else if (br % 10 == 6 || br % 10 == 7 || br % 10 == 8 || br % 10 == 9)
{
gr3 = br;
}
}
printf("Grupa 1\n%d\n",gr1);
printf("Grupa 2\n%d\n",gr2);
printf("Grupa 1\n%d\n",gr3);
return 0;
}
Instead of printing all the IDs and sorting them into groups it is only printing the last input number and group number.
I am in no way an experienced programmer so I can't really tell what is wrong with the way I have written this or how to solve it. I would appreciate it if you can guide me through
The output I am expecting is:
Grupa 1
20010 20581 19452
Grupa 2
20145 19873 19825 20653
Grupa 3
20147 20139 19458
The output I am getting is
Grupa 1
19452
Grupa 2
20653
Grupa 3
19458
Your gr1,gr2,gr3 int variables can only store one values at a time (here, the last value that was assigned to it so its showing only one result.) Make them something like an array eg gr1[],gr2[],gr3[], which will be able to hold multiple values at a time and will be able to print them out at the end.
The way you format you code makes it harder for yourself to figure out what is going on. You need to stash in a data in an ordered data structure (array, linked list etc):
#include <stdio.h>
#include <stdlib.h>
#define MAX_STUDENTS 1000
typedef size_t student_id;
enum group {
GROUP_1 = 1,
GROUP_2,
GROUP_3
};
enum group group_student(student_id id) {
switch(id % 10) {
case 0: case 1: case 2:
return GROUP_1;
case 3: case 4: case 5:
return GROUP_2;
default:
return GROUP_3;
}
}
int main(void) {
student_id ids[MAX_STUDENTS];
size_t n = 0; // required below
for(; n < sizeof ids / sizeof *ids; n++) {
if(scanf("%zu", ids + n) != 1) {
break;
}
}
for(enum group group = GROUP_1; group <= GROUP_3; group++) {
printf("Grupa %d\n", group);
for(size_t j = 0; j < n; j++) {
if(group == group_student(ids[j]))
printf("%zu ", ids[j]);
}
printf("\n");
}
}
and here is an example run:
$ echo '20010 20581 19452 20145 19873 19825 20653 20147 20139 19458' | ./a.out
Grupa 1
20010 20581 19452
Grupa 2
20145 19873 19825 20653
Grupa 3
20147 20139 19458
When you type this in, end input with ctrl-D. I used a enum group here as it's an identifier (not a number) and documents by virtue of the return type that you change the enum you want to change the function group_student(), too.

How do you write multiple conditions on if statements

if (num1 == (1,2,3,4,5,6,7,8,9)){
*some command*
}
does this sequence work, if not can you guide me masters. I'm a beginner
Try this:
if(num1 >= 1 && num1 <= 9) {
// Some code
}
&& operator will make sure num1 should be between 1 to 9 including it (i.e. 1, 9). It will execute some code only if both the conditions are true.
If the numbers you're testing for are in a continuous range, you can bound the value with greater than and less than (or equals):
For example, if you're testing if an int n is one of 1, 2, 3, 4, 5, 6, 7, 8, 9, you can do this:
if(n >= 1 && n <= 9)
{
// Code
}
If, however, the numbers are not a continuous range you have no choice but to explicitly test every value. So, if you were checking if n was one of 13, 57, -3, 11, -66, 100, you could have to write it out completely (or use a switch statement or lookup table):
if(13 == n || 57 == n || -3 == n || 11 == n || -66 == n || 100 == n)
{
// Code
}
Alternatively (only for integral types):
switch (n)
{
case 13:
case 57:
case -3:
case 11:
case -66:
case 100:
// Code
break;
}
You may want to write a helper method in the latter case to make it more clear what you're testing for. e.g.:
if(IsAcceptableValueForTask(n))
Where IsAcceptableValueForTask returns an int representing the truth (1|0) of 13 == n || 57 == n || -3 == n || 11 == n || -66 == n || 100 == n
You can use
if (num1 == 1 || num1 == 2 || num1 == 3 || num1 == 4 || num1 == 5 || num1 == 6 || num1 == 7 || num1 == 8 || num1 == 9 ){
//code
}
If you want to check between a range of numbers you can use
if(num1 >= 1 && num1 <= 9) {
//code
}
You can also use switch statement for more convenience if the numbers are random and there are many conditions

Search for `count' distinct odd numbers that are smaller than `bound' and add up to `sum'

I am working on a problem that finds 'count' odd numbers below the int value 'bound' and adds up to an int value sum. It is suggested that I use recursion to solve.
I have completed the recursion and have made it solve 7 / 8 cases in mimir. There is one case that is showing a fail but I cannot figure out what is wrong even when stepping through with gdb.
Problem case:
Input: 10 54 108
EDIT:
So it turns out that my code is correct and is finding the correct answer for this case ( AKA - No solution exists ) but my problem is that I only have 3 sec of run time to find this solution and currently my code takes longer than that.
Not looking for a straight answer necessarily, more of a point in the right direction. Trying to learn from this :)
https://ibb.co/4138WBw
int odd_sum(int count, int bound, int sum)
{
if (bound % 2 == 0)
return odd_sum(count, bound -1, sum);
else if ( sum == 0 && count == 0 && bound >= -1)
return 1;
else if ( sum - bound < 0)
return odd_sum(count, bound - 2, sum);
else if (count == 0 && sum != 0)
return 0;
else if (bound < 1 && sum != 0)
return 0;
else
{
int value = (odd_sum(count - 1, bound - 2, sum - bound));
if ( value )
{
return printf("%d ", bound);
}
else
return (odd_sum(count - 1, bound - 2, sum - bound));
}
/* Do not change the main() function */
int main(void)
{
int value;
int c, b, s;
printf("Please enter 3 positive integers: count, bound, and sum:\n");
if (scanf("%d%d%d", &c, &b, &s) != 3) {
printf("Please enter 3 integers.\n");
return 1;
}
if (c <= 0 || b <= 0 || s <= 0) {
printf("Integers must be positive.\n");
return 1;
}
value = odd_sum(c, b, s);
if (value)
printf("\n");
else
printf("There are no solutions.\n");
return 0;
}
The final result needs to look like this for the two cases, ( pass or fail )
$./odd_sum
Please enter 3 positive integers: count, bound, and sum:
10 20 100
1 3 5 7 9 11 13 15 17 19
$./odd_sum
Please enter 3 positive integers: count, bound, and sum:
10 18 100
There are no solutions.
$./odd_sum
Please enter 3 positive integers: count, bound, and sum:
12 30 200
5 7 9 11 13 15 17 19 23 25 27 29
Thank you guys in advance
This code seems to return the correct result for input, (10, 54, 108): 1 3 5 7 9 11 13 15 17 27
int odd_sum(int count, int bound, int sum){
if (count == 0 && sum == 0)
return 1;
if (count == 0 || bound <= 0)
return 0;
if (bound % 2 == 0)
return odd_sum(count, bound - 1, sum);
if (odd_sum(count - 1, bound - 2, sum - bound))
return printf("%d ", bound);
else
return odd_sum(count, bound - 2, sum);
return 0;
}

Loop through odd numbers and 2

Is it possible in C to have a fast for/while loop that loops through the odd numbers and 2? Without using arrays.
So I'd like it to loop through {1, 2, 3, 5, 7, 9, ..}
Of course. Here is a pretty straight forward way.
for(int i=1; i<N; i++) {
if(i>3) i++;
// Code
}
A bit more hackish variant:
for(int i=1; i<N; i+=1+(i>2)) {
// Code
}
But I think in this case that the most readable variant would be something like:
// Code for 1 and 2
// Then code for 3,5,7 ...
for(int i=3; i<N; i+=2) {
// Code
}
Another option
for(int i=1;;++i) // you didn't specify a limit
{
switch(i)
{
default:
if(!(i&1))continue;
case 1:
case 2:
DoSomething(i):
}
}
Another alternative which does use an array but only a small one that is a constant size of two elements no matter how many numbers in the sequence would be:
{
int i;
int iray[] = {1, 2};
int n = 15;
for (i = 1; i < n; i += iray[i > 2]) {
printf (" i = %d \n", i);
// code
}
}
which produces:
i = 1
i = 2
i = 3
i = 5
i = 7
i = 9
i = 11
i = 13
Extending this alternative to other sequences
And this alternative can be extended to other sequences where there is a change of a similar nature. For instance if the desired sequence was
1, 2, 3, 5, 8, 11, ..
Which involves several changes in the sequence. Beginning at 1 an increment of 1 is used followed by a first increment change beginning at 3 where an increment of 2 is used followed by a second change in the sequence beginning at 5 where an increment of 3 is used, you can make the following modification.
{
int i;
int iray[] = {1, 2, 3}; // increment changes
int n = 15;
// calculate the increment based on the current value of i
for (i = 1; i < n; i += iray[(i > 2) + (i > 3)]) {
printf (" i = %d \n", i);
// code
}
return 0;
}
which would produce:
i = 1
i = 2
i = 3
i = 5
i = 8
i = 11
i = 14
#include <stdio.h>
int main()
{
for(unsigned x = 0; x < 10; x++)
printf("%u%s element - %u\n",x + 1, !x ? "st" : x == 1 ? "nd" : x == 2 ? "rd" : "th", !x + x * 2 - (x >= 2));
return 0;
}
no jumps calculating in the !x + x * 2 - (x >= 2) so no pipeline flushes.

Evaluate 2 consecutive integers in an array into a character

What I want the program to do is to evaluate the 2 consecutive integers after another in a set of array, then convert these integers to a corresponding character.
For example, if I have array[10] = {4 2 3 2 5 3 5 3 6 3}, the first 2 ints 4 2 will be converted into "H", 3 2 = E, 5 3 = L and so on until it prints the word HELLO. The program should accept a list of integers.
This is what I've done so far..
#include <stdio.h>
#include <stdlib.h>
int main() {
int i=0, j=0, k=0;
int array[1000];
char space;
printf("Input integers to convert into a string: ");
do {
scanf("%d%c", &array[i], &space);
i++;
} while(space != '\n');
for(/*what should I include here?*/)
if (array[0] == 2 && array[1] == 1)
printf("A");
else if (array[0] == 2 && array[1] == 2)
printf("B");
/* and so may else ifs*/
}
Something like this should work. Instead of going through the for loop one int at a time, it would probably be best to do two at a time.
for(int i = 0; i < 1000; i += 2){
if (array[i] == 2 && array[i + 1] == 1)
printf("A");
else if (array[i] == 2 && array[i + 1] == 2)
printf("B");
/* and so may else ifs*/
}
I would create a function that converts the integers to the characters.
char int_to_char(int val)
{
if(val == 21)
return 'A';
if(val == 22)
return 'B';
if(val == 42)
return 'H';
if(val == 32)
return 'E';
if(val == 53)
return 'L';
if(val == 63)
return 'O';
// I don't see you pattern, so I don't know which value
// is which character
return '?';
}
I don't see your pattern here.
Then your loop would look like:
// i is the number of entered values
// making sure that the end condition is even
for(int j = 0; j < i&1 ? i - 1 : i; j += 2)
{
printf("%c", int_to_char(array[j] * 10 + array[j+1]));
}
This would print HELLO with the input 4 2 3 2 5 3 5 3 6 3.

Resources