C++ - Inserting and Extracting Characters from an Integer Array - c++

For example:
char mem[100000];
int reg[8];
mem[36] = 'p'; // add char p to our 36th index of our char array
reg[3] = (int)mem[36]; // store value of mem[36] into reg[3]
Now I want to print the char value at index 3 of that int array.
So far my thought process has lead me to code such as this:
char *c = (char*)reg[3];
cout << *c << endl;
But I am still getting weird values and characters when trying to print it out.
From my understanding, an integer is equal to 4 characters. Since a character is technically a byte and an integer is 4 bytes.
So I am storing a character into my integer array as 4 bytes, but when I pull it out, there is garbage data since the character I inserted is only one byte compared to the index being 4 bytes in size.

Have you tried this:
char mem[100000];
int reg[8];
mem[36] = 'p'; // add char p to our 36th index of our char array
reg[3] = (int)mem[36]; // store value of mem[36] into reg[3]
char txt[16];
sprintf(txt, "%c", reg[3]); // assigns the value as a char to txt array
cout<<txt<<endl;
This prints out the value 'p'

You shouldn't be using pointers here; it's sufficient to work with chars:
char c = reg[3];
cout << c << endl;
Note, however, that you could lose information when trying to stuff an int into a char variable.

I do not see what is your problem. You store the char into int var. You want to print it back - just cast the value to char and print it
#include <iostream>
int main()
{
char mem[100];
int reg[8];
mem[36] = 'p'; // add char p to our 36th index of our char array
// store value of mem[36] into reg[3]
reg[3] = mem[36];
// store value of mem[36] into reg[4] with cast
reg[4] = static_cast<int>(mem[36]);
std::cout << static_cast<char>(reg[3]) << '\n';
std::cout << static_cast<char>(reg[4]) << '\n';
}
/****************
* Output
$ ./test
p
p
*/

Related

C++: Why is this code giving me memory issues / undefined behavior?

A bit of Background if you are interested...
The next piece of code is an attempt at implementing a Packet Error Code generator using Cyclical Redundancy Check (CRC-15). This is used to detect communication data corruption. A more detailed introduction is unnecessary.
Code and Issues
init_PEC15_Table function is a lookup-table generator.
pec15 function takes a data input, calculates the address of the solution and find the result in the lookup-table.
data is a char array that I have assigned a value of 1 to. This is going to be passed to pec15.
Now, I found that by just reordering the cout commands, the value of "stuffed pec", which is the output I am interested in, changes. By reading online I understood that this could be due to the memory stack unexpectedly changing in a way that affects the result registers and that this could be due to out-of-bounds operations on other variables. Am I mistaken in my understanding?
Now, I am a beginner and this is very daunting. I might have made some gross mistakes that I am not aware of so please feel free to tear the code to shreds.
Also, if it matters, this code is running on an mbed LPC1768.
#include <iostream>
using namespace std;
unsigned short pec15Table[256];
const unsigned int CRC15_POLY = 0x4599;
void init_PEC15_Table() // Cyclical Redundancy Check lookup table generator function
{
unsigned short rem;
for (int i = 0; i < 256; i++)
{
rem = i << 7;
for (int bit = 8; bit > 0; --bit)
{
if (rem & 0x4000)
{
rem = ((rem << 1));
rem = (rem ^ CRC15_POLY);
}
else
{
rem = ((rem << 1));
}
}
pec15Table[i] = rem & 0xFFFF;
// cout << hex << pec15Table [i] << endl;
}
}
unsigned short pec15(char* data, int lengt = 16) //Takes data as an input,
{
int rem, address;
rem = 16;//PEC seed (intial PEC value)
for (int i = 0; i < lengt; i++)
{
address = ((rem >> 7) ^ data[i]) & 0xff;//calculate PEC table address
rem = (rem << 8) ^ pec15Table[address];
}
return (rem * 2);//The CRC15 has a 0 in the LSB so the final value must be multiplied by 2
}
int main()
{
init_PEC15_Table(); //initialise pec table
char data = (short) 0x1 ; // Write 0x1 to char array containing the data 0x1
char* dataPtr = &data; // Create a pointer to that array
unsigned short result = pec15(dataPtr); //Pass data pointer to pec calculator
cout << "data in: " << (short) *dataPtr << endl; //Print the short representation of the char data array (Outputs 1)
cout << "size of data: " << sizeof(*dataPtr) << endl; //Print the size of the char array (Outputs 1)
cout << "stuffed pec: " << result << endl; //Print the output of the pec calculation
return 0;
}
The code you've written here does not sync with the comments you've written:
char data = (short) 0x1 ; // Write 0x1 to char array containing the data 0x1
char* dataPtr = &data; // Create a pointer to that array
The first line does not write anything to a character array. Rather, it creates a char variable whose numeric value is 1. As a note, the cast to short here isn't needed and has no effect - did you mean to write something else?
The second line does not create a pointer to an array. Rather, it creates a pointer to the data variable. You could potentially think of this as a pointer to an array of length one, but that's probably not what you meant to do.
The two above lines don't by themselves do anything bad. The next line, however, is a real problem:
unsigned short result = pec15(dataPtr); //Pass data pointer to pec calculator
Remember that pec15 has a second argument that's supposed to denote the length of the data passed in. Since you didn't specify it, it defaults to 16. However, your dataPtr pointer only points to a single char value, not 16 char values, so this results in undefined behavior.
I'm not sure how to fix this because I don't have a good sense for the intent behind your code. Did you mean to make a sixteen-element array? Did you mean to create an array filled with the value 0x1? The correct fix here depends on the answer to that question.
Try:
unsigned short result = pec15(dataPtr, 1);
otherwise lengt is 16 (has default value). I'd also advice to remove default value of lengt, as it makes little sense in context of pec15 function.

