like the topic mention.... for example
int[10] msg;
msg[0] = 1;
msg[1] = 2;
const char* a = (const char*)msg[0];
const char* b = (const char*)msg[1];
It seem there is no value when I test by printf
I'm going to use it this way
char test[20];
strcpy(test, a);
strcat(test, ",");
strcat(test, b);
strcat(test, "\0");
mclient.publish("topic1/sensorAck",test);
The result show only comma
strcpy and strcat both stop when they reach a '\0' character in the source string. Since int 1 is actually 4 bytes (0, 0, 0, 1), it will stop on the first byte, because it's zero '\0' and never reach the '1' value byte.
Here's the C code to convert an integer into a C string.
int i = 1;
char text[12];
sprintf(text, "%d", i);
Related
#include<string>
#include<cstring>
class Solution {
void shift_left(char* c, const short unsigned int bits) {
const unsigned short int size = sizeof(c);
memmove(c, c+bits, size - bits);
memset(c+size-bits, 0, bits);
}
public:
string longestPalindrome(string s) {
char* output = new char[s.length()];
output[0] = s[0];
string res = "";
char* n = output;
auto e = s.begin() + 1;
while(e != s.end()) {
char letter = *e;
char* c = n;
(*++n) = letter;
if((letter != *c) && (c == &output[0] || letter != (*--c)) ) {
++e;
continue;
}
while((++e) != s.end() && c != &output[0]) {
if((letter = *e) != (*--c)) {
const unsigned short int bits = c - output + 1;
shift_left(output, bits);
n -= bits;
break;
}
(*++n) = letter;
}
string temp(output);
res = temp.length() > res.length()? temp : res;
shift_left(output, 1);
--n;
}
return res;
}
};
input string longestPalindrome("babad");
the program works fine and prints out "bab" as the longest palindrome but there's a heap overflow somewhere. Error like this appears:
Read of size 6 at ...memory address... thread T0
"babad" is size 5 and after going over this for an hour. I don't see the point where the iteration ever exceeds 5
There is 3 pointers here that iterate.
e as the element of string s.
n which is the pointer to the next char of output.
and c which is a copy of n and decrements until it reaches the address of &output[0].
maybe it's something with the memmove or memset since I've never used it before.
I'm completely lost
TL;DR : mixture of char* and std::string are not really good idea if you don't understand how exactly it works.
If you want to length of string you cant do this const unsigned short int size = sizeof(c); (sizeof will return size of pointer (which is commonly 4 on 32-bit machine and 8 on 64-bit machine). You must do this instead: const size_t size = strlen(c);
Address sanitizers is right that you (indirectly) are trying to get an memory which not belongs to you.
How does constructor of string from char* works?
Answer: char* is considered as c-style string, which means that it must be null '\0' terminated.
More details: constructor of string from char* calls strlen-like function which looks like about this:
https://en.cppreference.com/w/cpp/string/byte/strlen
int strlen(char *begin){
int k = 0;
while (*begin != '\0'){
++k;
++begin;
}
return k;
}
If c-style char* string does not contain '\0' it cause accessing memory which doesn't belongs to you.
How to fix?
Answer (two options):
not use mixture of char* and std::string
char* output = new char[s.length()]; replace with char* output = new char[s.length() + 1]; memset(output, 0, s.length() + 1);
Also you must delete all memory which you newed. So add delete[] output; before return res;
I try to write a char[] to a binary file, this is my method, for an int, a float, a double, and a char*
friend ofstream& operator<<(ofstream& outB, Test& t) {
//scriem int, float si double normal
outB.write((char*)&t.i, sizeof(int));
outB.write((char*)&t.f, sizeof(float));
outB.write((char*)&t.d, sizeof(double));
//scriem stringul ca un char ( +1 pentru \0)
outB.write(t.s.c_str(), t.s.size() + 1);
//scriem charul
int nrCHAR = strlen(t.c) + 1;
outB.write((char*)&nrCHAR, sizeof(int));
outB.write(t.c, strlen(t.c) + 1);
return outB;
}
I can do it like this?
outB.write(c, strlen(c) + 1);
c being my char[]
Usually, text fields are variable length, so you will have to write the length and the text. Here's my suggestion:
const uint32_t length = strlen(c);
outB.write((char *) &length, sizeof(length));
outB.write(c, length);
When reading, you can do the reverse:
const uint32_t length = 0;
inpB.read((char *) &length, sizeof(length));
char * text = new char [length + 1];
inpB.read(&text[0], length);
text[length] = '\0';
A nice feature of writing the length first, is that you can allocate dynamic memory for the string before reading the text. Also, since the length of the text is known, a block read can be performed.
When using a sentinel character, like '\0', you have to read character by character until the sentinel is read. This is slow, really slow. You may also have to reallocate your array, since you don't know the size of the string.
char *readByteArray() {
unsigned char l = readByte (); // reads one byte from the stream
char ret[l + 1]; // this should not be done
ret[0] = l; // or could also define a struct for this like {int length, char *data}
readBytes((char *)&ret + 1, l);
return (char *)&ret;
}
So the problem is, that I want to return an array, and the length of the array is determined by the function.
A better example of this would be the function I use for reading a string:
char *readString () {
unsigned char l = readByte (); // reads one byte from the stream
char ret[l + 1]; // +1 for null byte
readBytes((char *)&ret, l); // reads l bytes from the stream
ret[l] = '\0'; // null byte
return (char *)&ret; // problem
}
If the length of the array would be determined before the function I could allocate the array outside the function and pass it as a parameter, but calling this:
unsigned char l = readByte ();
char ret[l + 1];
readString (&ret, l);
every time I want to read a string would kind of defeat the purpose of the function.
Is there an elegant solution for this on windows AND ATmega328 (STL is not available)?
One of the following options should work:
Return a pointer to an array of char allocated from the heap. Make sure to delete the returned value in the calling function.
char* readByteArray()
{
unsigned char l = readByte();
char *ret = new char[l + 1];
ret[0] = l;
readBytes(ret + 1, l);
return ret;
}
Return a std::vector<char>.
std::vector<char> readByteArray()
{
unsigned char l = readByte();
std::vector<char> ret(l);
readBytes(ret.data(), l);
return ret;
}
I've tried so may ways on the Internet to append a character to a char* but none of them seems to work. Here is one of my incomplete solution:
char* appendCharToCharArray(char * array, char a)
{
char* ret = "";
if (array!="")
{
char * ret = new char[strlen(array) + 1 + 1]; // + 1 char + 1 for null;
strcpy(ret,array);
}
else
{
ret = new char[2];
strcpy(ret,array);
}
ret[strlen(array)] = a; // (1)
ret[strlen(array)+1] = '\0';
return ret;
}
This only works when the passed array is "" (blank inside). Otherwise it doesn't help (and got an error at (1)). Could you guys please help me with this ? Thanks so much in advanced !
Remove those char * ret declarations inside if blocks which hide outer ret. Therefor you have memory leak and on the other hand un-allocated memory for ret.
To compare a c-style string you should use strcmp(array,"") not array!="". Your final code should looks like below:
char* appendCharToCharArray(char* array, char a)
{
size_t len = strlen(array);
char* ret = new char[len+2];
strcpy(ret, array);
ret[len] = a;
ret[len+1] = '\0';
return ret;
}
Note that, you must handle the allocated memory of returned ret somewhere by delete[] it.
Why you don't use std::string? it has .append method to append a character at the end of a string:
std::string str;
str.append('x');
// or
str += x;
The function name does not reflect the semantic of the function. In fact you do not append a character. You create a new character array that contains the original array plus the given character. So if you indeed need a function that appends a character to a character array I would write it the following way
bool AppendCharToCharArray( char *array, size_t n, char c )
{
size_t sz = std::strlen( array );
if ( sz + 1 < n )
{
array[sz] = c;
array[sz + 1] = '\0';
}
return ( sz + 1 < n );
}
If you need a function that will contain a copy of the original array plus the given character then it could look the following way
char * CharArrayPlusChar( const char *array, char c )
{
size_t sz = std::strlen( array );
char *s = new char[sz + 2];
std::strcpy( s, array );
s[sz] = c;
s[sz + 1] = '\0';
return ( s );
}
The specific problem is that you're declaring a new variable instead of assigning to an existing one:
char * ret = new char[strlen(array) + 1 + 1];
^^^^^^ Remove this
and trying to compare string values by comparing pointers:
if (array!="") // Wrong - compares pointer with address of string literal
if (array[0] == 0) // Better - checks for empty string
although there's no need to make that comparison at all; the first branch will do the right thing whether or not the string is empty.
The more general problem is that you're messing around with nasty, error-prone C-style string manipulation in C++. Use std::string and it will manage all the memory allocation for you:
std::string appendCharToString(std::string const & s, char a) {
return s + a;
}
char ch = 't';
char chArray[2];
sprintf(chArray, "%c", ch);
char chOutput[10]="tes";
strcat(chOutput, chArray);
cout<<chOutput;
OUTPUT:
test
How would I manually concatenate two char arrays without using the strncpy function?
Can I just say char1 + char2?
Or would I have to write a for loop to get individual elements and add them like this:
addchar[0] = char1[0];
addchar[1] = char1[1];
etc
etc
addchar[n] = char2[0];
addchar[n+1] = char2[1];
etc
etc
To clarify, if
char1 = "happy"
char2 = "birthday"
I want addchar to = happybirthday
For a C-only solution use strncat:
char destination[80] = "";
char string1[] = "Hello";
char string2[] = " World!";
/* Copy string1 to destination */
strncat(destination, string1, sizeof(destination));
/* Append string2 to destination */
strncat(destination, string2, sizeof(destination) - sizeof(string1));
Note that the strn* family of string functions are safer than the ones without n, because they avoid the possibility of buffer overruns.
For a C++ solution, simply use std::string and operator+ or operator+=:
std::string destination("Hello ");
destination += "World";
destination += '!';
If you consider two trivial loops to be "manual", then yes, without using the standard library this is the only way.
char *append(const char *a, const char *b) {
int i = 0;
size_t na = strlen(a);
size_t nb = strlen(b);
char *r = (char*)calloc(na + nb + 1, 1);
for (i = 0; i < na; i++) {
r[i] = a[i];
}
for (i = 0; i < nb; i++) {
r[na + i] = b[i];
}
return r;
}
Remember to call free.
If you're using c++ just use an std::string. With std::strings, the + operator is supported, so you can do string1+string2.
Without using library functions, here is the procedure:
1. Point to the first character in string1.
2. While the current character at the pointer is not null, increment the pointer.
3. Create a "source" pointer pointing to string2.
4. While the character at the "source" location is not null:
4.1. Copy the character from the "source" location to the location pointed to by the String1 pointer.
4.2. Increment both pointers.
Unless this is homework, use C++ std::string for your text.
If you must use C style strings, use the library functions.
Library functions are optimized and validated, reducing your development time.
Alright, you want something like this:
char1 + char2
First, let's see the insane solution:
C:
char* StringAdd(char* a_Left, char* a_Right)
{
unsigned int length_left = strlen(a_Left);
unsigned int length_right = strlen(a_Right);
unsigned int length = length_left + length_right;
char* result = (char*)malloc(length);
// clear the string
memset(result, 0, length);
// copy the left part to the final string
memcpy(result, a_Left, length_left);
// append the right part the to the final string
memcpy(&result[length_left], a_Right, length_right);
// make sure the string actually ends
result[length] = 0;
return result;
}
C++:
char* StringAdd(char* a_Left, char* a_Right)
{
unsigned int length_left = strlen(a_Left);
unsigned int length_right = strlen(a_Right);
unsigned int length = length_left + length_right;
char* result = new char[length];
// clear the string
memset(result, 0, length);
// copy the left part to the final string
memcpy(result, a_Left, length_left);
// append the right part the to the final string
memcpy(&result[length_left], a_Right, length_right);
// make sure the string actually ends
result[length] = 0;
return result;
}
Now, let's see the sane solution:
char* StringAdd(char* a_Left, char* a_Right)
{
unsigned int length = strlen(a_Left) + strlen(a_Right);
char* result = new char[length];
strcpy(result, a_Left);
strcat(result, a_Right);
return result;
}
So, was this homework? I don't really care.
If it was, ask yourself: what did you learn?