How to get the right value? - c++

What must I do to get the right Level?
example:
int gXP = globalDoHandle::PlayerStats_XP(p);
ostringstream sXP; sXP << "XP(RP): " << gXP;
ostringstream sLEVEL; sLEVEL << "Level: " << gLEVEL;
I want use the XP value to get the right Level then.
If I get the the value 24450 should give me it then "10" back
I know I can use something like this, but that are 8000 Level in the Game!
if (gXP < 800) { Rank = "1"; }
else if (gXP < 2100) { Rank = "2"; }
else if (gXP < 3800) { Rank = "3"; }
...
LEVEL: XP
Level 1: 0
Level 2: 800
Level 3: 2100
Level 4: 3800
Level 5: 6100
Level 6: 9500
Level 7: 12500
Level 8: 16000
Level 9: 19800
Level 10: 24000
Level 11: 28500
Level 12: 33400
Level 13: 38700
Level 14: 44200
Level 15: 50200
Level 16: 56400
Level 17: 63000
Level 18: 69900
Level 19: 77100
Level 20: 84700
...Level 8000: 1787576850

To do such a job, you need std::lower_bound. std::lower_bound(l, h, v) returns an iterator it inside the range [l, h) for which the value on the range is the smallest verifying *it > v.
constexpr std::array<unsigned, 10> levels = { /* ... */ }; // xp needed for each level
unsigned level(unsigned xp)
{
auto it = std::lower_bound(cbegin(levels), cend(levels), xp);
return std::distance(begin(levels), it);
}
level(xp) returns the level reached with xp experience points with respect to the values of levels.
Se a full demo online

Use a std::array with your exp values in.
std::array<int, 8000> exp_table = { 0, 800, 2100... };
int level=0;
for(; level < exp_table.size() && exp_table[level] < gXP; ++level);
Rank = std::to_string(level); // If this is needed?
After this level will be set correctly. The only thing left is how you generate your exp_table. Read it from a file. Use some math formula.

Related

How to Stop a Brute Force Attack When Key is Found