How to use char data type as a number rather than a character?

When I use the char datatype to add two numbers, I get the sum of the ASCII code of the characters and not the numbers itself. When I researched on the internet, various sites say that the char type can indeed be used to handle one byte numbers. But in reality, I get the sum of ASCII values. Why is this happening? Below is just a sample code which illustrates the problem:
uint8_t rows,cols; //uint8_t is just a typedef for char
cin >> rows;
cout << rows + 1 << endl;
When people talk about "one-byte numbers", they're talking about 8-bit values, ranging from -128 to 127 for a char, or 0 to 255 for an unsigned char, also known as octets. These can be converted directly to larger integer types and to floats:
char eight_bit = 122;
float floating_point = eight_bit; // = 122.0
If you're trying to convert a digit value such as '1' into the numeric value it represents, there's stoi:
#include <string>
int ctoi(char c) {
std::string temp;
temp.push_back(c);
return std::stoi(temp);
}
Chars store the ASCII equivalent of a character as an integer.
For example
char value = 'A' // == int 65
It's best you use a short integer to store numbers, but if you really want to, you can do something like this;
char value1 = '2';
char value2 = '5';
char sum = (value1 + value2) - '0'; // int value of sum would be 7
When you use char, you use signed 8 bit data type (mostly).
And you get "sum of ASCII" only because std::cout is programmed to display char as ASCII character.
Try
cout << stratic_cast<int16_t>(rows) + 1 << endl;
And you will see that you get the 'number' rather than an 'ASCII character'.
NOTE
uint8_t is not (or probably should not be) char since char is defined as signed data type while uint* stands for unsigned.

Base encoding impossible with leading 0?

