Repetition using switch statement inside a for loop - c

I am trying to use a loop to print out a repetitive song, "this old man"
The first verse is:
This old man, he played one
He played knick-knack on my thumb
This old man came rolling home
This song repeats to ten, varying the two terms in italicize
one -> two++ and thumb -> another item such as shoe, knee, etc.
Here is my code so far:
#include <cs50.h>
#include <stdio.h>
#include <string.h>
string change1 (int i);
int main (void)
{
for (int i = 1; ; 1 < 11; i++)
{
printf ("This old man, he played ");
change1(i);
printf("He played knick-knack on my %s\n\n", s1);
}
return 0;
}
string change1(int i)
{
string s1;
switch(i)
{
case 1:
{
printf("one\n");
s1 = "thumb";
}
break;
case 2:
{
printf("two\n");
s1 = "shoe";
}
break;
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
case 10:
case 11:
printf("ill add these cases later");
}
}
This gives me an error message of: "control reaches end of non-void function"
I also got an undeclared variable s1 error but I declared it in the function.

You could simplify your program to an actual C program, rather than C++
int main (void)
{
int i;
char* items[] = {"thumb", "shoe", "", "", "", "", "", "", "", ""};
char* numbers[] = {"one", "two", "three","four","five","six","seven","eight","nine","ten"};
for (i = 0; i < 10; i++)
{
printf ("This old man, he played %s\n", numbers[i]);
printf("He played knick-knack on my %s\n\n", items[i]);
}
return 0
}

In C++ variables have scope. A variable is generally visible inside the curly braces where it is declared; outside these brackets the variable does not exist.
That is why you cannot use s1 from change1 inside the loop: you need to return a value (best choice in your situation), or use a variable that is in scope in both change1 and main.
printf ("This old man, he played ");
printf("He played knick-knack on my %s\n\n", change1(i));
...
string change1 (int i) {
string s1;
switch (i) {
...
}
return s1;
}
Note that you do not need a switch statement to implement change1: when the code is so uniform, you may be better off with an array:
const char *strings[] = {"thumb", "shoe", ...};

change1 needs to return the string it decided on. And main has to assign the return value to a variable, because as originally written s1 is local to the change1 function.
#include <cs50.h>
#include <stdio.h>
#include <string.h>
string change1 (int i);
int main (void)
{
for (int i = 1; ; 1 < 11; i++)
{
printf ("This old man, he played ");
string s1 = change1(i);
printf("He played knick-knack on my %s\n\n", s1);
}
return 0;
}
string change1 (int i)
{
string s1;
switch (i)
{
case 1:
{
printf("one\n");
s1 = "thumb";
}
break;
case 2:
{
printf("two\n");
s1 = "shoe";
}
break;
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
case 10:
case 11:
printf("ill add these cases later");
}
return s1;
}

use return statement at the end of switch class
return s1;

Related

Strange behaviour in a Dice Throwing simulation program

