Switch/String in c - c

I am trying to get this function to return a string.
char * vergleich(int random) {
char *erg;
switch(random) {
case 1: erg = "Siccor" ; break;
case 2: erg = "Paper" ; break;
case 3: erg = "Rock" ; break;
case 4: erg = "Lizard" ; break;
case 5: erg = "Spock" ; break;
default: break;
return erg;
}
}
int main() {
srand(time(NULL));
int p1 = rand() % 4;
int p2 = rand() % 4;
printf("player1 shows %s\n", vergleich(p1));
printf("\n\tif Player 2 plays %s or %s Player1 wins\n", vergleich(p1+1), vergleich(p1+3));
if(p2 == p1 + 1 || p2 == p1 +3) {
printf("player1 wins");
}else {printf("player2 wins");}
return 0;
}
}
I think the initialisation of the function is wrong, but I dont really know how to deal with strings, please help.
If I run the program it just crashes if case > 2. and the strings are not displayed right.

The crash happens since the function vergleich() can be called with argument 0 (when p1 is 0) and 6 when p1 is 3. Zero and six are not handled in the switch, so pointer erg points to junk.
So, I suggest to enumerate your items starting from 0 to 4. To avoid overflow during additions you should also use modulo operation %, for example (p1 + 3) % 5, (p1 + 1) % 5.
To generate random from 0 to 4 you can use rand() % 5;.

Related

Program that inputs a number and then prints the set bits of that number with the bit integer displayed next to it

for example, if I enter 12, I want to get 81 41 as the set bits in 12 are 1100
This is what I have for now, I do not think I am implementing the for loop correctly
#include <stdio.h>
void bin(unsigned n)
{
char list[6];
int x = 0, y = 1;
/* step 1 */
if (n > 1)
bin(n / 2);
/* step 2 */
list[x] = n % 2;
x++;
/*for(int i = 0; i < x; i++) {
printf("%d\n",list[i]);
}*/
for(int i = 0; i < 5; i++) {
if(list[i] == 1 && i == 5) {
printf("32%i",y);
}
if(list[i] == 1 && i == 4) {
printf("16%i",y);
}
if(list[i] == 1 && i == 3) {
printf("8%i",y);
}
if(list[i] == 1 && i == 2) {
printf("4%i",y);
}
if(list[i] == 1 && i == 1) {
printf("2%i",y);
}
if(list[i] == 1 && i == 0) {
printf("1%i",y);
}
}
}
I checked that I was correctly storing the bytes in the array, and it outputted correctly, but when I try to look for them one at a time in a loop, it seems to get stuck on the 32 bit integer, so for 12, it would print 321 321
This program has Undefined Behaviour from accessing uninitialized values of list. I'm going to refactor this code so its easier to talk about, but know this refactored code is still incorrect.
x is always 0. y is always 1. x++ has no effect. This function can be rewritten as:
void bin(unsigned n)
{
char list[6];
if (n > 1)
bin(n / 2);
list[0] = n % 2;
for (int i = 0; i < 5; i++) {
if (list[i] == 1) {
switch (i) {
case 5: printf("321"); break;
case 4: printf("161"); break;
case 3: printf("81"); break;
case 2: printf("41"); break;
case 1: printf("21"); break;
case 0: printf("11"); break;
}
}
}
}
There are some problems here.
Firstly, list is not shared between calls to bin, nor are any other variables.
In every call to bin, only list[0] is assigned a value - all others indices contain uninitialized values. You are (un)lucky in that these values are seemingly never 1.
With your example of 12 as the starting value:
When you initially call bin(12), what happens is:
bin(12) calls bin(6), bin(6) calls bin(3), bin(3) calls bin(1).
Starting from the end and working backwards, in bin(1):
n = 1, so list[0] = n % 2; assigns 1. The loop checks each element of list for the value 1, finds it when the index (i) equals 0, and prints 11.
This is repeated in bin(3), as 3 % 2 is also 1, and again this result is assigned to the first element of list. Again, we print 11.
In bin(6), 6 % 2 is 0. The loop finds no elements of list that equal 1. Nothing is printed.
And again, this is repeated in bin(12), as 12 % 2 is 0. Nothing is printed.
To reiterate, it is pure luck that this program appears to work. Accessing list[1] through list[4] (i < 5 ensures you never access the last element) in each function call is Undefined Behaviour. It is generally not worth reasoning about a program once UB has been invoked.
When dealing with bits, it would be a good time to use some bitwise operators.
Here is a program that more-or-less does what you have described.
It assumes 32-bit unsigned (consider using fixed width types from <stdint.h> to be more precise).
This program works by repeatedly shifting the bits of our initial value to the right b number of places and testing if the rightmost bit is set.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
unsigned num = argc > 1 ? atoi(argv[1]) : 42;
unsigned b = 32;
while (b--)
if ((num >> b) & 1)
printf("%u1 ", 1 << b);
putchar('\n');
}
$ ./a.out 12
81 41