I am trying to encode a string to base36.
static char *decode(unsigned long long value)
{
char base36[37] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char buffer[14];
unsigned int offset = sizeof(buffer);
buffer[--offset] = '\0';
do {
buffer[--offset] = base36[value % 36];
} while (value /= 36);
return _strdup(&buffer[offset]);
}
int main()
{
char original[8] = "0XDX3A1";
unsigned long long encoded = _strtoui64(original, NULL, 36);
char *decoded = decode(encoded);
cout << "Original: " << original << " Decoded: " << decoded << endl;
return 0;
}
The problem here is, while those functions work OK: if the string I am trying to encode has a leading 0 the decoded string is one character (or more) less than the original.
How to deal with this?
If you decode the string "01234" as a base-16 string (for example), you get the integer value 4660 (0x1234) -- exactly the same integer value you get by decoding the string "1234" or "00001234" as a base-16 string. By converting the string to an integer, you've thrown away any information about leading zeros. You've also discarded any information about uppercase vs. lowercase letters, assuming that A and a represent the same value.
Converting that integer value back to a string isn't going to restore that leading 0 unless you add it explicitly. And if you want to add that leading 0 (or multiple 0s) if and only if they were present in the original string, you're going to have to store that information somehow.
Introduce a new variable in your main, called zeroCount in main
Introduce a 2nd argument to function decode, called zeroCount
Count the amount of leading zeroes in the original to the zeroCount in main
Place zeroes to buffer[--offset] until you consume all the zeroCount before the return
Like this:
static char *decode( unsigned long long value, int zeroCount )
{ // introduced zeroCount argument there ^
char base36[37] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char buffer[14];
unsigned int offset = sizeof( buffer );
buffer[--offset] = '\0';
do {
buffer[--offset] = base36[value % 36];
} while ( value /= 36 );
while ( zeroCount-- ) buffer[--offset] = '0'; // <-- added this
return strdup( &buffer[offset] );
}
int main( )
{
char original[8] = "0XDX3A1";
unsigned long long encoded = _strtoui64( original, NULL, 36 );
int zeroCount = 0; // added
for ( int i = 0; i < sizeof original && original[i] == '0'; i++ ) // these
zeroCount++; // three
char *decoded = decode( encoded, zeroCount ); // <-- called along with zeroCount
cout << "Original: " << original << " Decoded: " << decoded << endl;
return 0;
}
Since there isn't any apparent rule for the 0 appending behaviour you desire, I had to assume that you'd like to have exact many leading zeroes that the original had.
You're calling a function tat takes a string containing a representation of a numeric value and converts it to an unsigned long long . The two string representations '00007' and '7' are both converted to numeric 7, and the leading zeroes are lost.
IF you want, eg, 00000036 to covert to 00000010 in base 36, you'll just have to count the zeroes you want and then decide how many of them to replace ( would it depend on the relative lengths of base 10 and base 36 strings? )
But it seems poor practice in the conversion functions. better, in my mind, to add leading zeroes when outputting the value. As many have commented, they have no significance and should not be part of the conversion logic.
I'd suggest you to create a wrapper around your method, and pass it a length parameter.
Eg.
char * wrap_base36enc(int out_len, unsigned long long value){
char pre_str[MAX_VAL]="", *ans = base36enc(value);
len -= strlen(ans);
while(len--){
strcat(pre_str,"0");
}
strcat(pre_str,ans);
return pre_str;
}

C++ pointer to char arithmetic