I am writing a program that encrypts/decrypts a message using Caesar Cipher and a shift number given by the user. I got that part down, more or less.
However, the final part of the program performs a brute force attack on an encrypted message, and we are attempting to find the shift key that was used to encrypt it. I am having trouble determining the best way to stop the program when it finds the match.
I will paste my code below, and what it comes up with running it now. I have tested with pencil and paper, and can see the key is 17 for our particular input, so I put a crap condition just to get it working. I am wondering how to stop it when it finds the correct value and/or a sentence that is actual English, so that it works for every input, not just our test case.
P.S. I apologize if this is answered elsewhere, the only posts I found on the topic were more related to stopping brute force attacks and/or having secure passwords.
char decrypt(char letter, int key);
int main(){
// Part 3 Brute-Force Attack
std::string ciphertext;
std::cout << "Enter in the ciphertext: ";
std::getline(std::cin, ciphertext);
std::cout << "\nBrute-Force Decryptions:" << std::endl;
int i = 0;
int keyCode = 0;
std::string gang = "";
int alphaArray[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24};
// The algorithm has nested for each loops, the first one keeps track of the key initialized to 0
// and the second loop goes through the string given and converts it to the proper value based
// on the shift key. The reason we want to find 't', 'h' or 'e' is because this signifies the
// begginning of an actual English sentence, and most likely our cracked message. I was able to
// determine this would begin the correct string we are looking for by bruteforcing the first // few letters using pencil and paper
for(auto key : alphaArray){
std::cout << "\nkey = " << key << ":\t";
for(auto letter : ciphertext){
letter = decrypt(letter, i);
gang += letter;
}
std::cout << gang << std::endl;
if (tolower(ciphertext[0]) - key + 26 == 't' && tolower(ciphertext[1]) - key == 'h' && tolower(ciphertext[2]) - key == 'e'){
keyCode = key;
break;
}
i++;
gang = "";
}
// Output results
std::cout << "\nPart 3 KeyCode: " << keyCode << std::endl;
std::cout << "\n\n";
return 0;
}
//////////////////////////////////////////////////////////////////////////////////////
// Function: Attempts to decrypt letter by shifting it up the alphabet 'key' times /
// Params: Letter as a char and key as an int value /
// Return: Letter shifted 'key' times /
//////////////////////////////////////////////////////////////////////////////////////
char decrypt(char letter, int key){
int position = (letter - key - 'A') % 26;
if(position < 0)
position += 26;
return (char)position + 'a';
}
Output:
Brute-Force Decryptions:
key = 0: kyvtjyzwkttzgyvitzjtrcjftbefnetrjtkyvttrvjrittzgyviftrwkvitalczljttrvjriftnyftivglkvucptljvutkyvttzgyvitkftgrjjtdvjjrxvjtkftyzjtkiffgjtulizextyzjtdzczkripttrdgrzxejtzetxrlchtefkvtkyrktkyvttrvjrittzgyvitzjtvrjzcpttirtbvutsptkyvtsilkvgwfitvtrkkrtbh
key = 1: jxusixyvjssyfxuhsyisqbiesademdsqisjxussquiqhssyfxuhesqvjuhszkbykissquiqhesmxeshufkjutboskiutsjxussyfxuhsjesfqiiscuiiqwuisjesxyisjheefistkhydwsxyiscybyjqhossqcfqywdisydswqkbgsdejusjxqjsjxussquiqhssyfxuhsyisuqiybosshqsautsrosjxusrhkjufvehsusqjjqsag
key = 2: iwtrhwxuirrxewtgrxhrpahdrzcdlcrphriwtrrpthpgrrxewtgdrpuitgryjaxjhrrpthpgdrlwdrgtejitsanrjhtsriwtrrxewtgridrephhrbthhpvthridrwxhrigddehrsjgxcvrwxhrbxaxipgnrrpbepxvchrxcrvpjafrcditriwpiriwtrrpthpgrrxewtgrxhrtphxanrrgprztsrqnriwtrqgjiteudgrtrpiiprzf
key = 3: hvsqgvwthqqwdvsfqwgqozgcqybckbqogqhvsqqosgofqqwdvsfcqothsfqxizwigqqosgofcqkvcqfsdihsrzmqigsrqhvsqqwdvsfqhcqdoggqasggousgqhcqvwgqhfccdgqrifwbuqvwgqawzwhofmqqoadowubgqwbquoizeqbchsqhvohqhvsqqosgofqqwdvsfqwgqsogwzmqqfoqysrqpmqhvsqpfihsdtcfqsqohhoqye
key = 4: gurpfuvsgppvcurepvfpnyfbpxabjapnfpgurppnrfneppvcurebpnsgrepwhyvhfppnrfnebpjubperchgrqylphfrqpgurppvcurepgbpcnffpzrffntrfpgbpuvfpgebbcfpqhevatpuvfpzvyvgnelppnzcnvtafpvaptnhydpabgrpgungpgurppnrfneppvcurepvfprnfvylppenpxrqpolpgurpoehgrcsbeprpnggnpxd
key = 5: ftqoeturfooubtqdoueomxeaowzaizomeoftqoomqemdooubtqdaomrfqdovgxugeoomqemdaoitaodqbgfqpxkogeqpoftqooubtqdofaobmeeoyqeemsqeofaotueofdaabeopgduzsotueoyuxufmdkoomybmuszeouzosmgxcozafqoftmfoftqoomqemdooubtqdoueoqmeuxkoodmowqponkoftqondgfqbradoqomffmowc
key = 6: espndstqenntaspcntdnlwdznvyzhynldnespnnlpdlcnntaspcznlqepcnufwtfdnnlpdlcznhszncpafepowjnfdponespnntaspcneznalddnxpddlrpdneznstdneczzadnofctyrnstdnxtwtelcjnnlxaltrydntynrlfwbnyzepneslenespnnlpdlcnntaspcntdnpldtwjnnclnvponmjnespnmcfepaqzcnpnleelnvb
key = 7: dromcrspdmmszrobmscmkvcymuxygxmkcmdrommkockbmmszrobymkpdobmtevsecmmkockbymgrymbozedonvimeconmdrommszrobmdymzkccmwocckqocmdymrscmdbyyzcmnebsxqmrscmwsvsdkbimmkwzksqxcmsxmqkevamxydomdrkdmdrommkockbmmszrobmscmokcsvimmbkmuonmlimdromlbedozpybmomkddkmua
key = 8: cqnlbqrocllryqnalrbljubxltwxfwljblcqnlljnbjallryqnaxljocnalsdurdblljnbjaxlfqxlanydcnmuhldbnmlcqnllryqnalcxlyjbblvnbbjpnblcxlqrblcaxxyblmdarwplqrblvrurcjahlljvyjrpwblrwlpjduzlwxcnlcqjclcqnlljnbjallryqnalrblnjbruhllajltnmlkhlcqnlkadcnyoxalnljccjltz
key = 9: bpmkapqnbkkqxpmzkqakitawksvwevkiakbpmkkimaizkkqxpmzwkinbmzkrctqcakkimaizwkepwkzmxcbmltgkcamlkbpmkkqxpmzkbwkxiaakumaaiomakbwkpqakbzwwxaklczqvokpqakuqtqbizgkkiuxiqovakqvkoictykvwbmkbpibkbpmkkimaizkkqxpmzkqakmiaqtgkkziksmlkjgkbpmkjzcbmxnwzkmkibbiksy
key = 10: aoljzopmajjpwolyjpzjhszvjruvdujhzjaoljjhlzhyjjpwolyvjhmalyjqbspbzjjhlzhyvjdovjylwbalksfjbzlkjaoljjpwolyjavjwhzzjtlzzhnlzjavjopzjayvvwzjkbypunjopzjtpspahyfjjhtwhpnuzjpujnhbsxjuvaljaohajaoljjhlzhyjjpwolyjpzjlhzpsfjjyhjrlkjifjaoljiybalwmvyjljhaahjrx
key = 11: znkiynolziiovnkxioyigryuiqtuctigyiznkiigkygxiiovnkxuiglzkxiparoayiigkygxuicnuixkvazkjreiaykjiznkiiovnkxizuivgyyiskyygmkyizuinoyizxuuvyijaxotminoyisorozgxeiigsvgomtyiotimgarwituzkizngziznkiigkygxiiovnkxioyikgyoreiixgiqkjiheiznkihxazkvluxikigzzgiqw
key = 12: ymjhxmnkyhhnumjwhnxhfqxthpstbshfxhymjhhfjxfwhhnumjwthfkyjwhozqnzxhhfjxfwthbmthwjuzyjiqdhzxjihymjhhnumjwhythufxxhrjxxfljxhythmnxhywttuxhizwnslhmnxhrnqnyfwdhhfrufnlsxhnshlfzqvhstyjhymfyhymjhhfjxfwhhnumjwhnxhjfxnqdhhwfhpjihgdhymjhgwzyjuktwhjhfyyfhpv
key = 13: xligwlmjxggmtlivgmwgepwsgorsargewgxliggeiwevggmtlivsgejxivgnypmywggeiwevsgalsgvityxihpcgywihgxliggmtlivgxsgtewwgqiwwekiwgxsglmwgxvsstwghyvmrkglmwgqmpmxevcggeqtemkrwgmrgkeypugrsxigxlexgxliggeiwevggmtlivgmwgiewmpcggvegoihgfcgxligfvyxitjsvgigexxegou
key = 14: wkhfvkliwfflskhuflvfdovrfnqrzqfdvfwkhffdhvdufflskhurfdiwhufmxolxvffdhvdurfzkrfuhsxwhgobfxvhgfwkhfflskhufwrfsdvvfphvvdjhvfwrfklvfwurrsvfgxulqjfklvfplolwdubffdpsdljqvflqfjdxotfqrwhfwkdwfwkhffdhvdufflskhuflvfhdvlobffudfnhgfebfwkhfeuxwhsirufhfdwwdfnt
key = 15: vjgeujkhveekrjgtekuecnuqempqypecuevjgeecgucteekrjgtqechvgtelwnkwueecguctqeyjqetgrwvgfnaewugfevjgeekrjgtevqercuueoguuciguevqejkuevtqqruefwtkpiejkueoknkvctaeecorckipuekpeicwnsepqvgevjcvevjgeecgucteekrjgtekuegcuknaeetcemgfedaevjgedtwvgrhqtegecvvcems
key = 16: uifdtijguddjqifsdjtdbmtpdlopxodbtduifddbftbsddjqifspdbgufsdkvmjvtddbftbspdxipdsfqvufemzdvtfeduifddjqifsdupdqbttdnfttbhftdupdijtdusppqtdevsjohdijtdnjmjubszddbnqbjhotdjodhbvmrdopufduibuduifddbftbsddjqifsdjtdfbtjmzddsbdlfedczduifdcsvufqgpsdfdbuubdlr
key = 17: thecshiftccipherciscalsocknowncasctheccaesarccipherocaftercjuliusccaesarocwhocreputedlycusedctheccipherctocpasscmessagesctochisctroopscduringchiscmilitaryccampaignscincgaulqcnotecthatctheccaesarcciphercisceasilyccrackedcbycthecbrutepforcecattackq
Part 3 KeyCode: 17
Brute-force-breaking Caesar-Cypher can be easily done by using heuristics. A very good and simple approach is, to use the average frequency of a letter in a given language. Such tables can be found on the internet for many languages.
Let us look at the English language. I found for example the following:
a: 0.0684
b: 0.0139
c: 0.0146
d: 0.0456
e: 0.1267
f: 0.0234
g: 0.0180
h: 0.0701
i: 0.0640
j: 0.0033
k: 0.0093
l: 0.0450
m: 0.0305
n: 0.0631
o: 0.0852
p: 0.0136
q: 0.0004
r: 0.0534
s: 0.0659
t: 0.0850
u: 0.0325
v: 0.0084
w: 0.0271
x: 0.0007
y: 0.0315
z: 0.0004
Later we need to look up this occurrence value for each letter of the alphabet. We will use lowercase only. We can define a compile-time array for that.
constexpr std::array<double, 26> LetterWeight{ .0684,.0139,.0146,.0456,.1267,
.0234,.0180,.0701,.0640,.0033,.0093,.0450,.0305,.0631,.0852,.0136,.0004,.0534,
.0659,.0850,.0325,.0084,.0271,.0007,.0315,.0004 };
Then, we will do the following. With the brute force approach, we will try all possible keys for decryption in a loop.
So, we will decrypt the encrypted message 25 times. We can omit the key 0, because then the message would be clear and readable.
In each loop for the 25 keys, we will additionally analyze each letter of the decrypted message (if it is the right key or not does not matter at this moment).
We will build a score for this decrypted string by adding up the above defined occurrence-value for each key based on the letter.
In the end, we will have a sum for each key / letter of the decrypted string. Additionally, we will store the key that has been used for those sums.
For this, we will define a std::array of std::pair. There will be 26 elements in the std::array. One for each of the tested keys. The content will be the sum of letter-occurrence-values for each key and again the key.
std::array<std::pair<double, int>, 26> score{};
We need to store again the key in the array, because we want to sort the std::array later to find the highest score and its corresponding key.
Regarding the encryption/decryption function, I gave a detailed answer with a long explanation here. Please, kindly check this.
Now, with all the above wisdom, we can come up with the following code cracker:
#include <iostream>
#include <array>
#include <cctype>
#include <string>
#include <algorithm>
// Some test string
const std::string test{ R"(Kyv rcxfizkyd yrj evjkvu wfi vrty cffgj, kyv wzijk fev bvvgj kirtb fw kyv bvp zezkzrczqvu kf 0 reu kyv
jvtfeu cffg xfvj kyiflxy kyv jkizex xzmve reu tfemvikj zk kf kyv gifgvi mrclv srjvu fe kyv jyzwk bvp.
Kyv ivrjfe nv nrek kf wzeu 'k', 'y' fi 'v' zj svtrljv kyzj jzxezwzvj kyv svxxzeezex fw re rtklrc Vexczjy
jvekvetv,reu dfjk czbvcp fli tirtbvu dvjjrxv.Z nrj rscv kf uvkvidzev kyzj nflcu svxze kyv tfiivtk jkizex
nv riv cffbzex wfi sp silkvwfitzex kyv wzijk wvn cvkkvij ljzex gvetzc reu grgvi.)" };
// Letter frequencies in the English Language
constexpr std::array<double, 26> LetterWeight{ .0684,.0139,.0146,.0456,.1267,.0234,.0180,.0701,.0640,.0033,.0093,.0450,.0305,.0631,.0852,.0136,.0004,.0534,.0659,.0850,.0325,.0084,.0271,.0007,.0315,.0004 };
// Simple function for Caesar encyption/decyption (decryption by simply using a negative key)
std::string caesar(const std::string& in, int key) {
std::string res(in.size(), ' ');
std::transform(in.begin(), in.end(), res.begin(), [&](char c) {return std::isalpha(c) ? (char)((((c & 31) - 1 + ((26 + (key % 26)) % 26)) % 26 + 65) | c & 32) : c; });
return res;
}
// Test code
int main() {
// We will try all possible ciphers 1..25
std::array<std::pair<double, int>, 26> score{};
for (int key = 1; key < 26; ++key) {
// Get one possible deciphered test
for (const char c : caesar(test, key)) {
// Calculate score according toLetter weight
score[key].first += (std::isalpha(c)) ? LetterWeight[(c & 31) - 1] : 0.0; // Build the score for this key, using the accumulated letter weight
score[key].second = key; // And store the key. Is necessary, becuase we will sort later and do not want to loose the key information
}
}
// Now sort for getting the index with the highes score
std::sort(score.begin(), score.end());
// And show the most probable result to the user.
std::cout << "Decrypted with key: "<< score.back().second-26 << "\n\n" << caesar(test, score.back().second) << "\n\n";
};
All the code breaking can be done with ~15 lines of code. So, rather simple.
The resulting output will be:

