example code:
const char* list[] = {"Elem_E", "Elem_T", "Elem_R", "Turtle", "Rabbit"};
const char ** patterns=0;
.
.
.
bool sec_run = false;
patterns = list;
process_data(patterns, sec_run);
process_data function:
process_data(const char **& pattern, bool sec_run){
.
.
some_variable=0;
for(int i; i < num_patterns;++i){
if(!sec_run){
some_variable = *pattern[i];
}
else{
if(/* list element contains "_" */)continue;
some_variable= /*letter after "_" */
}
if(some_variable == 'E') multiplier = 0;
else if(some_variable == 'T') multiplier = 1;
else if(some_variable == 'R') multiplier = 2;
}
}
So there is the base of what I'm trying to do. I cannot change signature for process_data. To start i do not get how some_variable = *pattern[i]; returns E,T, or R, and I cannot figure out how to iteratively access the full elements in the list. ie "Elem_E" to check for underscore and parse off the E.
I have little background in C++, but have used C numerous times. I am having a difficult time finding visual representation for char **& to help with based understanding of what is going on here, if you can point in the direction of a good tutorial with visual that will also suffice.
Sorry for confusion, forgot quotes in the list.
In C++, reading a parameter passed by reference (with the &) works the same as reading a parameter passed by value (without the &). The difference happens when you assign to the parameter. If the parameter was passed by value then the assignment is only visible inside the function but if it was passed by reference the assignment will be visible outside.
int mynumber = 0;
void foo(int &x)
{
printf("%d\n", x); //prints 0;
x = 10;
}
int main()
{
foo(mynumber);
printf("%d\n", mynumber); // prints 10
}
The equivalent to this in plain C would be to make the x parameter into a pointer and add the required *s and &s:
int mynumber = 0;
void foo(int *x)
{
printf("%d\n", *x);
*x = 10;
}
int main()
{
foo(&mynumber);
printf("%d\n", mynumber); // prints 10
}
Coming back to your code, I don't really know how to solve all your problems (what does the constant Elem_E mean? Is your list NULL terminated or is there a length stored somewhere?) but what I can say is that as long as you don't want to change the patterns global variable from inside process_data, using a char **& will be the same as using a char **.
I don't know how some_variable and multiplier will be used, but I made these changes to calculate them for each string in the list. The variable sec_run is not required in this approach. If no match is found, some_variable and multiplier are set to default values of '\0' and -1.
Output:
item=Elem_E some_variable=E multiplier=0
item=Elem_T some_variable=T multiplier=1
item=Elem_R some_variable=R multiplier=2
item=Turtle some_variable= multiplier=-1
item=Rabbit some_variable= multiplier=-1
Code:
void process_data(const char **& pattern, int num_patterns)
{
const char * item;
for (int i = 0; i < num_patterns; ++i)
{
item = pattern[i];
if ( item == NULL ) continue;
char some_variable = '\0'; // set to default for no match
int multiplier = -1; // set to default for no match
int len = strlen(item);
for (int j = 0; j < len; ++j)
{
if (item[j] == '_' && j + 1 < len)
some_variable = item[j + 1]; /*letter after "_" */
}
if (some_variable == 'E') multiplier = 0;
else if (some_variable == 'T') multiplier = 1;
else if (some_variable == 'R') multiplier = 2;
cout << "item=" << item << " some_variable=" << some_variable << " multiplier=" << multiplier << endl;
}
}
void pattern_test()
{
const char* list[] = { "Elem_E", "Elem_T", "Elem_R", "Turtle", "Rabbit" };
const char ** patterns = list;
// trick to calculate array length
// length of entire array divided by length of one element
int num_length = sizeof(list) / sizeof(list[0]);
process_data(patterns, num_length);
}
Related
this is my first time posting a question. I was hoping to get some help on a very old computer science assignment that I never got around to finishing. I'm no longer taking the class, just want to see how to solve this.
Read in an integer (any valid 64-bit
integer = long long type) and output the same number but with commas inserted.
If the user entered -1234567890, your program should output -1,234,567,890. Commas
should appear after every three significant digits (provided more digits remain) starting
from the decimal point and working left toward more significant digits. If the number
entered does not require commas, do not add any. For example, if the input is 234 you
should output 234. The input 0 should produce output 0. Note in the example above
that the number can be positive or negative. Your output must maintain the case of the
input.
I'm relatively new to programming, and this was all I could come up with:
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
long long n;
cout << "Enter an integer:" << endl;
cin >> n;
int ones = n % 10;
int tens = n / 10 % 10;
int hund = n / 100 % 10;
int thous = n / 1000 % 10;
int tthous = n / 10000 % 10;
cout << tthous << thous << "," << hund << tens << ones << endl;
return 0;
}
The original assignment prohibited the use of strings, arrays, and vectors, so please refrain from giving suggestions/solutions that involve these.
I'm aware that some sort of for-loop would probably be required to properly insert the commas in the necessary places, but I just do not know how to go about implementing this.
Thank you in advance to anyone who offers their help!
Just to give you an idea how to solve this, I've maiden a simple implementation. Just keep in mind that is just a simple example:
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
long long n = -1234567890;
if ( n < 0 )
cout << '-';
n = abs(n);
for (long long i = 1000000000000; i > 0; i /= 1000) {
if ( n / i <= 0 ) continue;
cout << n / i ;
n = n - ( n / i) * i;
if ( n > 0 )
cout << ',';
}
return 0;
}
http://coliru.stacked-crooked.com/a/150f75db89c46e99
The easy solution would be to use ios::imbue to set a locale that would do all the work for you:
std::cout.imbue(std::locale(""));
std::cout << n << std::endl;
However, if the restraints don't allow for strings or vectors I doubt that this would be a valid solution. Instead you could use recursion:
void print(long long n, int counter) {
if (n > 0) {
print(n / 10, ++counter);
if (counter % 3 == 0) {
std::cout << ",";
}
std::cout << n%10;
}
}
void print(long long n) {
if (n < 0) {
std::cout << "-";
n *= -1;
}
print(n, 0);
}
And then in the main simply call print(n);
A small template class comma_sep may be a solution, the usage may be as simple as:
cout << comma_sep<long long>(7497592752850).sep() << endl;
Which outputs:
7,497,592,752,850
Picked from here:
https://github.com/arloan/libimsux/blob/main/comma_sep.hxx
template <class I = int, int maxdigits = 32>
class comma_sep
char buff[maxdigits + maxdigits / 3 + 2];
char * p;
I i;
char sc;
public:
comma_sep(I i, char c = ',') : p(buff), i(i), sc(c) {
if (i < 0) {
buff[0] = '-';
*++p = '\0';
}
}
const char * sep() {
return _sep(std::abs(i));
}
private:
const char * _sep(I i) {
I r = i % 1000;
I n = i / 1000;
if (n > 0) {
_sep(n);
p += sprintf(p, "%c%03d", sc, (int)r);
*p = '\0';
} else {
p += sprintf(p, "%d", (int)r);
*p = '\0';
}
return buff;
}
};
The above class handles only integeral numbers, float/double numbers need to use a partial specialized version:
template<int maxd>
class comma_sep<double, maxd> {
comma_sep<int64_t, maxd> _cs;
char fs[64];
double f;
public:
const int max_frac = 12;
comma_sep(double d, char c = ',') : _cs((int64_t)d, c) {
double np;
f = std::abs(modf(d, &np));
}
const char * sep(int frac = 3) {
if (frac < 1 || frac > max_frac) {
throw std::invalid_argument("factional part too too long or invalid");
}
auto p = _cs.sep();
strcpy(fs, p);
char fmt[8], tmp[max_frac+3];
sprintf(fmt, "%%.%dlf", frac);
sprintf(tmp, fmt, f);
return strcat(fs, tmp + 1);
}
};
The two above classes can be improved by adding type-traits like std::is_integral and/or std::is_floating_point, though.
My problem is that the variable 'scoreA' should be the accumulation of all the values generated during each iteration of the for loop. However, I am not getting the accumulated value and get only the value at the final iteration. Could someone Kindly help me out as I am new to C++. I have defined scoreA outside the for loop so my understanding is that the value of scoreA should be the accumulated value for all the iterations. But my guess is that it is being reassigned to 0 because of which it is unable to accumulate the value.
#include<iostream>
#include<map>
#include<string>
using namespace std;
map<string,int> Score_Scheme;
string StringA = "aaaa";
int Score_Compute(string StringA);
int Base_case_A(int lenA);
int main ()
{
Score_Scheme["ac"] = -1;
Score_Scheme["ag"] = -2;
Score_Scheme["at"] = -1;
Score_Scheme["a-"] = -3;
Score_Scheme["cg"] = -3;
Score_Scheme["ct"] = -2;
Score_Scheme["c-"] = -4;
Score_Scheme["gt"] = -2;
Score_Scheme["g-"] = -2;
Score_Scheme["t-"] = -1;
Score_Scheme["--"] = 0;
Score_Scheme["aa"] = 5;
Score_Scheme["cc"] = 5;
Score_Scheme["gg"] = 5;
Score_Scheme["tt"] = 5;
Score_Scheme["ca"] = -1;
Score_Scheme["ga"] = -2;
Score_Scheme["ta"] = -1;
Score_Scheme["-a"] = -3;
Score_Scheme["gc"] = -3;
Score_Scheme["tc"] = -2;
Score_Scheme["-c"] = -4;
Score_Scheme["tg"] = -2;
Score_Scheme["-g"] = -2;
Score_Scheme["-t"] = -1;
int len_StringA = StringA.size ();
cout<<"length of A is:"<<len_StringA<<"\n";
Base_case_A(len_StringA);
return 0;
}
int Base_case_A(int lenA)
{
int scoreA = 0;
for(int i = 0;i<lenA;i++)
{
char x[2];
x[0] = StringA[i];
x[1] = '-';
scoreA=scoreA+Score_Compute(x);
cout<<i<<":"<<scoreA<<"\n";
}
cout<<scoreA<<"\n";
return 0;
}
int Score_Compute(string stringA)
{
return Score_Scheme[stringA];
}
Score_Compute() takes a std::string as input, but when the loop calls Score_Compute(x), x is a char[2] containing 2 char values neither of which are a null terminator.
When a char[] is passed as-is to a std::string, the char[] decays to char*, which std::string then assumes to be null-terminated, which yours is not.
So, the std::string that Score_Compute() receives will be wrong, usually containing random data after the characters you did specify (assuming the code doesn't just crash altogether while searching for a null terminator that doesn't exist), and so it will not match any entries in your std::map, causing Score_Compute() to return 0.
To fix the logic, you need to change the declaration of x to char x[3]; and then add x[2] = '\0'; before converting to std::string:
char x[3]; // <-- fix this!
x[0] = StringA[i];
x[1] = '-';
x[2] = '\0'; // <-- add this!
Otherwise, you have to specify the correct length when converting to std::string:
Score_Compute(string(x, 2));
Alternatively, simply change x to be a std::string to begin with:
string x(2, '\0');
x[0] = StringA[i];
x[1] = '-';
Or:
string x;
s.resize(2);
x[0] = StringA[i];
x[1] = '-';
Or:
string x = " -";
x[0] = StringA[i];
I am a C++ newbie.
Context: I found this third-party snippet of code that seems to work, but based on my (very limited) knowledge of C++ I suspect it will cause problems. The snippet is as follows:
int aVariable;
int anInt = 1;
int anotherInt = 2;
int lastInt = 3;
aVariable = CHAIN(anInt, anotherInt, lastInt);
Where CHAIN is defined as follows (this is part of a library):
int CHAIN(){ Map(&CHAIN, MakeProcInstance(&_CHAIN), MAP_IPTR_VPN); }
int _CHAIN(int i, int np, int p){ return ASMAlloc(np, p, &chainproc); }
int keyalloc[16384], kpos, alloc_locked, tmp[4];
int ASMAlloc(int np, int p, alias proc)
{
int v, x;
// if(alloc_locked) return 0 & printf("WARNING: you can declare compound key statements (SEQ, CHAIN, EXEC, TEMPO, AXIS) only inside main() call, and not during an event.\xa");
v = elements(&keyalloc) - kpos - 4;
if(v < np | !np) return 0; // not enough allocation space or no parameters
Map(&v, p); Dim(&v, np); // v = params array
keyalloc[kpos] = np + 4; // size
keyalloc[kpos+1] = &proc; // function
keyalloc[kpos+2] = kpos + 2 + np; // parameters index
while(x < np)
{
keyalloc[kpos+3+x] = v[x];
x = x+1;
}
keyalloc[kpos+3+np] = kpos + 3 | JUMP;
x = ASMFind(kpos);
if(x == kpos) kpos = kpos + np + 4;
return x + 1 | PROC; // skip block size
}
int ASMFind(int x)
{
int i, j, k; while(i < x)
{
k = i + keyalloc[i]; // next
if(keyalloc[i] == keyalloc[x]) // size
if(keyalloc[i+1] == keyalloc[x+1]) // proc
{
j = x-i;
i = i+3;
while(keyalloc[i] == keyalloc[j+i]) i = i+1; // param
if((keyalloc[i] & 0xffff0000) == JUMP) return x-j;
}
i = k;
}
return x;
}
EDIT:
The weird thing is that running
CHAIN(aVariable);
effectively executes
CHAIN(anInt, anotherInt, lastInt);
Somehow. This is what led me to believe that aVariable is, in fact, a pointer.
QUESTION:
Is it correct to store a parametrized function call into an integer variable like so? Does "aVariable" work just as a pointer, or is this likely to corrupt random memory areas?
You're calling a function (through an obfuscated interface), and storing the result in an integer. It might or might not cause problems, depending on how you use the value / what you expect it to mean.
Your example contains too many undefined symbols for the reader to provide any better answer.
Also, I think this is C, not C++ code.
I have written a program that sets up a client/server TCP socket over which the user sends an integer value to the server through the use of a terminal interface. On the server side I am executing byte commands for which I need hex values stored in my array.
sprint(mychararray, %X, myintvalue);
This code takes my integer and prints it as a hex value into a char array. The only problem is when I use that array to set my commands it registers as an ascii char. So for example if I send an integer equal to 3000 it is converted to 0x0BB8 and then stored as 'B''B''8' which corresponds to 42 42 38 in hex. I have looked all over the place for a solution, and have not been able to come up with one.
Finally came up with a solution to my problem. First I created an array and stored all hex values from 1 - 256 in it.
char m_list[256]; //array defined in class
m_list[0] = 0x00; //set first array index to zero
int count = 1; //count variable to step through the array and set members
while (count < 256)
{
m_list[count] = m_list[count -1] + 0x01; //populate array with hex from 0x00 - 0xFF
count++;
}
Next I created a function that lets me group my hex values into individual bytes and store into the array that will be processing my command.
void parse_input(char hex_array[], int i, char ans_array[])
{
int n = 0;
int j = 0;
int idx = 0;
string hex_values;
while (n < i-1)
{
if (hex_array[n] = '\0')
{
hex_values = '0';
}
else
{
hex_values = hex_array[n];
}
if (hex_array[n+1] = '\0')
{
hex_values += '0';
}
else
{
hex_values += hex_array[n+1];
}
cout<<"This is the string being used in stoi: "<<hex_values; //statement for testing
idx = stoul(hex_values, nullptr, 16);
ans_array[j] = m_list[idx];
n = n + 2;
j++;
}
}
This function will be called right after my previous code.
sprint(mychararray, %X, myintvalue);
void parse_input(arrayA, size of arrayA, arrayB)
Example: arrayA = 8byte char array, and arrayB is a 4byte char array. arrayA should be double the size of arrayB since you are taking two ascii values and making a byte pair. e.g 'A' 'B' = 0xAB
While I was trying to understand your question I realized what you needed was more than a single variable. You needed a class, this is because you wished to have a string that represents the hex code to be printed out and also the number itself in the form of an unsigned 16 bit integer, which I deduced would be something like unsigned short int. So I created a class that did all this for you named hexset (I got the idea from bitset), here:
#include <iostream>
#include <string>
class hexset {
public:
hexset(int num) {
this->hexnum = (unsigned short int) num;
this->hexstring = hexset::to_string(num);
}
unsigned short int get_hexnum() {return this->hexnum;}
std::string get_hexstring() {return this->hexstring;}
private:
static std::string to_string(int decimal) {
int length = int_length(decimal);
std::string ret = "";
for (int i = (length > 1 ? int_length(decimal) - 1 : length); i >= 0; i--) {
ret = hex_arr[decimal%16]+ret;
decimal /= 16;
}
if (ret[0] == '0') {
ret = ret.substr(1,ret.length()-1);
}
return "0x"+ret;
}
static int int_length(int num) {
int ret = 1;
while (num > 10) {
num/=10;
++ret;
}
return ret;
}
static constexpr char hex_arr[16] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
unsigned short int hexnum;
std::string hexstring;
};
constexpr char hexset::hex_arr[16];
int main() {
int number_from_file = 3000; // This number is in all forms technically, hex is just another way to represent this number.
hexset hex(number_from_file);
std::cout << hex.get_hexstring() << ' ' << hex.get_hexnum() << std::endl;
return 0;
}
I assume you'll probably want to do some operator overloading to make it so you can add and subtract from this number or assign new numbers or do any kind of mathematical or bit shift operation.
This is for a class so it has to use recursion, I've written a working code iteratively, but I can't get it to work in recursion and I'm really lost. I've been working on this for a week. Any guidance or suggestions at all would be extremely helpful.
This is my function, I need to take in the hexadecimal as a char pointer and output it's corresponding decimal. I'm constantly getting either stack overflow or memory allocation runtime errors, can anyone identify what's wrong and steer me in the right direction?
int hexToDecimal(const char *hex, int offset, int power){
if(offset >= 0){
hexChar = *(hex+offset);
if( isalpha(hexChar) ) {
hexChar = toupper(hexChar);
hexNum = hexChar - asciiCharOffset;
} else {
hexNum = hexChar - asciiIntOffset;
}
return hexToDecimal(hex, offset--, power++) + hexNum * (int)pow(16,power);
} else {
return 0;
}
}
I have not compiled it, but first glance tells me that the corresponding line should be:
return hexToDecimal(hex, offset-1, power+1) + hexNum * (int) pow(16,power-1);
Because in your case, you are calling yourself ad infinitum (being called with, lets say offset 6, if you pass offset-- it will still pass 6 because it will decrement after it gives the value to the function).
Also, the post-increment will give you undefined behavior for the call pow(16,power) later in the same expression, because (taking the example of power=6 again), it may be pow(16,6) or pow(16,7) depending on the compiler.
All that aside, there's also risk, that pow() will give you false (rounded down) value when converting to int (it may turnn out that pow(16,2) returns 255.9999999 and you end up with (int)255, there's ample evidence and solutions here on stackoverflow, just search for pow).
EDIT (in reply to comments):
Finally, introducing the magical printf debugger:
int hexToDecimal(const char *hex, int offset, int power){
if(offset >= 0){
char hexChar = *(hex+offset);
int hexNum,
recursed;
if( isalpha(hexChar) ) {
hexChar = toupper(hexChar);
hexNum = hexChar - asciiCharOffset;
}
else {
hexNum = hexChar - asciiIntOffset;
}
recursed= hexToDecimal(hexNum, offset-1, power+1);
printf("%d + %d * %d\n", recursed, hexNum, (int)pow(16,power-1));
return recursed + hexNum * (int)pow(16,power-1);
} else {
return 0;
}
}
You're using post-increment here:
return hexToDecimal(hex, offset--, power++)
Post-increment (and post-decrement) will increment/decrement the variable (i.e. it will actually change offset and power), but the inc/dec will happen after the variable is evaluated.
I.e.:
int i = 5;
std::cout << "i = " << i; // prints 'i = 5'
std::cout << "\ni = " << i++; // still prints 'i = 5' and then changes i to be 6
std::cout << "\ni = " << i; // prints 'i = 6'
You don't actually want to modify offset and power -- you want to pass a different value for these to the next hexToDecimal call.
You can catch these kind of mistakes if you make the method parameters const, i.e.:
int hexToDecimal(const char*hex, const int offset, const int power);
I recommend making parameters const when you have no intention to modify them. That way the compiler can help you catch a lot of common mistakes.
use predecrement in the the function argument . Use --offset in the argument.
if u use offset-- then intial value of offset is passed to function and then offset is decreased.
Here's one I wrote a LONG time ago... It's probably not the best or fastest approach, and could use some error checking, but I'll leave that as an exercise to the reader...
long GetValue(const char *pszStrVal)
{
long Retval = 0;
try {
char *p = (char*)pszStrVal;
if(p == NULL) return 0;
if(strstr(p, "0x")) {
p++;p++;
long x = strlen(p);
long pval = 1 << ((x-1)*4);
for(int y = 0;y < x;y++,pval = (pval >> 4))
{
int digit = 0;
switch(p[y])
{
case 'A':
case 'a':
digit = 10;
break;
case 'B':
case 'b':
digit = 11;
break;
case 'C':
case 'c':
digit = 12;
break;
case 'D':
case 'd':
digit = 13;
break;
case 'E':
case 'e':
digit = 14;
break;
case 'F':
case 'f':
digit = 15;
break;
default:
digit = p[y] - 0x30;
}
Retval += (pval * digit);
}
} else {
Retval = atoi(p);
}
}
catch(...)
{
Retval = 0;
}
return Retval;
}
Here's a simple solution that uses a second recursive function call. Hopefully it'll help you debug yours:
#include <stdio.h>
#include <ctype.h>
int h2d_rec(const char *hex, int d);
int h2d(const char *hex) {
return h2d_rec(hex, 0);
}
int h2d_rec(const char *hex, int d) {
char hexChar = *hex;
if (0==hexChar) {
return d;
}
int charNum;
if (isalpha(hexChar)) {
charNum = 10 + toupper(hexChar) - 'A';
} else {
charNum = hexChar - '0';
}
// Note d<<4 is the same as 16*d
return h2d_rec(hex+1, (d<<4) + charNum);
}
int main(int argc, const char **argv) {
const char *hex = "FF";
if (1<argc) {
hex = argv[1];
}
printf("%s in decimal is %d\n", hex, h2d(hex));
}
You might want to use long instead to handle bigger hex numbers.