Simulating virtual machine, have trouble with incrementing pc versus jumps - c

I'm writing a virtual machine in C and I have all the various functions working, however I'm having trouble putting them together. Specifically I'm running into the problem that I need a way to increment the program counter without it interfering with the instructions that change what pc is pointing at like JMP, JPC, CAL, and RET. When I try to put in measures to cancel out pc++ like a PCvalueAfterJmp - 1 or if statements to not increment on those cases, it suddenly goes into an infinite loop which appears to be repeatedly going through the instructions.
This program reads in an input file and prints to the screen what instructions are being processed and the current state of the stack
int main(int argc, char* argv[]){
int running = 1;
int numInstructions = 0;
int lineRun;
int arcntr = 0;
//Memory
int stack[MAX_STACK_HEIGHT];
instruction code[MAX_CODE_LENGTH];
int arlist[MAX_STACK_HEIGHT];
//Registers
int sp=0;
int bp=1;
int pc=0;
instruction ir;
//Initializing ir
ir.op = 0;
ir.l = 0;
ir.m = 0;
//Initializing stack
stack[1] = 0;
stack[2] = 0;
stack[3] = 0;
//Reading the input file
numInstructions = readFile(argc, argv, code);
if(numInstructions < 0) //Exit with error if readFile returns invalid
return 1;
//show input code
printFile(code, numInstructions);
//setup and labeling
printState(-1, ir, pc, bp, sp, stack, arlist);
//Execution loop
while(running)
{
lineRun = pc;
//Fetch cycle
ir = code[pc];
//Execution cycle returns a nonzero to keep program running until end
if(!execOp(&sp, &bp, &pc, ir, code, stack, arlist, &arcntr))
running = 0;
//if statement didn't work
printState(lineRun, ir, pc, bp, sp, stack, arlist);
//if (!(ir.op == 5 || ir.op == 7 || ir.op == 8 || (ir.op == 2 && ir.m == 0)))
pc++;
}
return 0;
}
Here is my execution cycle
int execOp(int* sp, int* bp, int* pc, instruction ir, instruction code[],
int stack[], int arlist[], int* arcntr){
switch((opcode)ir.op){
case LIT:
stack[++(*sp)] = ir.m;
break;
case OPR: //Operators
switch((operator)ir.m){
case RET:
if(*bp == 1) //Kill the simulation if we're at the base level
return 0;
arlist[--(*arcntr)] = 0;
*sp = *bp - 1;
*pc = stack[*sp+3];
*bp = stack[*sp+2];
break;
case NEG:
stack[*sp] = -stack[*sp];
break;
case ADD:
(*sp)--;
stack[*sp] = stack[*sp] + stack[*sp+1];
break;
case SUB:
(*sp)--;
stack[*sp] = stack[*sp] - stack[*sp+1];
break;
case MUL:
(*sp)--;
stack[*sp] = stack[*sp] * stack[*sp+1];
break;
case DIV:
(*sp)--;
stack[*sp] = stack[*sp] / stack[*sp+1];
break;
case ODD:
stack[*sp] = stack[*sp] % 2;
break;
case MOD:
(*sp)--;
stack[*sp] = stack[*sp] % stack[(*sp)+1];
break;
case EQL:
(*sp)--;
stack[*sp] = stack[*sp] == stack[*sp+1];
break;
case NEQ:
(*sp)--;
stack[*sp] = stack[*sp] != stack[*sp+1];
break;
case LSS:
(*sp)--;
stack[*sp] = stack[*sp] < stack[*sp+1];
break;
case LEQ:
(*sp)--;
stack[*sp] = stack[*sp] <= stack[*sp+1];
break;
case GTR:
(*sp)--;
stack[*sp] = stack[*sp] > stack[*sp+1];
break;
case GEQ:
(*sp)--;
stack[*sp] = stack[*sp] >= stack[*sp+1];
break;
}
break;
case LOD:
stack[++*sp] = stack[base(ir.l, *bp, stack) + ir.m];
break;
case STO:
stack[base(ir.l, *bp, stack) + ir.m] = stack[(*sp)--];
break;
case CAL:
arlist[(*arcntr)++] = *sp + 1;
stack[*sp + 1] = base(ir.l, *bp, stack);
stack[*sp + 2] = *bp;
stack[*sp + 3] = *pc - 1;
*bp = *sp + 1;
*pc = ir.m;
break;
case INC:
*sp = *sp + ir.m;
break;
case JMP:
*pc = ir.m;
break;
case JPC:
if(!stack[(*sp)--])
*pc = ir.m;
break;
case SOI:
printf("%d\n", stack[(*sp)--]);
break;
case SIO:
scanf("%d", &stack[++(*sp)]);
break;
}
return 1; //A non-zero return value keeps the machine running
}