Input a date in 8 digit numerical form and display into English form

Below is the c++ problem i have to solve and i'm having some trouble from number 2)
1) Prompt the user to input a date in 8 digit numerical form(MMDDYYYY)
ex. 04221970
2) Display the date in English form
ex. 22nd April 1970
3) If the day the user entered is 01,21,31, add "st" after the day
4) Else if the day the user entered is 02,22, add "nd" after the day
5) Elae if the day user entered is 03,23, add "rd" after the day
6) Else add "th" after the day
All of the step are rather straightforward. But dates are always tricky, since there are many rules. But only a couple apply for parsing.
Define a struct to hold the parsed value and parse the input.
[EDIT] The value of using a struct, is that it can be useful to have an intermediate function that would return this reusable bit of binary data.
struct date_s
{
unsigned int day;
unsigned int month;
unsigned int year;
};
// parsing
date_s date = {};
if (strlen(input) != 8 || sscanf(input, "%2u%2u%4u", &date.month, &date.day, &date.year) != 3)
{
// handle error
}
Validating the year is rather easy, there is nothing to do, unless you want to restrict to a specific range. For example, since we're using the Gregorian calendar, you may want to restrict to years after 1582, inclusive.
Validating the month is also very straightforward, we'll validate that along with the number of days in a month, which is the most tricky part, because of Febuary.
unsigned int day_max = 0;
switch (date.month)
{
case 1: case 3: case 5; case 7: case 8: case 10: case 12:
day_max = 31;
break;
case 4: case 6: case 9: case 11:
day_max = 30;
break;
case 2:
if (date.year % 4 != 0)
day_max = 28;
else if (date.year % 100 != 0)
day_max = 29;
else if (date.year % 400 != 0)
day_max = 28;
else
day_max = 29;
break;
// else day_max stays 0, of course
}
if (date.day < 1 || day_max < date.day)
{
// error
}
After all the validating is done, all you have to do is print.
For the months you will need to define a table of strings for display.
const char* MONTH[12] = { "January", /* etc... */ };
Date suffix.
const char* SUFFIX[4] = { "st", "nd", "rd", "th" };
We now have all the data we need to print, and all within range, too.
const char* suffix = SUFFIX[std::min(date.day, 4) - 1];
printf("%d%s %s %d", date.day, suffix, MONTH[date.month - 1], date.year);
// or, for US format
printf("%s %d%s, %d", MONTH[date.month - 1], date.day, suffix, date.year);

