C++: Efficient way to turn part of char array to int - c++

I have a char buffer that contains several integers one after the other without any breaks between them, where the offsets of each separate number are known in advance. For example "1234123123456", where from position [0] to [3] it would be the first number, [4] to [6] the second, and [7] to the end would be the third.
Is there any way to convert these different sections to ints without altering the buffer? Please no usage of std::string since it is inefficient for my purposes.

You can write a simple conversion function like this:
int convert_slice(const char *s, size_t a, size_t b) {
int val = 0;
while (a < b) {
val = val * 10 + s[a++] - '0';
}
return val;
}
int main(void) {
char buffer[] = "12345678901234567890";
printf("%d\n", convert_slice(buffer, 0, 4);
printf("%d\n", convert_slice(buffer, 4, 6);
printf("%d\n", convert_slice(buffer, 6, 11);
printf("%d\n", convert_slice(buffer, 11, 20);
return 0;
}
Will produce:
1234
56
78901
234567890
Note that I use 2 index arguments, the first is included and the second is excluded. This is more consistent with C and C++ practices. You could also use a more classic C++ API such as int convert_slice(const char *a, const char *b);

One clean way to do this without writing your own parsing code or making temporary copies is to use sscanf:
sscanf(src+start_offset, "%4d", &result);
If the length of the field (4 in the example) is not constant, though, you'll need either snprintf to construct a format string to pass to sscanf, or an array of possible format strings for the sizes you need.

Related

Best way to get length of const char * in c++

i know two way's to get length of const char *
const char * str = "Hello World !";
int Size = 0;
while (str[Size] != '\0') Size++;
and other way is very simple
const char * str = "Hello World !";
size_t Size = strlen(str);
but i don't want to use str lib functions like strlen and i think this function use my first way behavior too. because in the pc world when we want to count something we need to count each block's and there is no magic to get the length with one movement so i think the first way is the best option to get length of const char *. other way i think the first way is maybe too heavy for heavy string's. so im confused. which way is better and why other way is not ?
Let's inspect the assembly listing of these two methods.
#include <cstddef>
#include <cstring>
int string_size_1()
{
const char * str = "Hello World !";
int Size = 0;
while (str[Size] != '\0') Size++;
return Size;
}
int string_size_2()
{
const char * str = "Hello World !";
size_t Size = strlen(str);
return Size;
}
Using Clang 4.0.0 with flags -std=c++14 -O2
string_size_1(): # #string_size_1()
mov eax, 13
ret
string_size_2(): # #string_size_2()
mov eax, 13
ret
Link: https://godbolt.org/g/5S6VSZ
Both methods end up with exactly the same assembly listing. Also, the compiler optimizes away everything and just return a constant because the string literal is known during compile-time. So, in terms of performance, they are equally good.
But in terms of readability, strlen(str) is definitely better. A function call states the intention through the function name. A loop cannot do that.
Besides, std::string and std::string_view are more preferable than C-string in many cases. Consider them.
In this case the answer is known at compile time:
template <std::size_t S>
constexpr std::size_t string_length
(
char const (&)[S]
)
{
return S - 1;
}
usage:
std::cout << string_length("example") << std::endl;
For cases where the string is not a compile time constant use strlen if only the pointer to the string is available, std::distance if both pointers to the beginning and end are available, or .size() if your dealing with a std::string
3 years late but better late that never.
Short answer
#define length(array) ((sizeof(array)) / (sizeof(array[0])))
Long answer
So using sizeof(array) returns the size of the type of the array * the amount of elements. Knowing this, we could achieve this:
#define length(array) ((sizeof(array)) / (sizeof(array[0])))
and you would use it like:
type yourArray[] = {your, values};
length(yourArray); // returns length of yourArray
For example:
#include <stdlib.h>
#include <stdio.h>
#define length(array) ((sizeof(array)) / (sizeof(array[0])))
int main()
{
const char *myStrings[] = {"Foo", "Bar", "Hello, World!"}; // 3 elements
int myNums[] = {0, 1, 5, 7, 11037}; // 5 elements
char myChars[] = {'a', 'b', 'c', 'd', 'e', 'f', 'g'}; // 7 elements
printf("Length of myStrings array: %lu\n", length(myStrings));
printf("Length of myNums array: %lu\n", length(myNums));
printf("Length of myChars array: %lu\n", length(myChars));
return 0;
/* Output:
Length of myStrings array: 3
Length of myNums array: 5
Length of myChars array: 7 */
}
I tested it and it also works with uninitialized arrays, probably because they contain garbage (from being uninitialized) from the same type. Integer uninitialized arrays contain random integer numbers and const char* uninitialized arrays contain (null) which is treated as a const char*.
Now, this only works with arrays on the stack. Pointers pointing to space reserved in the heap used as an array would give unexpected results. For example:
int *myNums = (int *)malloc(3 * sizeof(int)); // Space for 3 integers
printf("Length of myNums: %lu\n", length(myNums)); // Outputs 2 instead of 3
So be advised. Who uses arrays on the heap anyways so whatever.
Note: This is relevant to this question as it works with const char * as requested. Works with other types too.

go equivalents of c types

What are the right equivalent of unsigned char or unsigned char* in go? Or am I even doing this right?
I have this C++ class:
class ArcfourPRNG
{
public:
ArcfourPRNG();
void SetKey(unsigned char *pucKeyData, int iKeyLen);
void Reset();
unsigned char Rand();
private:
bool m_bInit;
unsigned char m_aucState0[256];
unsigned char m_aucState[256];
unsigned char m_ucI;
unsigned char m_ucJ;
unsigned char* m_pucState1;
unsigned char* m_pucState2;
unsigned char m_ucTemp;
};
I am trying to rewrite it to go:
type ArcfourPRNG struct {
m_bInit bool
m_aucState0 [256]byte
m_aucState [256]byte
m_ucI, m_ucJ []byte
*m_pucState1 []byte
*m_pucState2 []byte
m_ucTemp []byte
}
func (arc4 *ArcfourPRNG) SetKey(pucKeyData []byte, iKeyLen int) {
func (arc4 *ArcfourPRNG) Reset() {
func (arc4 *ArcfourPRNG) Rand() uint {
Well, I just started with go a few hours ago. So this is still confusing me.
A function
for(i=0; i<256; i++)
{
m_pucState1 = m_aucState0 + i;
m_ucJ += *m_pucState1 + *(pucKeyData+m_ucI);
m_pucState2 = m_aucState0 + m_ucJ;
//Swaping
m_ucTemp = *m_pucState1;
*m_pucState1 = *m_pucState2;
*m_pucState2 = m_ucTemp;
m_ucI = (m_ucI + 1) % iKeyLen;
}
memcpy(m_aucState, m_aucState0, 256); // copy(aucState[:], aucState0) ?
Hopefully this can clear a few things up for you.
For storing raw sequences of bytes, use a slice []byte. If you know exactly how long the sequence will be, you can specify that, e.g. [256]byte but you cannot resize it later.
While Go has pointers, it does not have pointer arithmetic. So you will need to use integers to index into your slices of bytes.
For storing single bytes, byte is sufficient; you don't want a slice of bytes. Where there are pointers in the C++ code used to point to specific locations in the array, you'll simply have an integer index value that selects one element of a slice.
Go strings are not simply sequences of bytes, they are sequences of UTF-8 characters stored internally as runes, which may have different lengths. So don't try to use strings for this algorithm.
To reimplement the algorithm shown, you do not need either pointers or pointer arithmetic at all. Instead of keeping pointers into the byte arrays as you would in C++, you'll use int indexes into the slices.
This is kind of hard to follow since it's virtually all pointer arithmetic. I would want to have a description of the algorithm handy while converting this (and since this is probably a well-known algorithm, that should not be hard to find). I'm not going to do the entire conversion for you, but I'll demonstrate with hopefully a simpler example. This prints each character of a string on a separate line.
C++:
unsigned char *data = "Hello World";
unsigned char *ptr = 0;
for (int i = 0; i < std::strlen(data); i++) {
ptr = i + data;
std::cout << *ptr << std::endl;
}
Go:
data := []byte("Hello World")
for i := 0; i < len(data); i++ {
// The pointer is redundant already
fmt.Println(data[i:i+1])
}
So, learn about Go slices, and when you do reimplement this algorithm you will likely find the code to be somewhat simpler, or at least easier to understand, than its C++ counterpart.

How can I add multiple ints to a character array, then pull them out?

I am trying to place 3 integers(byte size is 4) into a character string byte by byte using c. I then need to "extract" the integers out of the character array so I can do integer operations on them. I have looked around and could not find any solutions to this. I think this will require some type of pointer use or shifting, but I cannot figure out how to write it.
char str[12]="";
int a;
int b;
int c;
int x;
int y;
int z;
a=5;
b=7;
c=12;
I know that an int is 4 bytes. I would like to make it so the str char array has the following data in it.
str = |a1|a2|a3|a4|b1|b2|b3|b4|c1|c2|c3|c4|
*I do not want it like this. str=|'5'|'7'|'12'|
I then need to "extract" the integers out of the character array.
x=str[0-3]; //extracting a
y=str[4-7]; //extracting b
z=str[8-11]; //extracting c
After this, I should be able to write x=y+z and x will be equal to 19.
One way is to treat str as an int array instead:
int* istr = reinterpret_cast<int*>(str)
Then you can use e.g.
istr[0] = a;
istr[1] = b;
istr[2] = c;
and
x = istr[0];
y = istr[1];
z = istr[2];
The question is not well posed so you are getting different answers which may or may not be solving your problem. In my interpretation, here's what you need:
int i1, i2, i3;
char arr[sizeof(i1)+sizeof(i2)+sizeof(i3)];
memcpy(arr, &i1, sizeof(i1));
memcpy(arr+sizeof(i1), &i2, sizeof(i2));
memcpy(arr+sizeof(i1)+sizeof(i2), &i3, sizeof(i3));
Note that I'm being deliberately explicit with using sizeof(i) instead of just "4". It is fairly safe that integers will be 32-bit in whatever environment you are using, but this is safer and strictly speaking more correct.
The easiest solution is to use memcpy:
int nums[sizeof str / sizeof(int)];
std::memcpy(nums, str, sizeof nums);
// Do work on nums here...
The reinterpret_cast approach is undefined behaviour.
Use (void *) to get a pointer to x, byte by byte
for (int i = 0; i < sizeof(int); ++i) {
str[i] = (void *)(&x)[i];
}
This will copy the 4 bytes of x into str, one by one. (void )(&x) casts x as a char array (or void*, same thing), and [i] accesses the i_th byte of the array
then access elements of str the same way.
Do the same with y and z, and don't forget the offset

Convert Int to Char Array

I need to make a class called MyInt which handles any size positive numbers by creating an int array. I am making a constructor to be used in converting an int (any size supported by ints) into a MyInt. I need to convert the int into a char array and then read digit by digit into the int array. So my question is, without using any libraries except <iostream> <iomanip> and <cstring> how can I convert an int with multiple digits into a character array?
You don't need to make a char array as an intermediary step. The digits (I assume in base 10) can be obtained one by one using modulo 10 operations. Something like:
convert(int *ar, const int i)
{
int p, tmp;
tmp = i
while (tmp != 0)
{
ar[p] = tmp % 10;
tmp = (tmp - ar[p])/10;
p++;
}
}
Not sure if this is what you want, but:
int myInt = 30;
char *chars = reinterpret_cast<char*>(&myInt);
And you can get the 4 separate char's:
chars[0]; // is the first char
chars[1]; // is the second char
chars[2]; // is the third char, and
chars[3]; // is the fourth/last char
...but I'm not entirely sure if that's what you are looking for.
One possible way of doing that conversion with such restraints is as follows:
function convert:
//find out length of integer (integer division works well)
//make a char array of a big enough size (including the \0 if you need to print it)
//use division and modulus to fill in the array one character at a time
//if you want readable characters, don't forget to adjust for them
//don't forget to set the null character if you need it
I hope I didn't misunderstand your question, but that worked for me, giving me a printable array that read the same as the integer itself.

Is it possible to pass char[][] to a function requesting char**?

I am trying to call a function that takes char** as a parameter. Its job is to fill an array of strings (i.e. an array of char*). I know the max length of the strings, and I can pass the max number to fill as another parameter, so I was hoping to stack allocate it like this:
fill_my_strings(char** arr_str, int max_str); // function prototype
char fill_these[max_strings][max_chars_per_string]; // allocating chars
fill_my_strings(fill_these, max_strings); // please fill them!
Of course, I get the "cannot convert char[max_strings][max_chars_per_string] to char**" error.
I know this is some subtle (or not-so-subtle) problem with my understanding of the difference between arrays and pointers. I'm just not sure why it's not possible to pass this block of memory to something wanting a char** and have it fill in my stack-allocated chars. Could somebody please explain if this is possible, or if not, why not?
Is it possible to call a function like this without calling malloc / new?
The simple answer to your question is no; a two dimensional array is different than a pointer-to pointer type. Arrays decay to pointers to their first element, but pointers actually are that value.
The difference between these types is clear, if you cast both to char*
int x;
char *arr_pp[] = {"foo", "bar", "baz"};
char arr_2d[][4] = {"foo", "bar", "baz"};
char *cp = (char*)arr_pp;
for(x=0; x<3; x++)
printf("%d ", cp[x]);
printf("\n");
cp = (char*)arr_2d;
for(x=0; x<3; x++)
printf("%d ", cp[x]);
printf("\n");
The output (on my computer) is:
-80 -123 4
102 111 111
Where the first row is gibberish formed by the fact that I'm printing an address cast into bytes, and the second row is the ascii values of "foo".
In a function taking a char ** the compiler can't know to decay array types, which don't actually contain pointers.
Suppose you have n pointers to strings of m-1 maximum characters (m characters including the NULL).
So, in pure C:
sizeof(char[n][m]) will return n*m.
sizeof(char**) will return the size of a pointer in your architecture, probably 32 (if x86) or 64 (if x86_64).
char[n][m] actually allocates the n*m byte contiguously. char** allocates a single pointer. This pointer references a memory stripe of *n bytes. Each of these n pointers points to a memory stripe of m characters.
So, considering that sizeof(char) == u, if you declare char a[n][m], when you use a[i][j], the compiler understands *(a + i*m*u + j*u).
So, considering that sizeof(char *) == w, if you declare char **a, when you use a[i][j], the compiler understands ((a + i*w) + j*w).
Completely different data management.
The closes thing you could do to handle your special case is to create a char** variable, and populate it with the addresses of your stack allocated matrix.
char **tmp = malloc(max_strings * sizeof(char *));
int i;
for(i = 0; i < max_strings; i++){
tmp[i] = &(fill_these[i][0]); //you probably can't reference a char[][] with a single index - not confirmed
}
I am not sure why fill_my_strings() need a char** parameter. From your example, caller have already allocated the memory from stack. So using a char* should be OK.
But if you want to use char** or you can't modify the fill_my_strings() function, try following example code:
void fill_my_strings(char** arr_str, int max_chars_per_string, int max_strings)
{
for(int i = 0; i < max_strings; ++i)
{
//Make sure you have enough space
memcpy(*arr_str, "ABCD", sizeof("ABCD"));
*arr_str += max_chars_per_string;
}
}
char fill_these[max_strings][max_chars_per_string];
char* pointer = (char*)fill_these;
fill_my_strings(&pointer, max_strings, max_chars_per_string);
The obvious thing to do is build an index
In c use something like:
char string_list[num_strings][str_length];
// ...
char**index = calloc( (num_strings+1), sizeof(*index) ); // calloc insures NULL termination
for (int i=0; i<num_strings; ++i) {
index[i] = string_list[i]
}
In c++ prefer new[] to calloc;