This part of your instruction decode select statement seems wrong
case CAL:
arlist[(*arcntr)++] = *sp + 1;
stack[*sp + 1] = base(ir.l, *bp, stack);
stack[*sp + 2] = *bp;
stack[*sp + 3] = *pc - 1;
*bp = *sp + 1;
*pc = ir.m;
break;
Normally you'd want to return to the NEXT instruction on a return.
stack[*sp + 3] = *pc - 1;
The *pc-1 part will probably will bring you back to your call instruction on return
I'd expect you'd want to push the address of the next instruction instead.
You'll probably want to update the stack pointer by 3 after pushing all that too, as well as checking your BP logic too

Related

How to connect KEYPAD-SMALLCALC and LCD

I'm working on calculator project using LM3S316 microcontroller & Keil software
I have some confusion about how can I work with KEYPAD-SMALLCALC
So, my question is :
how can I use this keypad and initialize it
also, how can I represent values and use it
finally, how to connect it with LCD
Thank You
The KEYPAD-SMALL-CALC is a matrix keypad, meaning you should configure some pins as input and some pins as output.
This is a decent library that i personally have used for a project of mine using a matrix keypad - https://github.com/nimaltd/KeyPad
You should be able to integrate it in your code without too much issues.
In short you have cols and rows. In the example provided the rows are input pins and the cols are output pins. There is a for cycle that is checking for a button press. By default rows are high, once a button is pressed the library checks for a combination between row and col that determinate which button has been pressed.
For configuration pins the easiest way would probably to use software such as "STM32CubeMX" which generates c code with your MCU configuration, you can easily configurate there the matrix keypad rows, cols and decide which pins you should use for the LCD.
Edit : Here is a modified version of the github library i have personally used in a project
source keyboard.c
#include "keyboard.h"
//#define _KEYPAD_DELAY(x) HAL_Delay(x)
const GPIO_TypeDef* _KEYPAD_COLUMN_GPIO_PORT[] =
{
COL_1_GPIO_Port,
COL_2_GPIO_Port,
COL_3_GPIO_Port,
COL_4_GPIO_Port,
COL_5_GPIO_Port,
COL_6_GPIO_Port,
COL_7_GPIO_Port,
COL_8_GPIO_Port
};
const uint16_t _KEYPAD_COLUMN_GPIO_PIN[] =
{
COL_1_Pin,
COL_2_Pin,
COL_3_Pin,
COL_4_Pin,
COL_5_Pin,
COL_6_Pin,
COL_7_Pin,
COL_8_Pin
};
const GPIO_TypeDef* _KEYPAD_ROW_GPIO_PORT[] =
{
ROW_1_GPIO_Port,
ROW_2_GPIO_Port,
ROW_3_GPIO_Port,
ROW_4_GPIO_Port
};
const uint16_t _KEYPAD_ROW_GPIO_PIN[] =
{
ROW_1_Pin,
ROW_2_Pin,
ROW_3_Pin,
ROW_4_Pin
};
KeyPad_t KeyPad;
//#############################################################################################
void KeyPad_Init(void)
{
KeyPad.ColumnSize = sizeof(_KEYPAD_COLUMN_GPIO_PIN)/2;
KeyPad.RowSize = sizeof(_KEYPAD_ROW_GPIO_PIN)/2;
}
//#############################################################################################
uint16_t KeyPad_Scan(void)
{
uint16_t key = 0;
uint8_t hold_key = 0;
int int_btn_cnt = 0;
int int_button_state_change = 0;
GPIO_PinState int_button_current_state = GPIO_PIN_SET;
GPIO_PinState int_button_last_state = GPIO_PIN_SET;
for(uint8_t c=0 ; c<KeyPad.ColumnSize ; c++)
{
for(uint8_t i=0 ; i<KeyPad.ColumnSize ; i++)
HAL_GPIO_WritePin((GPIO_TypeDef*)_KEYPAD_COLUMN_GPIO_PORT[i],_KEYPAD_COLUMN_GPIO_PIN[i],GPIO_PIN_SET);
HAL_GPIO_WritePin((GPIO_TypeDef*)_KEYPAD_COLUMN_GPIO_PORT[c],_KEYPAD_COLUMN_GPIO_PIN[c],GPIO_PIN_RESET);
for(uint8_t r=0 ; r<KeyPad.RowSize ; r++){
while(HAL_GPIO_ReadPin((GPIO_TypeDef*)_KEYPAD_ROW_GPIO_PORT[r],_KEYPAD_ROW_GPIO_PIN[r])==GPIO_PIN_RESET){
int_btn_cnt++;
if(int_btn_cnt == _KEYPAD_DEBOUNCE_TIME_MS){
key |= 1<<c;
key |= 1<<(r+8);
return key;
}
}
int_btn_cnt = 0;
}
}
return key;
}
//#############################################################################################
uint16_t KeyPad_WaitForKey(uint32_t Timeout_ms)
{
volatile uint16_t keyRead;
while(Timeout_ms==0)
{
keyRead = KeyPad_Scan();
if(keyRead!=0)
{
KeyPad.LastKey = keyRead;
return keyRead;
}
}
uint32_t StartTime = HAL_GetTick();
while(HAL_GetTick()-StartTime < Timeout_ms)
{
keyRead = KeyPad_Scan();
if(keyRead!=0){
KeyPad.LastKey = keyRead;
return keyRead;
}
}
return 0;
}
//#############################################################################################
char KeyPad_WaitForKeyGetChar(uint32_t Timeout_ms)
{
char result = 0;
switch(KeyPad_WaitForKey(Timeout_ms))
{
case 0x802: // ^
result = '^';
break;
case 0x804: // 7
result = '7';
break;
case 0x808: // 7
result = '8';
break;
case 0x810: // 9
result = '9';
break;
case 0x820: // 04
result = 0xFF;
break;
case 0x840: // D+
result = 0xFE;
break;
case 0x880: // M
result = 'M';
break;
case 0x401: // -%
result = '-';
break;
case 0x402: // +%
result = '+';
break;
case 0x404: // 4
result = '4';
break;
case 0x408: // 6
result = '5';
break;
case 0x410: // 6
result = '6';
break;
case 0x420: // 03
result = 0xFD;
break;
case 0x440: // PRUREP
result = 0xFC;
break;
case 0x480: // STL
result = 0xFB;
break;
case 0x201: // ALT
result = 0xFA;
break;
case 0x202: // CLK
result = 0xF9;
break;
case 0x204: // 1
result = '1';
break;
case 0x208: // 3
result = '2';
break;
case 0x210: // 3
result = '3';
break;
case 0x220: // 02
result = 0xF8;
break;
case 0x240: // PY1 RA
result = 0xF7;
break;
case 0x101: // C
result = 'C';
break;
case 0x102: // VD
result = 0xF6;
break;
case 0x104: // 0
result = '0';
break;
case 0x108: // .
result = '.';
break;
case 0x110: // QTY
result = 0xF5;
break;
case 0x120: // 01
result = 0xF4;
break;
case 0x140: // PY2PO
result = 0xF3;
break;
case 0x180: // TL
result = 0xF2;
break;
}
return result;
}
and the header file keyboard.h
#ifndef __KEYBOARD_H__
#define __KEYBOARD_H__
#include <stdint.h>
#include <stdbool.h>
typedef struct
{
uint8_t ColumnSize;
uint8_t RowSize;
uint16_t LastKey;
}KeyPad_t;
void KeyPad_Init(void);
uint16_t KeyPad_WaitForKey(uint32_t Timeout_ms);
char KeyPad_WaitForKeyGetChar(uint32_t Timeout_ms);
#define _KEYPAD_DEBOUNCE_TIME_MS 5
#endif /* __KEYBOARD_H__ */
You should only configure the const arrays with the ports and pins you are planning to use and use the library like this :
init keyboard at the start of your program:
KeyPad_Init();
and use it like this
uint8_t key = KeyPad_WaitForKeyGetChar(1); // wait 1 ms
key is the value of the pressed key, if you use KeyPad_WaitForKeyGetChar(0) the code will stay here and wait for a key press.
Hope it helps!

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