C++ - Variable Decrement

Heys.
I have this code, which sets a table for some mystery reason. Size is 6x60. Which means SIZEY defined as 6, and SIZEX as 60.
void set_table(char** table)
{
int i,j,k=0;
for(i=0;i<SIZEY;i+=3){
for(j=0;j<SIZEX;j++){
switch(k++%5){
case 0:
table[i][j]='|';
break;
case 1:
table[i][j]=' ';
break;
case 2:
table[i][j]=(char)((((k-2)/50)%10)+48);
break;
case 3:
table[i][j]=(char)((((k-3)/5)%10)+48);
break;
case 4:
table[i][j]=' ';
break;
default:
continue;
}
}
}
}
I am doing this with 3 variables, as you can see. Question is, can i do that with 2 variables, or even with only 1 ?
Thanks in advance.
Here's a simplification for you:
switch(k++%5){
case 0:
table[i][j]='|';
break;
case 1:
case 4:
table[i][j]=' ';
break;
case 2:
case 3:
table[i][j]= '0';
break;
default:
continue;
}
With C++, one case can fall into another, such as with cases 1 and 2 above.
Your expressions for case 2 and 3 can be simplified. I'll use case 2 as an example:
((((k-2)/50)%10)+48)
Substituting 2 for k yields
((((2-2)/50)%10)+48)
Simplify:
((((0)/50)%10)+48)
Zero divided by anything is zero, simplifying again:
(((0)%10)+48)
Zero mod anything is zero, since it involves division:
((0)+48)
Simplifying:
(48)
Replacing with the equivalent character (since your array is char):
'0'