I have written this piece of code which is supposed to simulate throwing dice many many times and counting that how many times each face is up. I have attached the output down there and as you can see it looks kind of strange. For example face 5 comes up exactly 10 times, faces 2, 3, 4 are about the same and face 6 comes zero in two rounds. The only face which acts about normal is 1.
Can anyone explain this to me? Is this normal? Am I doing something wrong or is it something related to my system?
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void) {
unsigned long int freq1, freq2, freq3, freq4, freq5, freq6;
unsigned long int L00p = 1;
unsigned short int DF;
while (L00p <= 6e7){
srand (time(NULL));
DF = 1 + (rand ()%6);
switch (DF)
{
case 1:
++freq1;
break;
case 2:
++freq2;
break;
case 3:
++freq3;
break;
case 4:
++freq4;
break;
case 5:
++freq5;
break;
case 6:
++freq6;
break;
default:
break;}
++L00p;
}
printf ("%s%25s\n", "Dice's Face", "Face Frequency");
printf ("1%25lu\n", freq1);
printf ("2%25lu\n", freq2);
printf ("3%25lu\n", freq3);
printf ("4%25lu\n", freq4);
printf ("5%25lu\n", freq5);
printf ("6%25lu\n", freq6);
return 0;
}
and here is the program's output after four times running it:
You don't initialize the frequency counters, so they'll likely contain garbage from the stack. (So yes, you were getting randomness, but not the randomness you want.)
You don't want to call srand() in the loop, but only once before it. Calling srand() with the same number (and time(NULL) will quite inevitably return the same second in a tight loop) will reset the rand() generator to return the same sequence of numbers, and since you only ever call rand() once before calling srand() again, you'll get a whole bunch of the same number.
The following version works fine, but you'd have a better time with an array.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void) {
unsigned long int freq1 = 0, freq2 = 0, freq3 = 0, freq4 = 0, freq5 = 0,
freq6 = 0;
srand(time(NULL));
for (int loop = 0; loop < 1000; loop++) {
int DF = 1 + (rand() % 6);
switch (DF) {
case 1:
++freq1;
break;
case 2:
++freq2;
break;
case 3:
++freq3;
break;
case 4:
++freq4;
break;
case 5:
++freq5;
break;
case 6:
++freq6;
break;
default:
break;
}
}
printf("%s%25s\n", "Dice's Face", "Face Frequency");
printf("1%25lu\n", freq1);
printf("2%25lu\n", freq2);
printf("3%25lu\n", freq3);
printf("4%25lu\n", freq4);
printf("5%25lu\n", freq5);
printf("6%25lu\n", freq6);
return 0;
}
Example output:
Dice's Face Face Frequency
1 177
2 160
3 166
4 169
5 155
6 173
For reference, a version using an array of 6 ints:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void) {
unsigned long int freqs[6] = {0};
srand(time(NULL));
for (int loop = 0; loop < 1000; loop++) {
freqs[rand() % 6] ++;
}
printf("%s%25s\n", "Dice's Face", "Face Frequency");
for(int face = 0; face < 6; face++) {
printf("%d%25lu\n", face + 1, freqs[face]);
}
return 0;
}
Here is an annotated adaptation of your code for educational purposes. You've learned about "loops", so here is an application for a do/while() loop.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
// Global variables are frowned upon because as the code grows more complex
// it is difficult or impossible to see where a value may be changed (inappropriately)
// For a tiny program like this that is unlikely to grow
// this proves the global variables are, by default, initialised to zero.
unsigned long int freq1, freq2, freq3, freq4, freq5, freq6;
int main() {
unsigned long int L00p = 0; // "local" var initialised. Good!
srand( time( NULL ) ); // called once at start of program.
do {
switch( ( rand() % 6 ) ) { // braces consistent with your main()
case 1: ++freq1; break; // get used to base-0 counting
case 2: ++freq2; break;
case 3: ++freq3; break;
case 4: ++freq4; break;
case 5: ++freq5; break;
case 0: ++freq6; break; // Ha-ha!! modulo!!!
default: printf( "A miracle has happened!!\n" );
break;
} // DO NOT hide that closing brace as you did. Prominent!
} while( ++L00p < 6e3 ); // increment counter after each loop done
// Swapped your output columns
// Using one format specifier for header and one for counts
// Notice how easy to modify only one instance?
char *tFmt = "%9s : %s Loops = %d\n";
char *oFmt = "%9lu : %d\n";
printf( tFmt, "Frequency", "Face", L00p );
// and... why not???
for( L00p = 0; L00p < 6; L00p++ ) {
int n; // not init'd because used immediately
switch( L00p ) {
case 1: n = freq1; break;
case 2: n = freq2; break;
case 3: n = freq3; break;
case 4: n = freq4; break;
case 5: n = freq5; break;
case 0: n = freq6; break;
}
printf( oFmt, n, L00p + 1 );
}
return 0;
}
Output
Frequency : Face Loops = 6000
958 : 1
1038 : 2
1018 : 3
1031 : 4
956 : 5
999 : 6
Again, for a simple, small piece of code like this, being able to see the entire switch block and compare values at a glance, concatenating statements can AID in writing bug-free code.

How to copy a multidimensional array to another without knowing the exact amount of rows in C?