C language switch-case: avoiding a case after used once

I'm trying a challenge where I need to get a random number, and print the sum of the digits inside the number without duplicates:
for example, 123 will print 6 ( 1 + 2 + 3 ), and 32111 will do the same ( because we don't add duplicates to our sum, the sum of this number is similar to the sum of 123. )
In my solution I thought about using switch case for each number, and use a flag that its value is one, than in each case I add 1 to the flag, and when the flag is 2 I add the number to the sum, but I don't know how to avoid a case after it happend, which if I see it correctly will avoid me using multiple flags for each number (because if we could avoid a case after it happend, i just could set the flag back to one after the switch and do all the process again )
can you help me out? thanks a lot!
#include <stdio.h>
#define TEN 10
#define NINE 9
#define EIGHT 8
#define SEVEN 7
#define SIX 6
#define FIVE 5
#define FOUR 4
#define THREE 3
#define TWO 2
#define ONE 1
int main(void)
{
int answer = 0, i = 0, remain = 0, sum = 0, flag = 1;
printf("Enter a number: ");
scanf("%d", &answer);
while(answer >= ONE)
{
remain = answer % TEN;
answer /= TEN;
printf("%d\n", remain);
switch (remain)
{
case ONE:
{
flag++;
if (flag == TWO)
{
sum = sum + ONE;
}
break;
}
case TWO:
{
flag++;
if (flag == TWO)
{
sum = sum + TWO;
}
break;
}
case THREE:
{
flag++;
if (flag == TWO)
{
sum = sum + THREE;
}
break;
}
case FOUR:
{
flag++;
if (flag == TWO)
{
sum = sum + FOUR;
}
break;
}
case FIVE:
{
flag++;
if (flag == TWO)
{
sum = sum + FIVE;
}
break;
}
case SIX:
{
flag++;
if (flag == TWO)
{
sum = sum + SIX;
}
break;
}
case SEVEN:
{
flag++;
if (flag == TWO)
{
sum = sum + SEVEN;
}
break;
}
case EIGHT:
{
flag++;
if (flag == TWO)
{
sum = sum + EIGHT;
}
break;
}
case NINE:
{
flag++;
if (flag == TWO)
{
sum = sum + NINE;
}
break;
}
default:
{
}
}
}
printf("The sum of the number is: %d", sum);
return 0;
}
Try using a bitmask representing each case. The main idea is to keep track for each number (from 0 to 9) using only one integer. Some bit of this single integer can be used as to find whether this number was seen before or not. If the bit is 0 then the corresponding number is seen for the first time (and we now set the bit to 1), and if we see that the bit is already 1, then we don't add it into our final sum.
int mask = 0;
switch (remain) {
case 1: // 001
if ((mask & 1) == 0) { // 1 = 1 << 0
sum += 1;
mask |= 1;
}
break;
...
case 3: // 100
if ((mask & 4) == 0) { // 4 = 1 << 2
sum += 3;
mask |= 4;
}
break;
...
case n:
if ((mask & k) == 0) { // k = 1 << (n-1)
sum += n;
mask |= k;
}
break;
...
Now you can see a pattern in the last case I used, we can simplify this switch-case into a single if statement.
int mask = 0;
int sum = 0;
while (answer) {
remain = answer % 10;
answer /= 10;
int offset = remain;
int flag = 1 << offset;
if ((mask & flag) == 0) {
sum += remain;
mask |= flag;
}
}
// sum contains the required answer
Each bit represents one of the cases, since you have only 10 cases this is the most efficient way to track the flags as you have more than 10 bits for an integer and it will be wastage to have a separate boolean flag for 0 to 9.
A case-term is a compile time constant, so you cannot "disable" it at runtime at the c language level. You would have to introduce a separate flag for each digit then.
I'd say - and have a look at you code - the switch-case approach is not the best as you duplicate a lot of similar code. A much easier way would be to have an array of 10 ints, each standing for a particular digit, and once a digit is encountered, set the respective array element to 1. At the end sum up in a loop.
If you have troubles getting this approach running, don't hesitate to ask again...

Program that moves the knight on the chessboard

This program changes the position of a chessboard from 0 to 1 when the knight moves from one position to another. If I try the case 0 the program works. Then after the case 0 if I try the case 1 the position changed to 1 is the one that is placed up-left from the case 0 one. Instead it should be the one placed up-up-right from the case 0 one. Why is the output like this?
#include <stdio.h>
int main(){
int board[8][8]={0};
int currentRow=4, currentColumn=4;
int cont=0, moveNumber=0, i, j;
while(moveNumber>=0 && moveNumber<=7){
printf("Enter a move: ");
scanf("%d", &moveNumber);
cont++;
switch(moveNumber){
case 0:
board[currentRow-1][currentColumn+2]=1;
break;
case 1:
board[currentRow-2][currentColumn+1]=1;
break;
case 2:
board[currentRow-2][currentColumn-1]=1;
break;
case 3:
board[currentRow-1][currentColumn-2]=1;
break;
case 4:
board[currentRow+1][currentColumn-2]=1;
break;
case 5:
board[currentRow+2][currentColumn-1]=1;
break;
case 6:
board[currentRow+2][currentColumn+1]=1;
break;
case 7:
board[currentRow+1][currentColumn+2]=1;
break;
}
for(i=0; i<8; i++){
for(j=0; j<8; j++){
printf("%d ", board[i][j]);
}
printf("\n");
}
printf("Total moves: %d\n",cont);
}
return 0;
}
The main issue is that you never update currentRow or currentColumn, so all moves happen from their initial values.
Some other notes: You should avoid "magic numbers" - 8 in this case. If you decide to change the size of the array, you have to search through all the code and find the eights and replace them. Use a define or const int.
You should always check the return value from scanf. What if the user types a, for example?
Array bounds checking is needed. What happens when a move takes the knight off the board - and past the bounds of the array?
#include <stdio.h>
// Avoid magic numbers
#define ROWS 8
#define COLS 8
int main(){
int board[ROWS][COLS] = {0};
int currentRow = 4, currentColumn = 4;
int cont = 0, moveNumber = 0, i, j;
// Loop forever
while (1) {
printf("Enter a move: ");
// Make sure user enters a number
while (1 != scanf("%d", &moveNumber)) {
// clear stdin
int c;
while((c = getchar()) != '\n' && c != EOF);
// See https://stackoverflow.com/a/6277391/669576
// for why fgets/sscanf is a better option than scanf
// Prompt user for new input
printf("Enter a valid integer:");
}
// Moved this here
if (moveNumber < 0 || moveNumber > 7) break;
cont++;
// Going to use some temp vars to calculate indices
int tempRow, tempCol;
// Calc new indices
switch (moveNumber) {
case 0:
tempRow = currentRow - 1;
tempCol = currentColumn + 2;
break;
case 1:
tempRow = currentRow - 2;
tempCol = currentColumn + 1;
break;
case 2:
tempRow = currentRow - 2;
tempCol = currentColumn - 1;
break;
case 3:
tempRow = currentRow - 1;
tempCol = currentColumn - 2;
break;
case 4:
tempRow = currentRow + 1;
tempCol = currentColumn - 2;
break;
case 5:
tempRow = currentRow + 2;
tempCol = currentColumn - 1;
break;
case 6:
tempRow = currentRow + 2;
tempCol = currentColumn + 1;
break;
case 7:
tempRow = currentRow + 1;
tempCol = currentColumn + 2;
break;
}
// Make sure we have valid indices
if (tempRow < 0 || tempCol < 0 || tempRow >= ROWS || tempCol >= COLS) {
printf("Illegal move\n");
}
else {
// Update the board
currentRow = tempRow;
currentColumn = tempCol;
board[currentRow][currentColumn] = 1;
// And print
for(i = 0; i < ROWS; i++){
for(j = 0; j < COLS; j++){
printf("%d ", board[i][j]);
}
printf("\n");
}
printf("Total moves: %d\n", cont);
}
}
return 0;
}
As #Jonhnny Mopp pointed out, you never update currentRow or currentColumn.
So after case 0 you set board[3][6] and after case 1 you set board[2][5].
So the return of case 1 is up-left of case 0.
I recommend you write a function TryToMoveKnight(int* x, int* y, int moveNumber) that attempts to move a knight in the desired direction.
You already have eight lines of very similar code, and the more work you need to do to move the piece, the worse it's going to get.
Things the function needs to do:
determine the target coordinates from the moveNumber and current
position
verify that the target coordinates are on the board
possibly check for a piece at that position
assign the new coordinates to your variables x and y whose addresses you passed in
This last step was missing from your original code, but checking that the target position is on the board is also going to be essential.
So where you currently have switch(moveNumber)... you would instead call TryToMoveKnight(&currentRow,&currentColumn,moveNumber);

How to find closest number in C?

So, I was working out some exercises from a recommended beginner's book: C Programming: A Modern Approach (2nd Edition) While working out one of the questions I found myself unable to proceed, as I couldn't return the number closest to the user's input.
Note: The question was asked before loops, functions and arrays were covered, thus I am assuming that these should not be required.
I managed to extract and simplify the problem to the following. Lets say I have the following numbers, and I want to return the number closest to the user's input:
10 20 30 40 50 60 70 80
printf("Enter a number to find closest value: ");
scanf("%d", &num);
For example:
User's input: 28
Closest number: 30
Next, I decided to find the difference between num and each of the numbers by subtracting from each.
difference1 = num - 10;
difference2 = num - 20;
and so on. (I am not using loops as these have not yet been covered in the book)
I taking into consideration, negative differences (25 - 40 = -15). If the difference is less than 0, I am multiplying the difference by -1 to get all the differences to a positive integer. By doing so I will be able to compare the differences successfully:
if (difference1 < 0) {
difference1 = difference1 * -1;
}
Next I am checking for the minimum difference in order to identify which was the closest number by doing:
if (difference1 < difference2) {
min1 = difference1;
}
else {
min1 = difference2;
}
if (difference3 < difference4) {
min2 = difference3;
}
else {
min2 = difference4;
}
if (difference5 < difference6) {
min3 = difference5;
}
else {
min3 = difference6;
}
if (difference7 < difference8) {
min4 = difference7;
}
else {
min4 = difference8;
}
if (min1 < min2) {
min5 = min1;
}
else {
min5 = min2;
}
if (min3 < min4) {
min6 = min3;
}
else {
min6 = min4;
}
if (min5 < min6) {
min = min5;
}
else {
min = min6;
}
I know this is a very long method, however I was unable to shorten the code without the use of a for-loop.
printf("Difference between the two numbers is %d\n", min);
Since min contains the difference between the user's input and the closest number I am unable to find a way to print the number closest to the user's input.
How can I trace the minimum difference to the original number which this was subtracted from ? Any suggestions would be appreciated, and please excuse the basic nature of this question.
I can help you to make the code shorter.
Here are my approach
int num = 71;
int diff,ans;
int div10 = (num / 10);
int lower = div10 * 10;
int upper = (div10 + 1) * 10;
if(lower<10) lower=10;
if(lower>80) lower=80;
if(upper<10) upper=10;
if(upper>80) upper=80;
int diff1 = lower - num;
int diff2 = upper - num;
if(diff1 < 0) diff1 *= -1;
if(diff2 < 0) diff2 *= -1;
if(diff1 < diff2) {
ans = lower;
diff = diff1;
}
else {
ans = upper;
diff = diff2;
}
printf("ans=%d, diff=%d\n",ans,diff);
Well what I would do:
int main(){
int closest;
int temp;
int a0 = 10, a1 = 20, a2 = 30; //and more..
int user_input = 28;
closest = abs(user_input - a0);
temp = abs(user_input - a1);
if (temp <= closest)
closest = temp;
//and so on
return 0;
}
Where abs is absolute value. Numbers should be in some data structure, because in the mean time you should ask if you still have something to check.
If you're dealing with 10s this should be quite simple:
num += 5;
closest_10 = num/10;
closest_10 *= 10;
Then you can have simple look up if you have an array of numbers. You can expand this to other multiples using a similar algorithm (say for 8s just replace 5 with 4 and 10 with).
As all numbers are fixed, the best approach (at least the most efficient once compiled) is to use the following snippet of code:
int closest(int number)
{
switch(number) {
case 0: case 1: case 2: case 3: case 4:
return 0;
case 5: case 6: case 7: case 8: case 9:
case 10: case 11: case 12: case 13: case 14:
return 10;
...
case 95: case 96: case 97: case 98: case 99: case 100:
return 100;
} /* switch */
} /* closest */
Even more efficient if you can inline the code instead of writing a function.
You need to better define: Lets say I have the following numbers.
How many numbers is the big question. Your example has them all as evenly divisible by 10. Your numbers are 10, 20, 30, and so on, and you mention a total of 8 numbers. Is it only 8 numbers maximum? Can they be any number? Will they all be integers? If its all integers and all divisible by 10, then you can use the modulo or modulus operator instead of subtraction.
The mod operator % only works on integers.
int a, b, c;
a = 3;
b = 25
c = a % 10; /* c will equal 3, 0 / 10 = 0 with remainder 3 */
c = b % 10; /* c will equal 5, 25 / 10 = 2 but remainder is 5 */
/* check if a number is even, just mod by 2 if zero then even */
if ( ( b % 2 ) == 0 )
printf(" value in b is even number\n");
else
printf(" value in b is odd number\n");

tricky interview question in C

In the following interview question :
Given a number n, give me the numbers
(among 3..5 and an even number of
numbers) whose adding would return the
original number. The resulting numbers
should be as balanced as possible,
meaning that instead of returning 3
and 5, for instance, return 4 and
4. Ex:
7 = 3 + 4
16 = 4 + 4 + 4 + 4 rather than 3 + 5 + 4 + 4
24 = 12 + 12 or 6 + 6 + 6 + 6
I thought of the following method:
splitnumber(int n)
{
//check if the number is even
if(n%2==0)
{
print(n/2,n/2);
//check if x=2^m multiple exists or
// not..like 4,8,16 etc
print (n/x...n/x);
}
else //else if the no is odd... this part is incomplete
{
if(n-3>0)
{
print (3);
}
n-=3;
if(n>0)
{
if (n>5)
{
print(3)
n-=3;
}
}
}
}
but still I am not able to complete all the cases... How should I check when the answer has unbalanced solution??
if (n < 4) print n;
else
switch (n % 4)
case 0: *print n/4 4's*
case 1: *print n/4 - 1 4's* print 5
case 2: *print n/4 - 1 4's* print 3 print 3
case 3: *print n/4 4's* print 3
Slightly inefficient implementation in C#
if (n < 4) Console.WriteLine(n);
else
switch (n % 4)
{
case 0:
Console.WriteLine(String.Join(" ", new string('4', n / 4).ToArray()));
break;
case 1:
Console.WriteLine(
(String.Join(" ", new string('4', n/4).ToArray().Skip(1)) +
" 5").TrimStart());
break;
case 2:
Console.WriteLine(
(String.Join(" ", new string('4', n/4).ToArray().Skip(1)) +
" 3 3").TrimStart());
break;
case 3:
Console.WriteLine(String.Join(" ", new string('4', n/4).ToArray() +
" 3"));
break;
}
Here is my solution where the result will be perfectly balanced and with detection of impossible cases:
vector<int> recursive_splitnumber(int n) {
if (n <= 5) {
return vector<int>(1,n);
}
int unbalancer = 0;
vector<int> result1, result2;
do {
int val1, val2;
if (n%2 == 0) {
val1 = n%2 + unbalancer;
val2 = n%2 - unbalancer;
}
else {
val1 = (n-1)%2 + 1 + unbalancer;
val2 = (n-1)%2 - unbalancer;
}
result1 = recursive_splitnumber(val1);
result2 = recursive_splitnumber(val2);
// Concatenate the result of the even and odd splits
result1.insert(result1.end(),result2.begin(),result2.end());
++unbalancer;
} while (result1.size()%2 != 0 && unbalancer <= 1);
return result1;
}
bool splitnumber(int n) {
vector<int> split = recursive_splitnumber(n);
if (split.size()%2 == 0) {
copy(split.begin(), split.end(), ostream_iterator<int>(cout, " "));
return true;
} else
return false;
}
That solution will also take into account cases like the number 22 where the balanced division gives 11+11 (11 being a number that cannot be represented using the given rules), the subdivision will be done as 10+12, then 5+5+6+6 and finally 5+5+3+3+3+3.

Resources