Directions are here:
I'm supposed to convert the ASCII string in the exact same input buffer, which is in this case pt1.
Unfortunately for me, the loop is executed only once and hence my output buffer only contains the first short value.
I'm trying to convert the ASCII string into a Unicode 16-bit string. According to the directions, pt1 is supposed to point to an ASCII string.
Expected Output is on this link.
https://i.stack.imgur.com/COpXl.jpg
void Convert(unsigned short *pt1) {
// pt1 is a pointer to a null-terminated variable length ASCII string
// 0x30 0x31 0x32 0x00 (sentinel value)
unsigned char *pt2 = (unsigned char *)pt1;
unsigned char value = *pt2;
while (*pt2 != 0x00) {
value = *pt2;
*pt1 = (unsigned short)value;
pt2++;
pt1++;
}
*pt1 = 0x0000;
}
There are multiple problems:
Your conversion function does not produce anything visible for the caller: you store code point values into a local array and return to the caller. The compiler warns you that at least pt3 is set and not used, but a more advanced compiler would optimise away all code for this function without a side effect.
What is the API description for Convert? You seem to receive a pointer to an ASCII string disguised as a pointer to unsigned short, and it seems the conversion should be performed in place. If this is the actual requirement, it is a very bad idea. The function should receive a pointer to a destination array with type unsigned short *, a size_t specifying the number of elements of this array and a pointer to the source string, with type const char *.
How should bytes outside the ASCII range be handled? Is the source string encoded in a given code page? it is UTF-8 encoded? Should the function report an error?
From the EDIT, you seem to confirm the insane API requirement. Assuming there is enough space in the argument array, you should perform the conversion from the last byte to the first, thus avoiding stepping on your own toes:
void Convert(unsigned short *pt1) {
// pt1 is a pointer to a null-terminated variable length ASCII string
// with enough space to receive the converted value including a null terminator
unsigned char *pt2 = (unsigned char *)pt1;
size_t i;
// Compute the number of bytes
for (i = 0; pt2[i] != '\0'; i++)
continue;
// Convert the contents from right to left
// Assuming ISO8859-1 encoding for bytes outside the ASCII range
for (;;) {
pt1[i] = (unsigned short)pt2[i];
if (i-- == 0)
break;
}
}
Related
I am creating a simple encryption program.
I am adding chars to chars to create a new char.
As of now the new 'char' is often a represented by a '?'.
My assumption was that the char variable has a max sum and once it was passed it looped back to 0.
assumed logic:
if char a == 1 && char z == 255
then 256 should == a.
This does not apear to be the case.
This snippet adds a char to a char.
It often prints out something like:
for (int i = 0; i < half; ++i) {
halfM1[i] = halfM1[i] + halfP1[i];
halfM2[i] = halfM2[i] + halfP2[(half + i)];
}
printf("\n%s\n", halfM1 );
printf("%s\n", halfM2);
Returns:
a???
3d??
This snippet removes the added char and the strings go back to normal.
for (int i = 0; i < half; ++i) {
halfM1[i] = halfM1[i] - halfP1[i];
halfM2[i] = halfM2[i] - halfP2[(half + i)];
}
printf("\n%s\n", halfM1 );
printf("%s\n", halfM2);
returns:
messagepart1
messagepart2
The code technically works, but I would like the encryption to be in chars.
If question on why 'half' is everywhere.
The message and key are split in half so the first half and second half of message have separate encryption.
First of all, there is no such thing as "wraparound" for common char. A common char is a signed type in x86, and signed integers do not have wraparound. Instead the overflow leads to undefined behaviour. Additionally, the range of chars can be -128 ... 127, or even something
For cryptographic purposes you'd want to use unsigned chars, or even better, raw octets with uint8_t (<stdint.h>).
Second problem is that you're printing with %s. One of the possible 256 resulting characters is \0. If this gets into the resulting string, it will terminate the string prematurely. Instead of using %s, you should output it with fwrite(halfM1, buffer_size, 1, stdout). Of course the problem is that the output is still some binary garbage. For this purposes many Unix encryption programs will write to file, or have an option to output an ASCII-armoured file. A simple ASCII armouring would be to output as hex instead of binary.
The third is that there is an operation that is much better than addition/subtraction for cryptographic purposes: XOR, or halfM1[i] = halfM1[i] ^ halfP1[i]; - the beauty of which is that it is its own inverse!
Here is my buffer and can any one explain how can i store a hexadecimal value inside this and when i try to print buffer[0], it is printing 0 instead of 500. I am trying to fill an element of the buffer with the ID which is of 11bits, I know the char is of 1 byte i.e.,8 bits and it cannot store the value. i have other elements to be filled into buffer and they are of type char. So i cannot change the type of the buffer from char to int. How can I solve my problem.
char *buffer;
buffer = (char *)malloc(10*(sizeof(frameRd))); //frameRd is of 16bytes
buffer[0] = frameRd->id;
for(int i =1;i<15;i++)
{
buffer[i] = frameRd->data;
}
for(int i =0,i<16;i++)
{
printf("%4X",buffer[i]);
}
where frame->id = 0x500; when i print this value on console, it is printing buffer[0] as 0 and surely because
Since buffer is char*, buffer[0] is char. Therefore, the assignment
buffer[0] = frameRd->id;
means "truncate frameRd->id to char, and store the result in buffer[0]," i.e. exactly the effect that you are observing. Moreover, when you print buffer[0] with %4X, you print the value of buffer[0] alone, converted to int.
If you want to get an int or a whole struct into a char[] buffer, use memcpy:
// Do not cast results of malloc
buffer = malloc(10*(sizeof(frameRd)));
// Save id into the buffer at index 0
memcpy(&buffer[0], &frameRd->id, sizeof(frameRd->id));
// Pull id back
int tmpId;
memcpy(&tmpId, &buffer[0], sizeof(tmpId));
printf("%04x\n", tmpId);
Demo.
I need to do a RPC. I'm trying to encode the length of a function name followed by the name of the function.
Function name: say_hello
Function name length: 9
Encoded array: [9, 's', 'a', 'y', ..., 'l', 'l', 'o']
So far:
unsigned char* encode_int(unsigned char *buffer, int value) {
buffer[0] = value >> 24;
buffer[1] = value >> 16;
buffer[2] = value >> 8;
buffer[3] = value;
return buffer + 4;
}
char* function_name = "say_hello";
char* buffer[256];
buffer = encode_int(&buffer, strlen(function_name));
strcpy(buffer, function, strlen(function_name));
puts(buffer);
You have lots of problems with your code. I won't just give you a working solution but will point out the problems. The first thing is that the code obviously doesn't compile. You are passing an undefined variable function to strcpy and give too many arguments to strcpy. I'll assume you've just transcribed the program incorrectly. But even if you fix that you will get a few compiler warnings which, if heeded, would identify most of your problems.
You are passing the address of buffer rather than the buffer itself to encode_int.
You declare buffer as an array of char pointers. Looks like what you really want is an array of char.
You encode an int into the start of the buffer. And then you try to print it as a string (via puts). That's not going to work and will result in no output (as you have probably found). Because the int will have a 0 value in the first byte (as you have encoded it). This is a null terminator for a string and hence the blank output.
EDIT: Correction to point 3. You've actually incremented buffer by 4 (if everyting else was fixed). So the puts will only show the function name (again, if everything else was fixed). And you've effectively lost the function name length.
Put words into buffer like this
int len;
len=Strlen(word);
memcpy(buffer,&len,sizeof(Int));
strncpy (&buffer[sizeof (int)],word,len);
Change the puts line to read
printf("%d %s\n",buffer,&buffer[sizeof (int)]);
I am trying to store an integer in a char array. How can I do that? This is my approach (by casting it the int to a char) but it does not work. What am I missing?
#include <stdio.h>
int main(int argc, char** argv)
{
char cArray[10] = {};
// Store a character in the char array
cArray[5] = 'c';
printf("%c\n", cArray[5]);
// Store an integer in the char array
cArray[6] = (char) 0; // WHY DOES THIS NOT WORK???
printf("%c\n", cArray[6]);
}
Let's start with the basics.
For x86 architecture(assuming you use it) a char variable is stored in 1 byte and an int variable is stored in 4 bytes.
It is IMPOSSIBLE to store a random integer value in a char variable unless you have some compression schema and know that some integer values will not occur(no random!) in your program. No exceptions.
In your case, you want to store integers in a char array. There are four options:
1.If you want to store a random integer in this char array, then you should get the pointer to the index that you want to store the integer and cast it to an integer pointer and use it like that.
char mychars[10];
int * intlocation = (int*)(&mychar[5]);
*intlocation = 3632; // stores 3632
Beware that this will write to 4 bytes(4 char locations in your array) starting from the index you have specified. You should always check you are not going out of array.Also you should do the same casting for retrieving the value when needed.
2.If your values are between [0,255] or [-128,127] you can safely store your integers in a char since these ranges can be represented using a byte. Beware that char being signed or unsigned is implementation-dependent. Check this out!
mychars[5] = 54;
3.If your integer is just a digit, you can use the char representation of the digit.
mychars[5] = your_digit + 48; // 48 is the ascii code for '0'
4.If you want to store the string representation of your integer, then you should use itoa() and write each char of the resulting string to your array one by one. In that case, you should always check that you are not going out of array.
cArray[6] = (char) 0; // WHY DOES THIS NOT WORK???
printf("%c\n", cArray[6]);
This code attempts to print a character with the encoding 0; assuming ASCII, nothing will get displayed because there is no printable character associated with that code.
If you intend to store the ASCII code for the character '0' and print it, then you need to write
cArray[6] = 48; // same as writing cArray[6] = '0' (ASCII)
printf( "%c\n", cArray[6] );
This will print 0 to your console.
If, on the other hand, you want to store any arbitrary integer value1 to cArray[6] and display that value, then you need to use the %d conversion specifier:
cArray[6];
printf( "%d\n", cArray[6] );
1. That is, any integer that fits into the range of char, anyway
Normally, a computer exactly does what you tell it. The instruction DWIM (do what I mean) hasn't been invented yet.
cArray[6] = (char) 0; // WHY DOES THIS NOT WORK???
sets the index position 6, but
printf("%c\n", cArray[5]);
prints the index position 5.
I would like to add on to Seçkin Savaşçı's answer (in which you cast a char* pointer to somewhere in the char array to an int* pointer, allowing you to write an integer to the array by dereferencing the pointer).
You can also use bit-shifting:
#include <stdio.h>
int main() {
int first_int = 4892; // number larger than 127 (max. value of char)
int second_int = 99584; // same
// char array to hold two integers:
char array[8]; // ...assuming an integer size of 4 and char size of 1
// Now, assuming you are on a little endian system (in which the least
// significant bytes come first), you can add the two above integers to the
// array like so:
array[0] = first_int; // assigns first_int's least significant byte
array[1] = first_int >> 8; // assigns first_int's 2nd least significant byte
array[2] = first_int >> 16; // assigns first_int's 2nd most significant byte
array[3] = first_int >> 24; // assigns first_int's most significant byte
// repeat for second_int:
array[4] = second_int;
array[5] = second_int >> 8;
array[6] = second_int >> 16;
array[7] = second_int >> 24;
// You can now prove that this char array holds the two integers like this:
printf("First integer: %d\n", *((int *) array));
printf("Second integer: %d\n", *((int *) (array + 4)));
return 0;
}
On a big endian system you would first assign the most significant byte, and move on to the least significant bytes.
Replace
cArray[6] = (char) 0; // WHY DOES THIS NOT WORK???
printf("%c\n", cArray[5]);
By
cArray[6] = (char)51;
printf("%c\n", cArray[6]);
Should display '3'
I think you will understand your mistake... 0 as int does not represent the printable character '0', but the NULL termination string
51 as int represent the character '3'
You may use itoa(0,&cArry[6],10).
Use the correctly desired format specifier.
cArray[6] = (char) 0; does store an integer 0 into array element cArray[6]. Its the printf() that is fooling OP into thinking that did not work.
Using %c says OP wants the character that is encoded with a 0. (It usually not visible). Use %d to print the integer value of cArray[6].
printf("%d\n", cArray[6]);
You can add the ASCII value of 0 to the value you want to store digit into the character array.
For example if you want to store 0,1,...,9 into the character array A[10], you may use the following code.
for(j = 0; j<k; j++)
{
A[j] = j + '0'; // Same effect if you use A[j] = j + 0x30
}
This works only if the integer you want to store is less than 10. Otherwise you will have to extract the digits using modulo operator and store.
Is it possible to represent an unsigned character array as a string?
When I searched for it, I found out that only memset() was able to do this (But character by character).
Assuming that is not the correct way, is there a way to do the conversion?
Context: I am trying to store the output of a cryptographic hash function which happens to be an array of unsigned characters.
eg:
unsigned char data[N]; ...
for(i=0;i<N;i++) printf("%x",data[i]);
My goal is to represent the data as a String (%s) rather than access it by each element. Since I need the output of the hash as a String for further processing.
Thanks!
So, based on your update, are you talking about trying to convert a unsigned char buffer into a hexadecimal interpretation, something like this:
#define bufferSize 10
int main() {
unsigned char buffer[bufferSize]={1,2,3,4,5,6,7,8,9,10};
char converted[bufferSize*2 + 1];
int i;
for(i=0;i<bufferSize;i++) {
sprintf(&converted[i*2], "%02X", buffer[i]);
/* equivalent using snprintf, notice len field keeps reducing
with each pass, to prevent overruns
snprintf(&converted[i*2], sizeof(converted)-(i*2),"%02X", buffer[i]);
*/
}
printf("%s\n", converted);
return 0;
}
Which outputs:
0102030405060708090A
In C, a string is an array of char, terminated with a character whose value is 0.
Whether or not char is a signed or unsigned type is not specified by the language, you have to be explicit and use unsigned char or signed char if you really care.
It's not clear what you mean by "representing" an unsigned character array as string. It's easy enough to cast away the sign, if you want to do something like:
const unsigned char abc[] = { 65, 66,67, 0 }; // ASCII values for 'A', 'B', 'C'.
printf("The English alphabet starts out with '%s'\n", (const char *) abc);
This will work, to printf() there isn't much difference, it will see a pointer to an array of characters and interpret them as a string.
Of course, if you're on a system that doesn't use ASCII, there might creep in cases where doing this won't work. Again, your question isn't very clear.
Well a string in C is nothing else than a few chars one after another. If they are unsigned or signed is not much of a problem, you can easily cast them.
So to get a string out of a unsigned char array all you have to do is to make sure that the last byte is a terminating byte '\0' and then cast this array to char * (or copy it into a array of char)
I successfully use this to convert unsigned char array to std:string
unsigned char array[128];
std::stringstream buffer;
for (int i = 0; i < 128; i++)
{
buffer << std::hex << std::setfill('0');
buffer << std::setw(2) << static_cast<unsigned>(array[i]);
}
std::string hexString = buffer.str();
An example as you've asked:
unsigned char arr [SIZE];