So my program is basically built to get game scores, and track w/l/t, etc. What I am needed to do is to arrange the scores in ascending order based off of the opponent's scores.
So to do that I decided to bubble sort, but when I do that and print it, the first pair [0][0], and [0][1] come out with big negative numbers, which is what I'm guessing is their reference then after that the rest print correctly. I've googled around and couldn't find anything about this so I was wanting to copy the original array into a copy and try sorting with that one.
#include <stdio.h>
#include <stdlib.h>
#define _CRT_SECURE_NO_WARNINGS //doesn't work
#define FLUSH myFlush()
#define GAMES 50
void titleDisplay(int);
void menuOptions();
void gameResults(int *counter, int team[][2], int); // records games from user input
void showRecord(int counter, int team[][2]); // shows current record
void displayResultFromGamesWon(int counter, int team[][2]);
void displayAllResults(int counter, int team[][2]); // shows all results ordered by opp score.
char getChoice();
void myFlush();
int main() {
//const int GAMES = 50; - program doesn't read this as a const when used to create arr.
const int MAX_GAMES = 50;
int userTeam[GAMES][2]; // array column 0 is user score, column 1 is opp score
int gameCounter = 0;
char userChoice;
do {
system("clear");
titleDisplay(1);
menuOptions();
userChoice = getChoice();
switch (userChoice) {
case 'a': case 'A':
gameResults(&gameCounter, userTeam, MAX_GAMES);
break;
case 'b': case 'B':
showRecord(gameCounter, userTeam);
break;
case 'c': case 'C':
displayResultFromGamesWon(gameCounter, userTeam);
break;
case 'd': case 'D':
displayAllResults(gameCounter, userTeam);
break;
case 'e': case 'E':
printf("Bye bye.\n");
system("pause");
break;
default:
printf("Invalid selection, choose again!\n");
system("pause");
break;
}//end switch
} while (userChoice != 'e' && userChoice != 'E');
return 0;
}
Here's where I sort and print:
//function definition
void displayAllResults(int counter, int team[][2]) {
int i;
int temp, temp2 = 0;
system("clear");
if (counter == 0) {
printf("\n\n\tYou haven't played any games yet.\n\n\n");
}
else {
titleDisplay(4);
printf("\t (Arranged by Opponent score low to high)\n\n");
printf("\tUser Score\t\t\tOpponent Score\n");
printf("\t----------\t\t\t--------------\n");
//begin bubble sorting
for (int x = 0; x < counter; x++) {
for (int y = x + 1; y < counter; y++) {
if (team[x][0] > team[y][0]) {
temp = team[x][1];
temp2 = team[x][0];
team[x][0] = team[y][0];
team[x][1] = team[y][1];
team[y][0] = temp2;
team[y][1] = temp;
}//end if
}
}//end bubble sort
for (i = 0; i < counter; i++) {
printf("\t%-8i\t\t\t%-11i\n", team[i][0], team[i][1]);
}//end for
}//end else
system("pause");
}//end function
I've tried declaring a variable of 'int sortedArray = team[counter][2];' in the displayAllResults function but that gave memory problems, and failed when I tried to access that variable. I tried memcpy, but either I didn't implement correctly or that doesn't work either.
Is it even possible to copy a 2D array like this to another one?
There are two ways to copy an array to another:
1-Using sizeof(array) and dividing it to size of one element of the array, in this case it is a pointer.
2- The best way is, to have a variable which will show you the length of the array.
I think you made an implementational mistake. I couldn't understand what you are doing. What is 5 for?
In any case, do have a variable for the length of the array.

Inside Switch Case - Variable Definition Related