If I add 1 to a pointer, the actual value added will be the size of the type that the pointer points to right? For example:
int* num[5];
cout << *num << ", " << *(num + 2) << endl;
This will print the value stored at num[1] and at num[2],
so num + 2 is actually num + 2*sizeof(int) if I'm not wrong.
Now, if I initialize an array of pointers to char to string literals, like this one:
char* ch[5] =
{
"Hi",
"There",
"I,m a string literal"
};
This can be done because a string literal like "hi" represents the address of its first character, in this case 'h'. Now my question is how can I write something like:
cout << *(ch + 2);
and get "I,m a string literal" as the output?
Since the pointer points to char, shouldn't adding 2 to the pointer actually be (ch + 2*sizeof(char)) ? giving me the output 'There' ?
Does it have something to do with cout? Does cout search the memory of the pointed to values to see if it finds '\0's recognizing the contents of the pointed to values as strings and then modifying pointer arithmetic? But then adding 1 to a pointer to char pointing to strings would mean adding different number of bytes (instead of the size of a char) everytime, since a string can be any size. Or am I totally wrong? I'm sorry I am new to C++, and programming in gerenal.
The array isn't storing chars, it's storing char *s. Hence saying ch + 2 will be equivalent to ch + 2*sizeof(char *). You then dereference that, which is pointing to "I'm a string literal".
Your initial example shows the confusion:
int* num[5];
cout << *num << ", " << *(num + 2) << endl;
This is an array of pointers-to-int. Hence, *(num + 2) will be *(num + 2*sizeof(int *)), not 2*sizeof(int). Let's demonstrate this with a small program:
#include <iostream>
int main()
{
int *num[3];
int x, y, z;
x = 1;
y = 2;
z = 3;
num[0] = &x;
num[1] = &y;
num[2] = &z;
std::cout << *(num + 2) << "\n";
}
This will print out a memory address (like 0x22ff28) because it is holding pointers, not values.
In C and C++, arrays and pointers are very similar (many books claim they are exactly the same. This is not -quite- true, but it is true in a lot of situations).
Your first example should be int num[5]. Then *(num + 2) (which is equivalent to num[2]) will be equivalent to *(num + 2*sizeof(int). Hopefully this clears up your confusion somewhat.
"If I add 1 to a pointer, the actual value added will be the size of the type that the pointer points to right?"
There's no guarantee in the C++ Standard that a pointer is the number of the byte of some memory where the pointer points to. If you add an integer n to a pointer, the result is a pointer to the nth next element in that array:
int iarr[10];
int* pi = iarr; // pi points to iarr[0]
int* pi2 = pi+2; // pi2 points to iarr[2]
What you get when you look at, e.g. int repr = (int)pi; is not defined by the C++ Standard.
What will happen on the most popular platforms/implementations, is that
(int)pi2 == ((int)pi) + 2*sizeof(int)
When you have arrays of pointers, the exact same thing happens:
int* piarr[10];
int** ppi = piarr; // ppi points to iarr[0]
int** ppi2 = piarr+2; // ppi2 points to iarr[2]
Note that the type of piarr is array of 10 pointer to int, therefore the elements of that array have the type pointer to int. A pointer to an element of that array consequently has the type pointer to pointer to int.
char* ch[5] is an array of 5 pointers to char.
"Hello" etc. are (narrow) string literals. A (narrow) string literal is an array of n const char, where n is the length of the string plus 1 (for the terminating \0 character). Arrays can be implicitly converted to pointers to the first element of the array, this is what happens here:
char* ch[5] =
{
"Hi",
"There",
"I,m a string literal"
};
The array ch contains three pointer to char. As those have been obtained by converting arrays to pointers, each of them points to the first element of an array of char: The pointer ch[0] (the first element of the array ch) points to the first element of the array "Hi", ch[1] points to the first element of "There" and so on.
Note there's also a conversion involved from const char to char, which is deprecated and should be avoided. The better form would be:
char const* ch[5] =
{
"Hi",
"There",
"I,m a string literal"
};
The expression *(ch + 2) is interpreted as follows:
ch names that array (see above)
ch + 2 implicitly converts ch from array of 3 pointers to char to pointer to pointer to char, a pointer pointing to the first element of the array ch. The type of this expression therefore is pointer to pointer to char.
ch + 2 makes the pointer from the last step now point to the second next element; it pointed to the first element of ch, so it now points to the third element of the array ch.
*(ch + 2) finally, the * dereferences the pointer and "fetches" the object pointed to. The pointer created by ch + 2 points to the 3rd element of the array ch, therefore, this expression resolves into the third element of the array ch. The type of the expression now is pointer to char.
The result of the expression is passed to std::cout::operator<<. As the type of the expression is pointer to char, cout will print that string: the third element of the array ch.
In C, a character is represented by the datatype char. It can hold any ASCII character and it ranges from 0 to 255. Moreover it uses a single byte of size.
A string, however, is represented by char*, which technically is an array of chars. There's a difference. A char is not the same as a char*. The former stores a single character, and the latter stores a memory direction which corresponds to the offset of the string.
Now, in your example, ch is not a char* but a char**. This is, it is an array of an array of chars, or better said, an array of strings. If we dereference ch once, as in *ch, we will get the first string: Hi. If we dereference it twice, as in **ch, we will get the first character of the first string: H. So, we can start working with pointer arithmetics!
cout << *(ch + 2) will output I,m a string literal
cout << **(ch + 1) will output T (first character of second string)
cout << *(*ch + 1) will output i (second character of first string)
Keep on working with these examples to understand better how characters and strings are output! It's all about pointer arithmetics!
Does it have something to do with cout?
No:
const char* cstrings[5] =
{
"Hi",
"There",
"I,m a string literal"
};
const char** x = cstrings + 2;
cout << *x << endl;
.
.
But what can be confusing is that the << operator works differently when given a pointer to a cstring--instead of outputting the address, it outputs the string. Here is an example:
int x = 10;
int* pint = &x;
const char* pstr = "hello";
cout << pint << endl << pstr << endl;
--output:--
0x7fff5fbff85c //hexidecimal string representation of an integer
hello
Since the pointer points to char,
1) The literal strings are stored in your array as pointers. That's why the type of the array is pointer.
2) Pointers are adresses in memory, which are just integers.
3) So your array of pointers is really an array of integers.

