I'm trying to build a simple BIN -> HEX converter using a class, I would like to save it later in a header file for eventual need <.<" .
It kinda works. Kinda because I have some output, but I cannot understand what is happening when it prints X. Why Am I getting those else exceptions ? I should get only 4 bit combinations..
I'm trying to learn. Sorry for eventual stupid code.
#include <iostream>
#include <bitset>
class Hash{
private:
char stringa[150];
int byteCount=0;
public:
//call to get a string
void getStringa(){
char temp_char;
std::cout << "Write a string and press enter to continue" << std::endl;
for(unsigned int i = 0; i < 150; i++){
temp_char = std::cin.get();
if(temp_char == '\n'){
stringa[i] = '\0';
byteCount = i;
break;
}
stringa[i] = temp_char;
}
}
char nibbleToHEX(std::bitset<4> x){
char HEX;
if(x == 0000) return HEX = '0';
else if (x == 0001) return HEX = '1';
else if (x == 0010) return HEX = '2';
else if (x == 0011) return HEX = '3';
else if (x == 0100) return HEX = '4';
else if (x == 0101) return HEX = '5';
else if (x == 0110) return HEX = '6';
else if (x == 0111) return HEX = '7';
else if (x == 1000) return HEX = '8';
else if (x == 1001) return HEX = '9';
else if (x == 1010) return HEX = 'A';
else if (x == 1011) return HEX = 'B';
else if (x == 1100) return HEX = 'C';
else if (x == 1101) return HEX = 'D';
else if (x == 1110) return HEX = 'E';
else if (x == 1111) return HEX = 'F';
else return 'X';
}
//call to encode string to 256 binary digits and then go HEX a nibble at a time
void encodeStringa(){
std::cout << "converting |" << stringa << "| to binary: \n";
char HEXSTRINGA[64];
for(unsigned int i = 0; i < 150; i++){
if(stringa[i] == '\0') break;
std::bitset<4> x(stringa[i]);
std::cout << x;
HEXSTRINGA[i] = nibbleToHEX(x);
}
std::cout << std::endl;
std::cout << "You used " << byteCount << " bytes.\n";
std::cout << "You still have " << 64-byteCount << " bytes." << std::endl;
std::cout << "Converted string in HEX form: " << HEXSTRINGA << std::endl;
}
};
int main() {
Hash BCHAIN;
BCHAIN.getStringa();
BCHAIN.encodeStringa();
return 0;
}
Some test IO is:
**Teststring**
0100010100110100001101000010100111100111
XXBXBXA3XF
X is an error at least for what I am trying to do..
I don't get it why, I would expect random combination of 4 bits for some chars.. because I only have 15 combinations with 4 bits. Not an X ... is an overflow issue?
You can do much simpler by simply combining four subsequent characters into a number:
char const* const digits = "0123456789abcdefg"; // or upper case, if you prefer
for(auto i = x; i < byteCount; i += 4)
// ^: to be considered later!
{
unsigned int n
= (stringa[i + 0] == '1') << 3
| (stringa[i + 1] == '1') << 2
| (stringa[i + 2] == '1') << 1
| (stringa[i + 3] == '1') << 0;
HEXSTRING[pos++] = digits[n];
}
So far I did not consider a letter not being either '0' or '1' – leaving this to you!
One thing yet open is the number of input digits not being a multiple of 4!
Well, above I started with some unspecified x, remember? I'd prefer filling up the lacking digits with leading zeros, i.e. considering e.g. 110011 as 00110011:
size_t pos = 0;
unsigned int n = 0;
size_t offset = byteCount % 4;
if(offset != 0)
{
size_t o = offset - 1
for(size_t i = 0; i <= o; ++i)
{
n |= (stringa[i] == '1') << (o - i);
}
HEX_STRING[pos++] = digits[n];
}
And now we start above loop at this offset:
for(auto i = offset; i < byteCount; i += 4)
{
// ...
}
For this working correctly you yet need to set the byteCount appropriately. You do so if the string is shorter than 150 characters. You might set it to 150 before entering the loop – but what, if input string is even longer? You'd get inappropriate results!
You might want to prefer reading into a std::string instead!
std::string stringa;
std::cin >> stringa;
This will stop reading a string at the first whitespace occurring. You might instead use std::getline if you want to handle input like 00 11 as well (you'd do so with your current solution, but you do not skip the whitespace).
With either approach you then can use stringa.length() instead of byteCount, the latter being dropped entirely.
The numbers you wrote in nibbleToHEX are not binary but decimal (not beginning with zero) and octal (beginning with zero)
If you want to use binary string, you should use std::bitset:
#include <string>
char nibbleToHEX(std::bitset<4> x){
char HEX;
if(x == std::bitset<4>(std::string("0000"))) return HEX = '0';
else if (x == std::bitset<4>(std::string("0001"))) return HEX = '1';
else if (x == std::bitset<4>(std::string("0010"))) return HEX = '2';
else if (x == std::bitset<4>(std::string("0011"))) return HEX = '3';
else if (x == std::bitset<4>(std::string("0100"))) return HEX = '4';
else if (x == std::bitset<4>(std::string("0101"))) return HEX = '5';
else if (x == std::bitset<4>(std::string("0110"))) return HEX = '6';
else if (x == std::bitset<4>(std::string("0111"))) return HEX = '7';
else if (x == std::bitset<4>(std::string("1000"))) return HEX = '8';
else if (x == std::bitset<4>(std::string("1001"))) return HEX = '9';
else if (x == std::bitset<4>(std::string("1010"))) return HEX = 'A';
else if (x == std::bitset<4>(std::string("1011"))) return HEX = 'B';
else if (x == std::bitset<4>(std::string("1100"))) return HEX = 'C';
else if (x == std::bitset<4>(std::string("1101"))) return HEX = 'D';
else if (x == std::bitset<4>(std::string("1110"))) return HEX = 'E';
else if (x == std::bitset<4>(std::string("1111"))) return HEX = 'F';
else return 'X';
}
Or 0b prefix (since C++14):
char nibbleToHEX(std::bitset<4> x){
char HEX;
if(x == 0b0000) return HEX = '0';
else if (x == 0b0001) return HEX = '1';
else if (x == 0b0010) return HEX = '2';
else if (x == 0b0011) return HEX = '3';
else if (x == 0b0100) return HEX = '4';
else if (x == 0b0101) return HEX = '5';
else if (x == 0b0110) return HEX = '6';
else if (x == 0b0111) return HEX = '7';
else if (x == 0b1000) return HEX = '8';
else if (x == 0b1001) return HEX = '9';
else if (x == 0b1010) return HEX = 'A';
else if (x == 0b1011) return HEX = 'B';
else if (x == 0b1100) return HEX = 'C';
else if (x == 0b1101) return HEX = 'D';
else if (x == 0b1110) return HEX = 'E';
else if (x == 0b1111) return HEX = 'F';
else return 'X';
}
My recommendation is using an array (string literal is an array):
char nibbleToHEX(std::bitset<4> x){
unsigned long idx = x.to_ulong();
if (idx < 16) {
return "0123456789ABCDEF"[idx];
} else {
return 'X';
}
}
Also you should initialize HEXSTRINGA in the function encodeStringa, or some junk may be printed after the hash:
char HEXSTRINGA[64] = "";
Related
I am making a function that validates a user input is a grid reference, between A0 and J9 (a 10 x 10 grid).
I can validate the integer part fine, but am wondering how to validate the alphabetical part, without saying for example:
if(Column == 'A' || Column == 'a' || Column == 'B' ....)
In a similar fashion to saying if int Row < 10.
Also, is there a way to convert to a single character, such as stoi for string to integer?
Here is my functions code, thank you.
void InputLocation(){
bool still_prompt = true;
while (still_prompt)
{
std::string answer;
std::cout << "Enter a grid location from A0 to J9" << std::endl;
std::getline(std::cin, answer);
std::string Column = answer.substr(0, 1);
std::string Row = answer.substr(1, 1);
if (answer.length() > 2 || answer.length() < 2){
std::cerr << "Location input must be of length 2 characters.\n";
continue;
}
else{ // If input has length 2, then get to this stage
try{
int intRow = std::stoi(Row);
if (intRow < 0 || intRow > 9){
std::cerr << "Row number must be between 0 and 9. \n";
continue;
}
}
catch (...){
std::cerr << "Second character of location input must be integer. \n";
continue;
}
}still_prompt = false;
}
}
Individual characters can be treated as numbers, so this is pretty simple to do! For example:
bool test(char character) {
return 'a' <= character && character <= 'j';
}
This function tests if a character is between 'a' and 'j'. This works because under the hood, 'a' and 'j' are just numbers. You can even see what numbers they are just by printing out the value:
int a_value = 'a'; // chars can be implictly converted to int
int j_value = 'j';
std::cout << "value of 'a'": << a_value << '\n';
std::cout << "value of j'j": << j_value << '\n';
Putting it all together. We can check if something is in the correct range just by doing a comparison. The following function will check if a character is within the range a through j.
bool testInRange(char c) {
return ('a' <= c && c <= 'j') || ('A' <= c && c <= 'J');
}
We can also write a function to convert it into an index on the grid:
int charToGridIndex(char c) {
if('A' <= c && c <= 'J')
{
return c - 'A';
}
else if('a' <= c && c <= 'j')
{
return c - 'a';
}
else
{
// Return -1 to indicate an invalid character
return -1;
}
}
Here,
charToGridIndex('a') == 0
charToGridIndex('b') == 1
charToGridIndex('c') == 2
charToGridIndex('d') == 3
charToGridIndex('e') == 4
charToGridIndex('f') == 5
charToGridIndex('g') == 6
charToGridIndex('h') == 7
charToGridIndex('i') == 8
charToGridIndex('j') == 9
I have an array of unsigned char which contains hex values. I would like to show it in the logs and in order to do it I need to convert it into a string.
Obviously if I directly try to use the character array as a string I get gibberish as is it interpreted as ASCII (e.g., it will be rendered as: "\xfê)Z+’\x2". Ideally I want to show the raw hex values without them being interpreted.
I have tried to copy it into a string but have not been successful. I am going to present what I have tried and the results that I got:
//My starting data type is unsigned char *
unsigned char* index = Block_data.Index;
//I convert it to const char* since most functions I could find for this type of
//conversion require a const char *, if this step can be avoided: I will do that
const char* indexc1 = reinterpret_cast<const char*>(index);
char outVal[9]; //allocate target buffer space
sprintf_s(outVal, "%9x", indexc1); //copy to target. This manages to copy the
// address of indexc1 and not its contents
sprintf_s(outVal, "%9x", *indexc1); //This gets one character from the
// address
sscanf_s(indexc1, "%9x", outVal); //This gets empty string
I feel that the answer may be quite simple but after some research I tried the above and have not been successful. Since I am running out of ideas (I tried few similar things as above) I am turning to the community for some help on this.
Your question is not very clear but I am assuming you want to build a string showing , in hex, the values of the first four bytes pointed to by index.
The code could be:
char outVal[9];
sprintf(outVal, "%02X%02X%02X%02X", index[0], index[1], index[2], index[3]);
Do not try this with char * pointer, that could lead to undefined behaviour. It relies on index being unsigned char *.
If you want to print many more bytes, then you can switch to a loop, for example:
std::vector<char> outVal( 2 * len + 1 );
for (size_t i = 0; i < len; ++i)
sprintf(&outVal[i * 2], "%02X", index[i]);
// OutputDebugString(&outVal[0]);
Assuming you have arbitrary characters that you want represented as hex, you can simply use makeString() and appendChar() from the following complete test program:
#include <iostream>
#include <iomanip>
#include <string>
#include <sstream>
#include <cstring>
// Append a single character as two-digit hex string.
void appendChar(std::stringstream &ss, const char *pref, const char ch) {
ss << pref
<< std::setfill('0')
<< std::setw(2)
<< std::hex
<< static_cast<unsigned int>(ch & 0xff);
}
// Construct a hex string from buffer.
std::string makeString(const char * const buff, size_t slen = 0) {
std::stringstream ss;
// Zero-length means C-style string.
if (slen == 0)
slen = strlen(buff);
// Process each byte in character array.
if (slen > 0) {
appendChar(ss, "", buff[0]);
for (size_t i = 1; i < slen; ++i)
appendChar(ss, " ", buff[i]);
}
return ss.str();
}
// Rudimentary test code.
int main() {
std::cout << makeString("hello", 4) << std::endl;
std::cout << makeString("\x3\x1\x4\x1\x5\x9\xff") << std::endl;
}
It's probably not that hard to do that on a higher level (if this isn't a performance intensive application):
std::string hexToString(unsigned char c)
{
std::string res = "";
if (c >= 0xF0)
{
res += "F";
c -= 0xF0;
}
else if (c >= 0xE0)
{
res += "E";
c -= 0xE0;
}
else if (c >= 0xD0)
{
res += "D";
c -= 0xD0;
}
else if (c >= 0xC0)
{
res += "C";
c -= 0xC0;
}
else if (c >= 0xB0)
{
res += "B";
c -= 0xB0;
}
else if (c >= 0xA0)
{
res += "A";
c -= 0xA0;
}
else if (c >= 0x90)
{
res += "9";
c -= 0x90;
}
else if (c >= 0x80)
{
res += "8";
c -= 0x80;
}
else if (c >= 0x70)
{
res += "7";
c -= 0x70;
}
else if (c >= 0x60)
{
res += "6";
c -= 0x60;
}
else if (c >= 0x50)
{
res += "5";
c -= 0x50;
}
else if (c >= 0x40)
{
res += "4";
c -= 0x40;
}
else if (c >= 0x30)
{
res += "3";
c -= 0x30;
}
else if (c >= 0x20)
{
res += "2";
c -= 0x20;
}
else if (c >= 0x10)
{
res += "1";
c -= 0x10;
}
else
{
res += "0";
}
if (c >= 0xF)
{
res += "F";
c -= 0xF;
}
else if (c >= 0xE)
{
res += "E";
c -= 0xE;
}
else if (c >= 0xD)
{
res += "D";
c -= 0xD;
}
else if (c >= 0xC)
{
res += "C";
c -= 0xC;
}
else if (c >= 0xB)
{
res += "B";
c -= 0xB;
}
else if (c >= 0xA)
{
res += "A";
c -= 0xA0;
}
else if (c >= 0x9)
{
res += "9";
c -= 0x90;
}
else if (c >= 0x8)
{
res += "8";
c -= 0x8;
}
else if (c >= 0x7)
{
res += "7";
c -= 0x7;
}
else if (c >= 0x6)
{
res += "6";
c -= 0x6;
}
else if (c >= 0x5)
{
res += "5";
c -= 0x5;
}
else if (c >= 0x4)
{
res += "4";
c -= 0x4;
}
else if (c >= 0x3)
{
res += "3";
c -= 0x3;
}
else if (c >= 0x2)
{
res += "2";
c -= 0x2;
}
else if (c >= 0x1)
{
res += "1";
c -= 0x10;
}
else res += "0";
return res;
}
This is like a rather hacked interpretation, but it's quite reliable.
I am writing an operating system in C and assembly, and in implementing the EXT2 file system I have encountered a problem. I need to convert FOUR bytes of hexadecimal to decimal in c. An example would be to convert 00 00 01(10000) to 65536.I need to convert to decimal,because parsing the super block requires all values to be in decimal. Most specifically the ext2 fs I'm working on is here:
#include "ext2.h"
#include <stdlib.h>
long hex2dec(unsigned const char *hex){
long ret = 0;
int i = 0;
while(hex[i] != 0){
//if(hex[i] >= 0x00 && hex[i] <= 0x09)
// ret+=(10 * i) * hex[i];
}
//kprintf("\n");
return ret;
}
char *strsep(char *buf,int offset,int num){
char *ret = malloc(1024);
int j = 0;
int i = offset;
int end = (offset + num);
int i1 = 0;
while(i1 < num){
///kstrcat(ret,&buf[i]);
ret[i1] = buf[i];
i++;
i1++;
}
return ret;
}
int get_partition(partnum){
if(partnum > 4)
return -1;
//int i = (12 * partnum);
int i = 0;
if(partnum == 1)
i = 190;
else if(partnum == 2)
i = 206;
else if(partnum == 3)
i = 222;
else
i = 190;
int ret = 0;
char *buf = malloc(1024);
ata_read_master(buf,1,0x00);
ret = buf[(i + 2)];
return ret;
}
int _intlen(int i){
int ret = 0;
while(i){
ret++;
i/=10;
}
return ret;
}
int _hex2int(char c){
if(c == '0')
return 0;
else if(c == '1')
return 1;
else if(c == '2')
return 2;
else if(c == '3')
return 3;
else if(c == '4')
return 4;
else if(c == '5')
return 5;
else if(c == '6')
return 6;
else if(c == '7')
return 7;
else if(c == '8')
return 8;
else if(c == '9')
return 9;
else if(c == 'A')
return 10;
else if(c == 'B')
return 11;
else if(c == 'C')
return 12;
else if(c == 'D')
return 13;
else if(c == 'E')
return 14;
else if(c == 'F')
return 15;
}
int hex2int(char c){
int i = c;
}
int comb(const char *str,int n){
int i = 0;
int ret = 0;
while(i < n){
//if(str[i] == 0x01)
// kprintf("(:");
/*int j = str[i];
int k = 0;
int m = 0;
if(j < 10)
j*=10;
else
while(j > 0){
k+=(10 ^ (_intlen(j) - m)) * j % 10;
m++;
j/=10;
}
//kprintf("%d",j);
//if(j == 1)
// kprintf("(:");*/
i++;
}
//ret = (char)ret;
ret = (char)str
int ret = 0;
int i = 0;
char *s = malloc(1024);
/*while(i < n){
//kstrcat(s,&((char*)buf[i]));
n++;
}*/
return ret;
//kprintf("\n");
//return ret;
}
struct ext2_superblock *parse_sblk(int partnum){
int i = get_partition(partnum);
if(i > 0)
kprintf("[EXT2_SUPERBLOCK]Found partition!\n");
else
i = 0;
struct ext2_superblock *ret;
struct ext2_superblock retnp;
char *buf = malloc(1024);
int i1 = 0;
//char *tmpbuf = malloc(4);
/*if(i != 0)
ata_read_master(buf,((i * 4)/256),0x00);
else{
kprintf("[WRN]: Looking for superblock at offset 1024\n");
ata_read_master(buf,4,0x00);
}*/
ata_read_master(buf,2,0x00);
const char *cmp = strsep(buf,0,4);
retnp.ninode = comb(strsep(buf,0,4),4);
retnp.nblock = comb(strsep(buf,4,4),4);
retnp.nsblock = comb(strsep(buf,8,4),4);
retnp.nunallocb = comb(strsep(buf,12,4),4);
retnp.nunalloci = comb(strsep(buf,16,4),4);
retnp.supernum = comb(strsep(buf,20,4),4);
retnp.leftshiftbs = comb(strsep(buf,24,4),4);
retnp.leftshiftfs = comb(strsep(buf,28,4),4);
retnp.numofblockpg= comb(strsep(buf,32,4),4);
// retnp.numofffpbg= comb(strsep(buf,36,4));
retnp.numoffpbg = comb(strsep(buf,36,4),4);
retnp.numofinpbg = comb(strsep(buf,40,4),4);
retnp.lastmount = comb(strsep(buf,44,4),4);
retnp.lastwrite = comb(strsep(buf,48,4),4);
retnp.fsckpass = comb(strsep(buf,52,2),2);
retnp.fsckallow = comb(strsep(buf,54,2),2);
retnp.sig = comb(strsep(buf,56,2),2);
retnp.state = comb(strsep(buf,58,2),2);
retnp.erroropp = comb(strsep(buf,60,2),2);
retnp.minorpor = comb(strsep(buf,52,2),2);
retnp.ptimefsck = comb(strsep(buf,64,4),4);
retnp.inter = comb(strsep(buf,68,4),4);
retnp.osid = comb(strsep(buf,72,4),4);
retnp.mpv = comb(strsep(buf,76,4),4);
retnp.uid = comb(strsep(buf,80,2),2);
retnp.gid = comb(strsep(buf,82,2),2);
ret = &retnp;
return ret;
i1 = 0;
}
If there is anyway of avoiding conversion and successfully implementing ext2 I would be glad to hear it. I would prefer it to be in c,but assembly is also okay.
If you have this:
const uint8_t bytes[] = { 0, 0, 1 };
and you want to consider that the bytes of a (24-bit) unsigned integer in little-endian order, you can convert to the actual integer using:
const uint32_t value = ((uint32_t) bytes[2] << 16) | (bytes[1] << 8) | bytes[0];
This will set value equal to 65536.
You can use std::istringstream or sscanf instead of writing your own.
char const * hex_text[] = "0x100";
const std::string hex_str(hex_text);
std::istringstream text_stream(hex_str);
unsigned int value;
text_stream >> std::ios::hex >> value;
std::cout << "Decimal value of 0x100: " << value << "\n";
Or using sscanf:
sscanf(hex_text, "0x%X", &value);
std::cout << "Decimal value of 0x100: " << value << "\n";
A good idea is to search your C++ reference for existing functions or search the internet, before writing your own.
To roll your own:
unsigned int hex2dec(const std::string& hex_text)
{
unsigned int value = 0U;
const unsigned int length = hex_text.length();
for (unsigned int i = 0; i < length; ++i)
{
const char c = hex_text[i];
if ((c >= '0') && (c <= '9'))
{
value = value * 16 + (c - '0');
}
else
{
c = toupper(c);
if ((c >= 'A') && (c <= 'Z'))
{
value = value * 16 + (c - 'A') + 10;
}
}
}
return value;
}
To convert to use C-style character strings, change the parameter type and use strlen for the length.
I have a string of different 3 letter words:
catdogmattabratliematdogatt
I need to assign each of the words with an alphabet and print the final string.
cat: P, dog: A, mat: T, tab: I, rat: E, lie: O, att: L
so my output should be:
PATIEOTAL
I tried using a switch statement but it doesn't allow me to enter 3 characters together.
Use a map<string, char> to do the following:
map<string, char> wordToChar;
// Load wordToChar appropriately; c++11 you can use an initializer list for simplicity
for (int i = 0; i < strLen; i += 3)
{
string str;
str.push_back(theString[i]);
str.push_back(theString[i+1]);
str.push_back(theString[i+2]);
cout << wordToChar[theString] << endl;
}
It seems I can use three char in a switch-statement! It is also not just me but a standard features called "multicharacter literals" (see 2.14.3 [lex.ccon] paragraph 1; the type of these beasts is int). It isn't that I would advise anybody to use this hack but it works although the characters may need to be reversed in the computation depending on the Endianess of the system (I'm not sure about that detail). Here is a complete example (although the input wants separate words rather than one string which needs to be separated):
#include <iostream>
#include <string.h>
int main(int ac, char* av[])
{
typedef unsigned char u;
for (int i(1); i != ac; ++i) {
if (strlen(av[i]) == 3)
{
std::cout << std::hex;
int value(u(av[i][2])
+ 256u * (u(av[i][1])
+ 256u * u(av[i][0])));
switch (value) {
default:
std::cout << "option not found!: '" << av[i] << "'\n";
break;
case 'cat': std::cout << 'P'; break;
case 'dog': std::cout << 'A'; break;
case 'mat': std::cout << 'T'; break;
case 'tab': std::cout << 'I'; break;
case 'rat': std::cout << 'E'; break;
case 'lie': std::cout << 'O'; break;
case 'att': std::cout << 'L'; break;
}
}
}
std::cout << '\n';
}
Since you asked about using switch statements, I assume that it would be acceptable to have a hard-coded list of 3-letter words and their corresponding letters. In that case, I would solve this problem using a sequence of if-then-else statements, each attempting to match the characters of the 3-letter words. Alternatively, you could use nested switch statements, but the syntax makes that solution a bit harder to read IMO.
static char match_word(std::string const &str, std::size_t offset)
{
char ret = '?';
if (str[offset + 0] == 'c' && str[offset + 1] == 'a' && str[offset + 2] == 't') {
ret = 'P';
}
else if (str[offset + 0] == 'd' && str[offset + 1] == 'o' && str[offset + 2] == 'g') {
ret = 'A';
}
else if (str[offset + 0] == 'm' && str[offset + 1] == 'a' && str[offset + 2] == 't') {
ret = 'T';
}
else if (str[offset + 0] == 't' && str[offset + 1] == 'a' && str[offset + 2] == 'b') {
ret = 'I';
}
else if (str[offset + 0] == 'r' && str[offset + 1] == 'a' && str[offset + 2] == 't') {
ret = 'E';
}
else if (str[offset + 0] == 'l' && str[offset + 1] == 'i' && str[offset + 2] == 'e') {
ret = 'O';
}
else if (str[offset + 0] == 'a' && str[offset + 1] == 't' && str[offset + 2] == 't') {
ret = 'L';
}
return ret;
}
Then you can test the code with a simple main function like this:
int main(int argc, char **argv)
{
if (argc != 2) {
std::cerr << "USAGE: " << argv[0] << " ENCODED" << std::endl;
return 1;
}
else {
std::string example(argv[1]);
for (std::size_t idx = 0; idx < example.size(); idx += 3) {
std::cout << match_word(example, idx);
}
std::cout << std::endl;
return 0;
}
}
Then just run the program with the encoded string as the one and only argument like this:
$ ./a.out catdogmattabratliematdogatt
PATIEOTAL
#include <iostream>
#include <string>
using namespace std;
// Turns a digit between 1 and 9 into its english name
// Turn a number into its english name
string int_name(int n)
{
string digit_name;
{
if (n == 1) return "one";
else if (n == 2) return "two";
else if (n == 3) return "three";
else if (n == 4) return "four";
else if (n == 5) return "five";
else if (n == 6) return "six";
else if (n == 7) return "seven";
else if (n == 8) return "eight";
else if (n == 9) return "nine";
return "";
}
string teen_name;
{
if (n == 10) return "ten";
else if (n == 11) return "eleven";
else if (n == 12) return "twelve";
else if (n == 13) return "thirteen";
else if (n == 14) return "fourteen";
else if (n == 14) return "fourteen";
else if (n == 15) return "fifteen";
else if (n == 16) return "sixteen";
else if (n == 17) return "seventeen";
else if (n == 18) return "eighteen";
else if (n == 19) return "nineteen";
return "";
}
string tens_name;
{
if (n == 2) return "twenty";
else if (n == 3) return "thirty";
else if (n == 4) return "forty";
else if (n == 5) return "fifty";
else if (n == 6) return "sixty";
else if (n == 7) return "seventy";
else if (n == 8) return "eighty";
else if (n == 9) return "ninety";
return "";
}
int c = n; // the part that still needs to be converted
string r; // the return value
if (c >= 1000)
{
r = int_name(c / 1000) + " thousand";
c = c % 1000;
}
if (c >= 100)
{
r = r + " " + digit_name(c / 100) + " hundred";
c = c % 100;
}
if (c >= 20)
{
r = r + " " + tens_name(c /10);
c = c % 10;
}
if (c >= 10)
{
r = r + " " + teen_name(c);
c = 0;
}
if (c > 0)
r = r + " " + digit_name(c);
return r;
}
int main()
{
int n;
cout << endl << endl;
cout << "Please enter a positive integer: ";
cin >> n;
cout << endl;
cout << int_name(n);
cout << endl << endl;
return 0;
}
I Keep getting this Error code:
intname2.cpp: In function âstd::string
int_name(int)â:
intname2.cpp:74: error: no match for
call to â(std::string) (int)â
intname2.cpp:80: error: no match for
call to â(std::string) (int)â
intname2.cpp:86: error: no match for
call to â(std::string) (int&)â
intname2.cpp:91: error: no match for
call to â(std::string) (int&)â
You are using digit_name, teen_name, etc as functions, when they are defined as variables. If you want to use them like that, you need to define them before your int_name function like this:
string digit_name(int n)
{
if (n == 1) return "one";
else if (n == 2) return "two";
else if (n == 3) return "three";
else if (n == 4) return "four";
else if (n == 5) return "five";
else if (n == 6) return "six";
else if (n == 7) return "seven";
else if (n == 8) return "eight";
else if (n == 9) return "nine";
return "";
}
Timothy, it looks like you're confused about the requirements of the assignment. Please make sure you understand the requirements, because at this stage it doesn't look like you know what's expected of you. You're trying to move the body of one function into the body of another function and that's simply not possible to do.
Please post the exact words that your teacher used in order for us to give you proper advice on the question.
Here are some tips for you:
If your teacher has covered switch statements then use switch statements.
Check if your teacher is not asking you to do function declarations.
Check if your teacher is not asking you to put the functions in libraries (a header file and source file).
OK scrap the tips... given your teacher's requirements I think it might look a little bit like this:
string int_name(int n)
{
int c = n; // the part that still needs to be converted
string r; // the return value
if (c >= 1000)
{
r = int_name(c / 1000) + " thousand";
c = c % 1000;
}
if (c >= 100)
{
// If you have covered switch statements then it will look like this
string digitName;
switch(c/100) // <- instead of calling digit_name(c/100), we call switch(c/100)
{
case 1:
// assign the digit name
digitName = "one";
break;
case 2:
//... fill here with your own code
break;
case 3:
//... fill here with your own code
break;
// write all the cases through 9
default:
digitName = "";
break;
}
// in the result string use the digitName variable
// instead of calling the digit_name function
r = r + " " + digitName + " hundred";
c = c % 100;
}
if (c >= 20)
{
r = r + " " + tens_name(c /10);
c = c % 10;
}
if (c >= 10)
{
r = r + " " + teen_name(c);
c = 0;
}
if (c > 0)
r = r + " " + digit_name(c);
return r;
}
Note that I'm using a switch statement, but if you your teacher hasn't shown you switch statements yet, then you can still use if/else statements:
string int_name(int n)
{
int c = n; // the part that still needs to be converted
string r; // the return value
if (c >= 1000)
{
r = int_name(c / 1000) + " thousand";
c = c % 1000;
}
if (c >= 100)
{
// declare a digitName
string digitName;
// declare a temporary value
int temp = c/100;
if(1 == temp)
{
// assign the digit name
digitName = "one";
}
else if( 2 == temp )
{
digitName = "two";
}
else if( 3 == temp )
{
// fill in the rest
}
else if( 4 == temp )
{
// fill in the rest
}
// write all the other else if statements
else
{
digitName = "":
}
// in the result string use the digitName variable
// instead of calling the digit_name function
r = r + " " + digitName + " hundred";
c = c % 100;
}
if (c >= 20)
{
r = r + " " + tens_name(c /10);
c = c % 10;
}
if (c >= 10)
{
r = r + " " + teen_name(c);
c = 0;
}
if (c > 0)
r = r + " " + digit_name(c);
return r;
}
You're going to have to take the first example with digit_name and apply it to tens_name and teen_name functions.
WARNING:
In reality you don't want to repeat the same code and clutter a single function with a bunch of code that could be in its own function. You ALWAYS want to break out repeating code into functions... if she's asking you to repeat code when you can use functions then you should be concerned. Ask your teacher if this is what she REALLY wants you to do!