In this code, why I am getting i = "some garbage value" as output? I see that i is being declared but value = 10, not assigned. Why ?
main()
{
int a =1;
switch (a)
{
int b = 10;
case 1: printf ("b = %d \n", b);
break;
}
b is not being initialized. The assignment is outside of any case in the switch, so it picks whatever was in the stack at that point.
If you want a variable inside a case statement, the right way to do it is:
switch(a)
{
case 1:
{
int b=10; //start a new block scope
printf("b=%d",b);
}
break;
}

Edit arrays within function and return array to main in C

Im writing a program to give the user options whether they want to:
Add random numbers to an array
Print array
Search for an element in an array
Left shift array
These have to be in separate functions and it needs to b recursive and until the user wants to finish it keeps running my code is:
int main()
{
int array[M][N];
int ans;
puts("Please enter what you would like to do:\n
1: Create an array with random values\n
2: Print Array\n
3: Search for a number in an array\n
4: Shift each value to the left");
scanf("%d",&ans);
switch(ans) {
case 1:
PopulateRandom2D(array);
break;
case 2:
PrintArray(array);
break;
case 3:
LinearSearch2D(array);
break;
case 4:
LeftShift(array);
break;
default:
puts("Goodybye");
return 0;
}
main();
return 0;
}
void PopulateRandom2D(int array[][N])
{
int r,c;
srand(time(NULL));
for(r = 0; r < M; r++) {
for(c = 0; c < N; c++) {
array[r][c] = 1 + (rand() % (M * N));
}
}
}
After i call the function i need the user to enter another command and call a different function from the user input. Ive been experimenting by first hitting 1 so it fills the array with numbers and then hitting 2 so it will hopefully print out that array but all i get are huge numbers in the array. I don't think the function is editing the array in main correctly so main doesn't get the array with random values but how do i fix this?
The code below works:
#include "stdafx.h"
#include <stdlib.h>
#include <time.h>
const int M = 10;
const int N = 20;
void PrintArray(int array[][N]) {}
void LinearSearch2D(int array[][N]) {}
void LeftShift(int array[][N]) {}
void PopulateRandom2D(int array[][N])
{
int r, c;
srand(time(NULL));
for (r = 0; r < M; r++) {
for (c = 0; c < N; c++) {
array[r][c] = 1 + (rand() % (M * N));
}
}
}
int main()
{
int array[M][N];
int ans;
while (true)
{
puts("Please enter what you would like to do:"
"\n1: Create an array with random values"
"\n2: Print Array"
"\n3: Search for a number in an array"
"\n4: Shift each value to the left"
"\n5: Quit");
scanf("%d", &ans);
switch (ans) {
case 1:
PopulateRandom2D(array);
break;
case 2:
PrintArray(array);
break;
case 3:
LinearSearch2D(array);
break;
case 4:
LeftShift(array);
break;
default:
puts("Goodybye");
return 0;
}
}
return 0;
}
I leave it to you to fill in the other functions.
You're currently recursively calling main(). In each iteration of calling main(), you'll create a new array on the stack.
This isn't what you want.
Instead, wrap your code in a while(true) { ... } loop. It would look something like this:
#include <stdbool.h>
int main()
{
int array[M][N];
int ans;
while (true) {
puts("Please enter what you would like to do:\n
1: Create an array with random values\n
2: Print Array\n
3: Search for a number in an array\n
4: Shift each value to the left");
scanf("%d",&ans);
switch(ans) {
case 1:
PopulateRandom2D(array);
break;
case 2:
PrintArray(array);
break;
case 3:
LinearSearch2D(array);
break;
case 4:
LeftShift(array);
break;
default:
puts("Goodybye");
return 0;
}
}
return 0;
}

Switch: Declared Variable outside switch and use it in it

The following isn't the it's just the part causing problem:
int s,p;
scanf("%d",s);
switch(s)
{
case 1:
{
p=10;
break;
}
case 2:
{
p=15;
break;
}
}
printf("%d",p);
The problem is that p prints a random and very large number, What is causing it?
So i used some of your advice and know i have the following code:
int s,p=0;
scanf("%d",&s);
switch(s)
{
case 1:
{
p=10;
break;
}
case 2:
{
p=15;
break;
}
default:
{
printf("Number invalid");
return 0;
}
}
printf("%d",p);
Now i it's always going to default even though i only enter 1 or 2
Ok now it worked Thank You All!
You have two problems: (i) p is uninitialised and (ii) you're passing s to scanf where the address of s is required.
Change:
int s,p;
scanf("%d",s);
to:
int s, p = 0;
scanf("%d", &s);
"int p" declaration assigns p to an arbitrary value: whatever happened to be in memory. Now, if s doesn't equal 1 or 2, that value never changes, and that's what you see. What you can do is
add default: clause to your switch() and assign p to something meaningful there
declare p as "int p = 0;"
What number are you scanning in? You probably you don't have a switch case for that number, which means that p is uninitialized (and hence random). For example if you enter 3, there is no case statement for 3 and p will contain a random value. I would suggest that you detect invalid input with an default case where you assign a value of 0 to p.
default:
p = 0;
Corrected code:
int s,p;
scanf("%d", &s);
switch(s)
{
case 1:
{
p=10;
break;
}
case 2:
{
p=15;
break;
}
default:
{
p=0;
break;
}
}
printf("%d",p);
Edit: Fixed scanf problem per Paul R
You can use default and then try to figure out what was scanned in

Resources