Conversion from Integer to BCD

I want to convert the integer (whose maximum value can reach to 99999999) in to BCD and store in to array of 4 characters.
Like for example:
Input is : 12345 (Integer)
Output should be = "00012345" in BCD which is stored in to array of 4 characters.
Here 0x00 0x01 0x23 0x45 stored in BCD format.
I tried in the below manner but didnt work
int decNum = 12345;
long aux;
aux = (long)decNum;
cout<<" aux = "<<aux<<endl;
char* str = (char*)& aux;
char output[4];
int len = 0;
int i = 3;
while (len < 8)
{
cout <<"str: " << len << " " << (int)str[len] << endl;
unsigned char temp = str[len]%10;
len++;
cout <<"str: " << len << " " << (int)str[len] << endl;
output[i] = ((str[len]) << 4) | temp;
i--;
len++;
}
Any help will be appreciated
str points actually to a long (probably 4 bytes), but the iteration accesses 8 bytes.
The operation str[len]%10 looks as if you are expecting digits, but there is only binary data. In addition I suspect that i gets negative.
First, don't use C-style casts (like (long)a or (char*)). They are a bad smell. Instead, learn and use C++ style casts (like static_cast<long>(a)), because they point out where you are doing things that are dangeruos, instead of just silently working and causing undefined behavior.
char* str = (char*)& aux; gives you a pointer to the bytes of aux -- it is actually char* str = reinterpret_cast<char*>(&aux);. It does not give you a traditional string with digits in it. sizeof(char) is 1, sizeof(long) is almost certainly 4, so there are only 4 valid bytes in your aux variable. You proceed to try to read 8 of them.
I doubt this is doing what you want it to do. If you want to print out a number into a string, you will have to run actual code, not just reinterpret bits in memory.
std::string s; std::stringstream ss; ss << aux; ss >> s; will create a std::string with the base-10 digits of aux in it.
Then you can look at the characters in s to build your BCD.
This is far from the fastest method, but it at least is close to your original approach.
First of all sorry about the C code, I was deceived since this started as a C questions, porting to C++ should not really be such a big deal.
If you really want it to be in a char array I'll do something like following code, I find useful to still leave the result in a little endian format so I can just cast it to an int for printing out, however that is not strictly necessary:
#include <stdio.h>
typedef struct
{
char value[4];
} BCD_Number;
BCD_Number bin2bcd(int bin_number);
int main(int args, char **argv)
{
BCD_Number bcd_result;
bcd_result = bin2bcd(12345678);
/* Assuming an int is 4 bytes */
printf("result=0x%08x\n", *((int *)bcd_result.value));
}
BCD_Number bin2bcd(int bin_number)
{
BCD_Number bcd_number;
for(int i = 0; i < sizeof(bcd_number.value); i++)
{
bcd_number.value[i] = bin_number % 10;
bin_number /= 10;
bcd_number.value[i] |= bin_number % 10 << 4;
bin_number /= 10;
}
return bcd_number;
}