Issues with state machine in c [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I'm facing some issues with my state machine (function automate()). It seems that the enum always keep the same values instead of changing it depending on differents conditions in the function.
My output is always "DECREMENT_PARA_1" Can anyone tell me why the variable etat_courant doesn't keep the value in memory for each iteration please ? Thanks in advance ! Here is my code :
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
//PARAMETRES
enum Etat {INIT, DECREMENT_PARA_1, INCREMENT_PARA_1, ETAT_INVARIANT_1, DECREMENT_PARA_2, ETAT_INVARIANT_2, INCREMENT_PARA_2, RADAR_SATURE};
//Prototypes
void automate(int tddv_estime, int tab_para_automate[][2], enum Etat *etat_courant, int* para_1_courant, int* para_2_courant);
void fct_test(int scenario[]);
int main()
{
int scenario[15] = {21, 21, 20, 12, 12, 20, 22, 22, 22, 22, 22, 22, 22, 22, 500};
fct_test(scenario);
return 0;
}
/*-----------------------------------------------------------------------
Fonction fct_test
-------------------------------------------------------------------------*/
void fct_test(int scenario[])
{
int increment = 1;
int tddv_estime;
int para_1_courant = 10;
int para_2_courant = 4;
int para_1_min = 5;
int para_1_max = 10;
int para_2_min = 1;
int para_2_max = 4;
int tab_para_automate[2][2] = {{0}};
int tab_para_application[1][3] = {{0}};
tab_para_automate[0][0] = para_1_min;
tab_para_automate[0][1] = para_1_max;
tab_para_automate[1][0] = para_2_min;
tab_para_automate[1][1] = para_2_max;
tab_para_application[0][0] = para_1_courant;
tab_para_application[0][1] = para_2_courant;
tab_para_application[0][2] = increment;
int i;
enum Etat etat_courant = INIT;
for (i=0 ; i<15 ; i++)
{
tddv_estime = scenario[i];
printf("%d\n",scenario[i]);
automate(tddv_estime, tab_para_automate, &etat_courant, &para_1_courant, &para_2_courant);
}
//}
}
/*-----------------------------------------------------------------------
Fonction automate
-------------------------------------------------------------------------*/
void automate(int tddv_estime, int tab_para_automate[][2], enum Etat *etat_courant, int* para_1_courant, int* para_2_courant)
{
int evenement;
int tddv_worst = 20;
if (tddv_estime < tddv_worst)
evenement = 1; //Etat initial
if (tddv_estime > tddv_worst)
evenement = 2; //Decrement para1
if (tddv_estime < tddv_worst && *para_1_courant<= tab_para_automate[0][1])
evenement = 3; //Increment para1
if (tddv_estime == tddv_worst)
evenement = 4; //Etat Invariant 1
if (tddv_estime > tddv_worst && *para_1_courant <= tab_para_automate[0][0])
evenement = 5; //Decrement para_2
if (tddv_estime < tddv_worst && *para_2_courant <= tab_para_automate[1][1])
evenement = 6; //Increment para2
if (tddv_estime == tddv_worst)
evenement = 7; //Etat Invariant 2
if (tddv_estime > tddv_worst && *para_1_courant<= tab_para_automate[0][0] && *para_2_courant<= tab_para_automate[1][0])
evenement = 8; //Etat radar sature
switch (*etat_courant) {
case INIT:
switch(evenement)
{
case 1:
*etat_courant = INIT;
printf("ETAT_INITIAL\n");
break;
case 2:
*etat_courant = DECREMENT_PARA_1;
printf("DECREMENT_PARA_1\n");
break;
}
break;
case DECREMENT_PARA_1:
switch(evenement)
{
case 5:
*etat_courant = DECREMENT_PARA_2;
printf("DECREMENT_PARA_2\n");
break;
case 4:
*etat_courant = ETAT_INVARIANT_1;
printf("ETAT_INVARIANT_1\n");
break;
case 3:
*etat_courant = INCREMENT_PARA_1;
printf("INCREMENT_PARA_1\n");
break;
case 2:
*etat_courant = DECREMENT_PARA_1;
printf("DECREMENT_PARA_1\n");
break;
}
break;
case INCREMENT_PARA_1:
switch(evenement)
{
case 4:
*etat_courant = ETAT_INVARIANT_1;
printf("ETAT_INVARIANT_1\n");
break;
case 3:
*etat_courant = INCREMENT_PARA_1;
printf("INCREMENT_PARA_1\n");
break;
case 2:
*etat_courant = DECREMENT_PARA_1;
printf("DECREMENT_PARA_1\n");
break;
}
break;
case ETAT_INVARIANT_1:
switch(evenement)
{
case 2:
*etat_courant = DECREMENT_PARA_1;
printf("DECREMENT_PARA_1\n");
break;
case 4:
*etat_courant = ETAT_INVARIANT_1;
printf("ETAT_INVARIANT_1\n");
break;
case 3:
*etat_courant = INCREMENT_PARA_1;
printf("INCREMENT_PARA_1\n");
break;
}
break;
case DECREMENT_PARA_2:
switch(evenement)
{
case 5:
*etat_courant = DECREMENT_PARA_2;
printf("DECREMENT_PARA_2\n");
break;
case 7:
*etat_courant = ETAT_INVARIANT_2;
printf("ETAT_INVARIANT_2\n");
break;
case 6:
*etat_courant = INCREMENT_PARA_2;
printf("INCREMENT_PARA_2\n");
break;
case 8:
*etat_courant = RADAR_SATURE;
printf("RADAR_SATURE\n");
break;
}
break;
case ETAT_INVARIANT_2:
switch(evenement)
{
case 5:
*etat_courant = DECREMENT_PARA_2;
printf("DECREMENT_PARA_2\n");
break;
case 7:
*etat_courant = ETAT_INVARIANT_2;
printf("ETAT_INVARIANT_2\n");
break;
case 6:
*etat_courant = INCREMENT_PARA_2;
printf("INCREMENT_PARA_2\n");
break;
}
break;
case INCREMENT_PARA_2:
switch(evenement)
{
case 5:
*etat_courant = DECREMENT_PARA_2;
printf("DECREMENT_PARA_2\n");
break;
case 7:
*etat_courant = ETAT_INVARIANT_2;
printf("ETAT_INVARIANT_2\n");
break;
case 6:
*etat_courant = INCREMENT_PARA_2;
printf("INCREMENT_PARA_2\n");
break;
case 3:
*etat_courant = INCREMENT_PARA_1;
printf("INCREMENT_PARA_1\n");
break;
}
break;
default :
exit(1);
break;
}
}
Can anyone tell me why the variable etat_courant doesn't keep the value in memory for each iteration please ?
It actually is keeping the value in memory: it can not do otherwise, etat_courant will be kept in memory until fct_test(...) returns. The reason the output is always DECREMENT_PARA_1 is purely due to the logic in your automate() function.
For example, you have a redundant comparison in your automate() function - which is overriding a previous assignment of evenement.
if (tddv_estime == tddv_worst)
evenement = 4; //Etat Invariant 1
// ...
if (tddv_estime == tddv_worst)
evenement = 7; //Etat Invariant 2
If - and this is just hypothetical (whether or not this is the right thing to do depends on what you are trying to achieve) - you remove the second comparison, the output will vary at least once.
As an aside ... It is safer to pass the size of the array to your fct_test(...) function - as in
int main(void) {
int scenario[] = {21, 21, 20, 12, 12, 20, 22, 22,
22, 22, 22, 22, 22, 22, 500};
fct_test(scenario, sizeof(scenario)/sizeof(scenario[0]));
return 0;
}
void fct_test(int *scenario, size_t array_len) {
// Etc. (ommitted for brevity )
for (i = 0; i < array_len; i++) {
tddv_estime = scenario[i];
// etc.
}
}
(Note that I added a return 0 in your main() also - which you were missing.)

Counting vowels in text without arrays (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.

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