Counting vowels in text without arrays (C) - c

i have to write a program that counts all vowels in a text & gives out the percentage of every vowel for the whole text.
For whatever reason we are not allowed to use arrays, but instead should do it with getchar().
#include <stdio.h>
#include <ctype.h>
int main() {
int current;
int cntAll = 0;
int cntA = 0, cntE = 0, cntI = 0, cntO = 0, cntU = 0;
int pA = 0, pE = 0, pI = 0, pO = 0, pU = 0;
printf("Enter Text: ");
while ((current = getchar()) != EOF){
if (isspace(current)) continue; // check for whitespace, if whitespace continue
else {
switch (current) { // check for vowel & increase vowelcount
case 'a':
cntA += 1;
case 'A':
cntA += 1;
case 'e':
cntE += 1;
case 'E':
cntE += 1;
case 'i':
cntI += 1;
case 'I':
cntI += 1;
case 'o':
cntO += 1;
case 'O':
cntO += 1;
case 'u':
cntU += 1;
case 'U':
cntU += 1;
}
}
cntAll++;
}
pA = (cntA / cntAll) * 100;
pE = (cntE / cntAll) * 100;
pI = (cntI / cntAll) * 100;
pO = (cntO / cntAll) * 100;
pU = (cntU / cntAll) * 100;
printf("\nLetters: %d\nPercentage A: %d\nPercentage E: %d\nPercentage I: %d\nPercentage O: %d\nPercentage U: %d\n",cntAll,pA,pE,pI,pO,pU);
system("PAUSE");
return 0;
}
Increasing the cntAll value works without problems, but it doesn't count the individual vowels for whatever reason.
Would appreciate any help!
Edited:
#include <stdio.h>
#include <ctype.h>
int main() {
int current;
int cntAll = 0;
int cntA = 0, cntE = 0, cntI = 0, cntO = 0, cntU = 0;
double pA = 0, pE = 0, pI = 0, pO = 0, pU = 0;
printf("Enter Text: ");
while ((current = getchar()) != EOF){
if (isspace(current)) continue;
else {
switch (current) {
case 'a':case 'A':
cntA += 1;
break;
case 'e':case 'E':
cntE += 1;
break;
case 'i':case 'I':
cntI += 1;
break;
case 'o':case 'O':
cntO += 1;
break;
case 'u':case 'U':
cntU += 1;
break;
}
}
cntAll++;
}
pA = 100.0 * cntA / cntAll;
pE = 100.0 * cntE / cntAll;
pI = 100.0 * cntI / cntAll;
pO = 100.0 * cntO / cntAll;
pU = 100.0 * cntU / cntAll;
printf("\nLetters: %d\nPercentage A: %.2lf\nPercentage E: %.2lf\nPercentage I: %.2lf\nPercentage O: %.2lf\nPercentage U: %.2lf\n",cntAll,pA,pE,pI,pO,pU);
system("PAUSE");
return 0;
}
cheers