Is jBCrypt's default log_rounds still appropriate for 2013

I've been using jBCrypt version 0.3 out-of-the-box now since it came out in 2010. I use the default getsalt() method which sets the number of "log_rounds" to 10. Given the progression of password cracking hardware and methods, is this value still appropriate as a default, or should i be looking at some higher value.
Info from the javadoc...
String pw_hash = BCrypt_v03.hashpw(plain_password, BCrypt_v03.gensalt());
String strong_salt = BCrypt_v03.gensalt(10)
String stronger_salt = BCrypt_v03.gensalt(12)
The amount of work increases exponentially (2**log_rounds), so each increment is twice as much work. The default log_rounds is 10, and the valid range is 4 to 31.
I made a little test class to check the performance of checkPw() under differing salt log_rounds.
public void testCheckPerformance() {
int MULT = 1;
for( int i = 4; i < 31; i++) {
String salt = BCrypt_v03.gensalt(i);
String hashpw = BCrypt_v03.hashpw("my pwd", salt);
long startTs = System.currentTimeMillis();
for( int mult = 0; mult < MULT; mult++) {
assertTrue(BCrypt_v03.checkpw("my pwd", hashpw));
}
long endTs = System.currentTimeMillis();
System.out.println(""+i+": " + ((endTs-startTs)/MULT));
}
}
My PC is an 8 core i7 2.8GHz. The results are:
log-rounds: time in millis.
4: 3
5: 3
6: 6
7: 11
8: 22
9: 46
10: 92
11: 188
12: 349
13: 780
14: 1449
15: 2785
16: 5676
17: 11247
18: 22264
19: 45170
Using the default log_rounds=10 means that a single thread can check a login in 0.1s. This potentially limits the number of login checks per second that a single server can achieve.
So i guess the question becomes how much time are you prepared to spend per password check vs how many password checks per second you want to size the system to cope with.

I asked this yesterday, after the input given I'm still having trouble implementing

I'm not sure how to fix this or what I did wrong, but whenever I enter in a value it just closes out the run prompt.
So, seems I do have a problem somewhere in my coding. Whenever I run the program and input a variable, it always returns the same answer.."The content at location 76 is 0."
On that note, someone told me that "I don't know, but I suspect that Program A incorrectly has a fixed address being branched to on instructions 10 and 11." - mctylr but I'm not sure how to fix that..
I'm trying to figure out how to incorporate this idea from R Samuel Klatchko.. I'm still not sure what I'm missing but I can't get it to work..
const int OP_LOAD = 3;
const int OP_STORE = 4;
const int OP_ADD = 5;
...
const int OP_LOCATION_MULTIPLIER = 100;
mem[0] = OP_LOAD * OP_LOCATION_MULTIPLIER + ...;
mem[1] = OP_ADD * OP_LOCATION_MULTIPLIER + ...;
operand = memory[ j ] % OP_LOCATION_MULTIPLIER;
operation = memory[ j ] / OP_LOCATION_MULTIPLIER;
I'm new to programming, I'm not the best, so I'm going for simplicity. Also this is an SML program. Anyway, this IS a homework assignment and I'm wanting a good grade on this. So I was looking for input and making sure this program will do what I'm hoping they are looking for. Anyway, here are the instructions: Write SML (Simpletron Machine language) programs to accomplish each of the following task:
A) Use a sentinel-controlled loop to read positive number s and compute and print their sum. Terminate input when a neg number is entered.
B) Use a counter-controlled loop to read seven numbers, some positive and some negative, and compute + print the avg.
C) Read a series of numbers, and determine and print the largest number. The first number read indicates how many numbers should be processed.
Without further a due, here is my program. All together.
int main()
{
const int READ = 10;
const int WRITE = 11;
const int LOAD = 20;
const int STORE = 21;
const int ADD = 30;
const int SUBTRACT = 31;
const int DIVIDE = 32;
const int MULTIPLY = 33;
const int BRANCH = 40;
const int BRANCHNEG = 41;
const int BRANCHZERO = 41;
const int HALT = 43;
int mem[100] = {0}; //Making it 100, since simpletron contains a 100 word mem.
int operation; //taking the rest of these variables straight out of the book seeing as how they were italisized.
int operand;
int accum = 0; // the special register is starting at 0
int j;
// This is for part a, it will take in positive variables in a sent-controlled loop and compute + print their sum. Variables from example in text.
memory [0] = 1010;
memory [01] = 2009;
memory [02] = 3008;
memory [03] = 2109;
memory [04] = 1109;
memory [05] = 4300;
memory [06] = 1009;
j = 0; //Makes the variable j start at 0.
while ( true )
{
operand = memory[ j ]%100; // Finds the op codes from the limit on the memory (100)
operation = memory[ j ]/100;
//using a switch loop to set up the loops for the cases
switch ( operation ){
case 10: //reads a variable into a word from loc. Enter in -1 to exit
cout <<"\n Input a positive variable: ";
cin >> memory[ operand ]; break;
case 11: // takes a word from location
cout << "\n\nThe content at location " << operand << "is " << memory[operand]; break;
case 20:// loads
accum = memory[ operand ]; break;
case 21: //stores
memory[ operand ] = accum; break;
case 30: //adds
accum += mem[operand]; break;
case 31: // subtracts
accum-= memory[ operand ]; break;
case 32: //divides
accum /=(memory[ operand ]); break;
case 33: // multiplies
accum*= memory [ operand ]; break;
case 40: // Branches to location
j = -1; break;
case 41: //branches if acc. is < 0
if (accum < 0)
j = 5;
break;
case 42: //branches if acc = 0
if (accum == 0)
j = 5;
break;
case 43: // Program ends
exit(0); break;
}
j++;
}
return 0;
}
So, seems I do have a problem
somewhere in my coding. Whenever I run
the program and input a variable, it
always returns the same answer.."The
content at location 76 is 0."
Look at what your program is doing:
memory [0] = 1010; /* Read from user and store at address 10 */
memory [01] = 2009; /* Read garbage into acc from address 9 */
memory [02] = 3008; /* Add whatever garbage is in address 8 into accumulator */
memory [03] = 2109; /* Store garbage from accumulator into address 9 */
memory [04] = 1109; /* Print the contents of address 9, which is garbage */
memory [05] = 4300; /* Stop */
memory [06] = 1009; /* Read from user and store in address 9 */
So... yeah. To debug something like this, you just need to print out all the pertinent variables of your program to see whether they're what you think they are. For example, in case 10 you could have done cout << "10: operand is " << operand << endl; and then in case 11 you could have done cout << "11: operand is " << operand << endl; and you would have seen right away that the operand was 10 in the first instruction, 9 in the second, and 8 in the 3rd.
If you want to guarantee that memory always starts with the value 0, write a for loop (you can change your declaration to do it but there are subtleties you'd need to learn):
for( int i = 0; i < sizeof(memory); ++i ) { memory[i] = 0; }
Here's working program that adds 2 values the user enters and prints the result:
memory [0] = 1009;
memory [1] = 1008;
memory [2] = 2009;
memory [3] = 3008;
memory [4] = 2109;
memory [5] = 1109;
memory [6] = 4300;
As I suggested yesterday in your original question. I believe you may have an error in case 10 and 11 hard coded to modify the "stack pointer" (j) to 5 if I'm reading your code correctly.
The case statements for switch (operation) don't match your opcode constants (e.g. READ = 10, BRANCH = 40). (This has been fixed in your example)
For debugging at least having a default statement in the switch to catch unknown operations is recommended to catch mistakes.
Added:
I'd also suggest printing the operation and operand as they are being executed, to help you follow the Simpletron's program execution.
You still have not fixed the usage of leading zeros of memory addresses. The C/C++ compiler interprets the leading zero as meaning octal (base 8) number system.
Your example code as posted does not even compile. Please edit and fix the variable name usage (hint: mixing mem and memory).
Code fixes removed.
The values in the switch statement are incorrect. The operation values will be 10, 11, 20, 21 etc. not 1, 2, 3 etc as you check for in your cases. Which means none of your code gets executed as you don't have cases for these numbers.
Good luck!