You need to insert break statements between the cases.
Otherwise the program will execute all the statements below the one first entered. Actually this is a good feature. It allows you to consider multiple labels at the same time. Putting this together you get:
switch (current){
case 'a': case 'A':
cntA += 1;
break; // Don't follow through to the other cases.
case 'b': case 'B': /*etc*/
After this, note that (cntA / cntAll) * 100; will evaluate the expression in parentheses in integer arithmetic, which will truncate it to 0 in most cases. The fix is to write it as
100 * cntA / cntAll;
This will still truncate to an integer. If that's not tolerable then consider using the floating point expression 100.0 * cntA / cntAll and change your printf formatters accordingly. Using floating point is arguably better anyway as it obviates the potential for overflow when evaluating 100 * cntA.

case labels falls through to the next one below it without a break.
So if you read an 'a' then all the cases in your switch will be executed.
You need something like
switch (current) { // check for vowel & increase vowelcount
case 'a':
cntA += 1;
break; // <-- Note break here
...

First thing i notice is that you are missing break on every switch case. This will lead to wrong behaviour.
Second thing:
pA = (cntA / cntAll) * 100;
will calculate cntS/cntAll first which is <0. This value will be interpreted as integer so you always have 0*100 which is 0. You can rewrite it as
pA = (cntA * 100 ) / cntAll;
In that case you don't have to cast to float to get the right result. Note that for large cntA you may overflow.

Related

Switch statement with two arguments

I have a question related to switch statement with 2 arguments. I do not understand which value to look for. I've read somewhere that comma(,) is equal to AND,but that is not helping me much since when debugging it goes to case 1,case 1,and then default,so I really don't get it.
Any help would be appreaciated,Thanks!
#define ADD(x, y) x+y
#define MUL(x, y) x*y
void main() {
int arr[6] = { 012, -2, 7 - 011, 0x1F, 3 }, res = 0;
int n = sizeof(arr) / sizeof(int), i, j;
for (i = -1, j = n; i <= n / 2;) {
switch (--j, ++i) {
case 0: res += MUL(arr[i], arr[j]);
case 1: res += ADD(arr[i], arr[j]); break;
case 4: res += MUL(ADD(arr[i], arr[j]), ADD(arr[i + 1], res));
default: res++; break;
}
}
printf("%d", res);
} ```
Operator comma is not equal to AND. Operator comma evaluates operands from left to right, and returns the last result. Thus,
switch (--j, ++i) {
i = 0;
it goes to the case 0, you don`t have break statement so you go to the case 1

Why is the second for-loop not executing?

The issue in the code below is that the second for-loop does not seem to execute.
I added the printf("1"); and printf("h"); statements to test if the loops were executing. The program printed the 1's but not the h's.
Some background info about the program is that I am supposed to allocate a 2D array and store sine waves at different frequencies in each row of the array.
Also the variable PI is defined as a macro with value acos(-1).
short int** Notes = (short int**) calloc(25,sizeof(short int*));
for(int x = 0; x < 25; x++){
Notes[x] = (short int*) calloc(44100 * (1/3),sizeof(short int));
}
for(int x = 0; x < 25; x++){
float freq;
switch(x){
case 0:
freq = 440.00;
break;
case 1:
freq = 466.16;
break;
case 2:
freq = 493.88;
break;
case 3:
freq = 523.25;
break;
case 4:
freq = 554.37;
break;
case 5:
freq = 587.33;
break;
case 6:
freq = 622.25;
break;
case 7:
freq = 659.25;
break;
case 8:
freq = 698.46;
break;
case 9:
freq = 739.99;
break;
case 10:
freq = 783.99;
break;
case 11:
freq = 830.61;
break;
case 12:
freq = 880.00;
break;
case 13:
freq = 932.33;
break;
case 14:
freq = 987.77;
break;
case 15:
freq = 1046.50;
break;
case 16:
freq = 1109.73;
break;
case 17:
freq = 1174.66;
break;
case 18:
freq = 1244.51;
break;
case 19:
freq = 1318.51;
break;
case 20:
freq = 1396.91;
break;
case 21:
freq = 1479.98;
break;
case 22:
freq = 1567.98;
break;
case 23:
freq = 1661.22;
break;
case 24:
freq = 0.00;
break;
}
printf("1");
for(int y = 0; y < 44100 * (1/3); y++)
{
Notes[x][y] = 32700 * sin(2 * PI * freq * (y/44100));
printf("h");
}
}
for(int y = 0; y < 44100 * (1/3); y++)
The substatement never executes because y < 44100 * (1/3) is always false. This is because integer division rounds toward zero, so (1/3) and therefore 44100 * (1/3) are zero.
Assuming you want the value which is one-third of 44100, just write 44100/3.
Dividing two integers will result in an integer:
for(int y = 0; y < 44100 * (1/3); y++)
is evaluated as:
for(int y = 0; y < 44100 * (0); y++)
So you never enter the loop
for(int y = 0; y < 44100 * (1/3); y++)
Here the testExpression y < 44100 * (1/3) always evaluate to false.
As 1/3 as both will result in zero as it is integer division and dividing two integers will result integer.
You can use
for(int y = 0; y < 44100 * (1.0/3); y++)

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);

Is my pointer bad initialized?

I am struggling with an error while debugging my application, I have been able to point out that the error seems to happen in the call to the function adc_gain_enum_to_real_gain(),however I don't see why it goes wrong, I suspect is related to passing/reading the pointer &adc_gain. Any hints?
Thanks in advance!
void saadc_handler_interrupt(nrf_drv_saadc_evt_t const * const p_event)
{
uint32_t err_code;
uint16_t voltage;
nrf_saadc_value_t adc_result;
uint16_t tmp_voltage;
float adc_gain;
if (p_event->type == NRF_DRV_SAADC_EVT_CALIBRATEDONE)
{
m_adc_cal_in_progress = false;
}
else if (p_event->type == NRF_DRV_SAADC_EVT_DONE)
{
adc_result = p_event->data.done.p_buffer[0];
err_code = nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer, 1);
APP_ERROR_CHECK(err_code);
err_code = adc_gain_enum_to_real_gain(ADC_GAIN, &adc_gain); //<===HERE!!
APP_ERROR_CHECK(err_code);
float tmp = adc_result / (( (1/6) / ADC_REFERENCE_VOLTAGE) * pow(2, ADC_RESOLUTION_BITS));
tmp_voltage = (uint16_t) ((tmp / m_battery_divider_factor) * 1000);
voltage = ( (tmp_voltage + 5) / 10) * 10; // Round the value.
NRF_LOG_INFO("Read value from saadc %d\nV",voltage);
batt_event_handler_adc(voltage);
}
//nrf_drv_saadc_uninit();
}
Such a function is
uint32_t adc_gain_enum_to_real_gain(nrf_saadc_gain_t gain_reg, float * const real_val)
{
switch(gain_reg)
{
case NRF_SAADC_GAIN1_6: *real_val = 1 / (float)6;
break;
case NRF_SAADC_GAIN1_5: *real_val = 1 / (float)5;
break;
case NRF_SAADC_GAIN1_4: *real_val = 1 / (float)4;
break;
case NRF_SAADC_GAIN1_3: *real_val = 1 / (float)3;
break;
case NRF_SAADC_GAIN1_2: *real_val = 1 / (float)2;
break;
case NRF_SAADC_GAIN1: *real_val = 1;
break;
case NRF_SAADC_GAIN2: *real_val = 2;
break;
case NRF_SAADC_GAIN4: *real_val = 3;
break;
default: return M_BATT_STATUS_CODE_INVALID_PARAM;
};
return M_BATT_STATUS_CODE_SUCCESS;
}
Here
float tmp = adc_result / (( (1/6) / ADC_REFERENCE_VOLTAGE) * pow(2, ADC_RESOLUTION_BITS));
(1/6) will always evaluate to 0. It's an integer division!
So the whole expression (( (1/6) / ADC_REFERENCE_VOLTAGE) * pow(2, ADC_RESOLUTION_BITS)) results in 0. (note: floating point here), which in turn provokes a division by zero here adc_result / ....
To fix this either do
(1./6)
or
(1/6.)
or
((float) 1/6)
or
(1 /(float) 6)
or any combination of the above.
Unrelated but another cause of trouble related to integer division as well is here:
(tmp_voltage + 5) / 10
Fix as above.

Switch/String in 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;.

Resources