void char() {
char buff[50];
int l;
int i = 0;
i = sprintf(buff,a,b,c);
for(i=0,i<=l,l++)
serial.println(buff);
}
I want to have a buffer that will be printed like #123#234#
a=123
b=234
is it the correct way to do that? I tried but I didn't get any output. Probably silly mistake.
EDIT:
#include <stdio.h>
void abc() {
int a = 123;
int b = 234;
char buff[50];
int l;
int i = 0;
l = sprintf(buff,"#%d#%d#",a,b);
for(i=0;i<=l;l++);
printf("%s", buff);
//return buff;
//serial.println(buff);
}
int main() {
//char bhg = abc();
//printf("&d", bhg);
abc();
}
I tried with this.Working properly but taking time to give output. Can I make it fast? Probably it is trying to iterate through that char[50] for allocation.
That's not how you use sprintf. You need to use a format string. Like:
l = sprintf(buff,"#%d#%d#",a,b);
Also, you are assigning the returned length to i in your code, not l.
I'm sure I'm probably violating SO protocol here, but base on your comments, you can do:
a = 100;
b = 23;
Serial.print('#');
Serial.print(a);
Serial.print('#');
Serial.println(b);
This will send this string of characters to your serial port: "#100#23", and in what is probably the most efficient way possible.
Forget about sprintf (which is almost impossible to use safely). Something like:
std::ostringstream buff;
buff << "#" << a << "#" << b << "#";
serial.println( buff.str().c_str() );
should be all you need. (Although I'm not sure: what is l in your code, and why do you loop over it?)
Related
Here is a problem. When I try to convert it by using strncpy_s, array has some type of "trash data" from memory in the end of it. Even when I fill buffer with "\0". How to convert it clear?
typedef class Ryadok {
private:
int LengthOf = 0;
char text[20];
string* address;
public:
Ryadok(string strin) {
this->text[0] = '\0';
memset(text, '\0', sizeof(text));
strncpy_s(text, strin.c_str(), sizeof(text) - 1);
this->address = &strin;
for (int i = 0; i < sizeof(strin); i++) {
cout << this->text[i];
}
}
~Ryadok() {
}
}*cPtr;
int main()
{
Ryadok example("sdsdfsdf");
}
The idea to use c_str() function to convert the std::string to a a-string. Then we can simply call strcpy() function to copu the c-string into char array
std::string s = "Hello World!";
char cstr[s.size() + 1];
strcpy(cstr, s.c_str()); // or pass &s[0]
std::cout << cstr << '\n';
return 0;
When using the strncpy_s function you tell it to copy as many chars as will fit into your buffer "text". Since the string you create the "example" instance with is shorter, the copy function will keep going after the end of the actual string.
That is where your garbage comes from. Even worse you risk a Segmentation Fault this way. Your code might access parts of the RAM it is not allowed to read from. That will cause it to crash.
You are right though to copy the data pointed to by the return of c_str(). The pointer returned by c_str() points to data that belongs to the std::string object and might be changed or even invalidated by that object. (Read more here)
Here's a modified version of your code that should avoid the garbage:
typedef class Ryadok {
private:
int LengthOf = 0;
char text[20];
string* address;
public:
Ryadok(string strin) {
this->text[0] = '\0';
memset(text, '\0', sizeof(text));
if(strin.length()+1 <= sizeof(text)) {
strncpy_s(text, strin.c_str(), strin.length()+1);
} else {
//some error handling needed since our buffer is too small
}
this->address = &strin;
for (int i = 0; i < sizeof(strin); i++) {
cout << this->text[i];
}
}
~Ryadok() {
}
}*cPtr;
int main()
{
Ryadok example("sdsdfsdf");
}
I need to pass a char pointer to function, then change the value that it points to inside the function and print values outside the function.
The problem I have is that I'm losing it when I leave function and try to print it outside. What can I do to avoid this?
This is an code example:
char array[] = "Bada boom";
char *pText = array;
reverseText(pText);
cout << (pText);
cout should print
moob adaB
When I print inside the function, everything is fine(it prints reversed).
My task is to print It out outside the function (as you can see in a 4th line of code)
This is the full of code which have the bug (printing inside func works, outside didn't work)
#include <iostream>
#include <string>
#include <string.h>
using namespace std;
char reverseText(char *text);
int main(){
char array[] = "Bada boom";
char *pTekst = array;
reverseText(pTekst);
cout << (pTekst); //in here it doesn't work
}
char reverseText(char *text){
char befRev[100]; int lenght=-1;
/*until *text doesn't meet '\0' */
for(int i=0;*text!='\0';i++){
befRev[i]=(*text);
text++;
lenght++;
}
/*reversing*/
int j=0;
for(int i=lenght;i>=0;i--){
*(text+j)=befRev[i];
j++;
}
for(int i=0;i<=lenght;i++) //in here it does print the right value
cout << text[i];
};
Just re-arrange the array in-place. The pointer itself doesn't need to change:
#include <cstring>
#include <algorithm>
void reverseText(char* array)
{
auto len = std::strlen(array);
std::reverse(array, array+len);
}
int main()
{
char array[] = "Bada boom";
char *pText = array;
reverseText(pText);
std::cout << pText << std::endl;
}
Output:
moob adaB
If you really wanted to provide a pointer that points to a different address to the caller, you could simply return it:
char* foo(char* stuff)
{
char* tmp = ....;
...
// do some stuff
...
return tmp;
}
Alternatively, you could pass the pointer by reference, but the intent is less clear than in the previous version:
void foo(char*& stuff)
{
stuff = something_else;
}
But in both cases, you must make absolutely sure the thing the new pointer points to is valid outside of the function. This might require some dynamic memory allocation. For your case, it seems the best and simplest option is to re-arrange the array in place.
To answer your question, you have an error in logic. Notice that in your first loop in reverseText you increment the local pointer text. In your second loop you did not reset text to it's original value so beforeRev is being copied over starting at location text+offset.
If you were to look at pText on return from call to reverseText you would find it contains:
"Bada boom\0moob adaB"
Your reverseText should be renamed palindrome :)
This is pretty straightforward. Some points to note:
An array decays to a pointer when you pass it to a function.
You are passing in a null terminated string. So the length of the char array you are passing in is the length of the string (including white space) +1.
Because you are using a pointer there is no need to assign a temp variable to hold everything.
Here is some code in C that is easy to translate to C++. Working out the actual reverse algorithm is left for you as an exercise.
#include<stdio.h>
void reverseText(char* text)
{
// Hint: It can be done in one loop!
int i;
for(i = 0; i < 9; i++)
{
// Your algorithm to reverse the text. I'm not doing it for you! ;)
*(text + i) = 'r';
}
}
int main()
{
char array[] = "Bada boom";
reverseText(array);
printf("The text reversed: %s\n", array);
return 0;
}
My final code:
#include <iostream>
void reverseText(char* text){
int length=-1; char tmp;
/*Length = sign from 0 to 8 without counting explicit NUL terminator*/
for(int i=0;*(text+i)!='\0';i++){
length++;
}
int j=0; int i=length;
while(j<i){
tmp=*(text+j); //tmp=first
*(text+j)=*(text+i); //first=last
*(text+i)=tmp; //last=tmp
j++;
i--;
}
}
int main(){
char array[] = "Bada boom";
char *pText = array;
reverseText(pText);
std::cout << pText;
}
I should have read more about pointers before I started this exercise.
You can either return a pointer or pass a pointer to pointer as a function argument.
//pointer to pointer
void reverseText(char** textPtr) {
char* newText = ...; //initialize;
...
*textPtr = newText; //assign newText
}
//return pointer
char* reverseText(char* text) {
char* newText = ...; //initialize
return newText;
}
Remember that if you allocate memory in this function you must do it dynamically (with new or malloc) and you have to free it afterwards (with delete or free respectively). Memory allocation in a function like this is probably a bad practice and should be avoided.
So I'm making a function that is similar to SubStr. This is an assignment so I cannot use the actual function to do this. So far I have created a function to take a string and then get the desired substring. My problem is returning the substring. In the function when I do Substring[b] = AString[b]; the substring is empty, but if I cout from inside the function I get the desired substring. So what is wrong with my code?
Here is a working demo: http://ideone.com/4f5IpA
#include <iostream>
using namespace std;
void subsec(char AString[], char Substring[], int start, int length);
int main() {
char someString[] = "abcdefg";
char someSubString[] = "";
subsec(someString, someSubString, 1, 3);
cout << someSubString << endl;
return 0;
}
void subsec(char AString[], char Substring[], int start, int length) {
for (int b = start; b <= length; b++) {
Substring[b] = AString[b];
}
}
Maybe this does what you're looking for? It's hard to say as your initial implementation used the length parameter as more of an end position.
#include <iostream>
using namespace std;
void subsec(char AString[], char Substring[], int start, int length)
{
const int end = start + length;
int pos = 0;
for(int b = start; b < end; ++b)
{
Substring[pos++] = AString[b];
}
Substring[pos] = 0;
}
int main()
{
char someString[50] = "abcdefghijklmnopqrstuvwxyz";
char someSubString[50];
subsec(someString, someSubString, 13, 10);
cout << someSubString << endl;
return 0;
}
There are several problems with the code:
1) The char arraysomeSubString has size 1 which cannot hold the substring.
2) The subsec is not correctly implemented, you should copy to the Substring from index 0.
Also remember to add \0 at the end of the substring.
void subsec(char AString[], char *Substring, int start, int length) {
int ii = 0;
for (int jj = start; jj <= length; jj++, ii++) {
Substring[ii] = AString[jj];
}
Substring[ii] = '\0';
}
You need to allocate more than 1 byte for someSubString i.e.
char someSubString[] = "xxxxxxxxxxxxxxxxxx";
or just
char someSubString[100];
if you know the max size you'll ever need.
Either would allocate enough space for the string you're copying to it. Then, you're not doing anything about the terminating 0 either. At the end of a C-style string there needs to be a terminating null to signify end of string. Otherwise cout will print something like;
abcdefgxxxxxxx
if you initialized with x's as I indicated.
There are a few problems with your code as it stands. Firstly, as your compiler is no doubt warning you, in C++ a string literal has type const char[], not just char[].
Secondly, you need to have enough space to store your substring. A good way to do this is for your function to allocate the space it needs, and then pass back a pointer to this memory. This is the way things are typically done in C code. The only thing is that you have to remember to delete the allocated array when you're done with it. (There are other, better ways to do this in C++, with things like smart pointers and wrapper objects, but those come later :-) ).
Thirdly, you'll have a problem if you request a length which is actually longer than the passed-in string -- you'll run off the end and start copying random memory (or just crash), which is definitely not what you want. C strings are terminated with a "nul byte" -- so you need to check whether you've come across this.
Speaking of the nul, you need to make sure that your substring ends with one.
Lastly, it's not really a problem but there's no need for the start parameter, you can just pass a pointer to the middle of the array if you want to.
char* substring(const char* str, int length)
{
// Allocate memory for substring;
char* subs = new char[length+1];
// Copy characters from given string
int i = 0;
while (i < length && str[i] != '\0') {
subs[i] = str[i];
i++;
}
// Append the nul byte
subs[i] = '\0';
return subs;
}
int main()
{
const char someString[] = "foobarbaz"; // Note -- must be const in C++
char* subs = substring(someString + 3, 3);
assert(strcmp(subs, "bar") == 0);
delete subs;
}
I use an external library to deal with udp (OSC) communication between 2 apps.
To format the messages that will be sent, the library is expecting a char* but I get a string from the UI that I have to convert.
While I was dealing with other parts of my code the udp part was hard coded like that :
char* endofMess = "from setEndMess";
and was working fine. I thought it would be easy to get it working with my strings and wrote :
std::string s = "from setEndMess";
char* endofMess = const_cast<char*>(s.c_str());
but unlike for the first example where I was receiving the message correctly formatted, I now receive only gibberish characters. Does somebody know where it can come from?
Thanks!
Matthieu
EDIT : the code I use :
The method to send the message each time OSCVal will change :
void osc500::testOSC(int identifier, float OSCval)
{
UdpTransmitSocket transmitSocket( IpEndpointName( destIP, port ) );
char buffer[1024];
osc::OutboundPacketStream p( buffer, 1024 );
p << osc::BeginBundleImmediate
<< osc::BeginMessage( endofMess )
<< OSCval << osc::EndMessage
<< osc::EndBundle;
transmitSocket.Send( p.Data(), p.Size() );
}
And if I have to change the OSC pattern I call this one :
void osc500::setEndMess(String endpattern){
// endofMess = "from setEndMess"; //OK works fine each time it's called
//1st try :
//std::string s = "from setEndMess";
//endofMess = const_cast<char*>(s.c_str()); //gibberish
//2nd try :
//std::string s = "from setEndMess";
//endofMess = &s[0]; //gibberish
//3rd & 4th tries :
//char s[4] = {'t','e','s','t'};
//char s[5] = {'t','e','s','t','\0'};
//endofMess = s; //gibberish
}
c_str() is for read-only access of std::string.
If you want to write to a string through pointers, then use either...
an array (or vector) of char instead of std::string
char* buf = &str[0]; - point directly to the first character of a string
Trick (2) is guaranteed to work under C++11; in practice it works in C++03 too but that relies on compiler implementation of std::string having contignuos storage.
(And whatever you do, keep an eye on the buffer length.)
I suspect the char* is not written to, it is only non const because it is a legacy API. If so, your problem is probably that the std::string has fallen out of scope or been modified between the point where you call c_str and where it is used in the guts of the API.
If you want to modify the std::string content, I think you should use &s[0] (making sure that the string is big enough).
std::string s = "abcdef...";
char* ptr = &s[0];
e.g. (tested with MSVC10):
#include <iostream>
#include <ostream>
#include <string>
using namespace std;
void f(char* ptr, size_t count)
{
for (size_t i = 0; i < count; i++)
ptr[i] = 'x';
}
int main()
{
string s = "abcdef";
cout << s << endl;
f(&s[0], 3);
cout << s << endl;
}
Output:
abcdef
xxxdef
I have main function like this:
void main()
{
char *s;
inputString(s);
printf("%s",s);
}
and inputString function:
void inputString(char *&s)
{
//Some code line to input a string and set s point to this string
}
Is there have a function auto malloc memory enough store string which inputed (I need input string in inputString function).
Just 3 lines of code (put these inside int main() )are enough
std::string s;
std::cin >> s; //or getline() as desired
std::cout << s;
If you keep using this C style approach, then no, you will have to make assumptions and allocate enough memory yourself. The C++ approach is much more superior, use std::strings and don't do manual allocations:
#include <string>
#include <iostream>
void inputString(std::string& s)
{
//Don't bother for the memory management
}
int main()
{
std::string s;
inputString(s);
std::cout << s ;
}
Also do note that your code is not legal C++. void main() is illegal!!!
Edit: At the time of this answer the question was tagged C++. Later the question was retagged NOT by the OP, and I don't quite agree with it...
You're mixing C and C++ in your example.
In your case before you can use s it should be initialized. For example, like this:
void inputString(char *&s)
{
s = strdup(xxx); // or malloc, calloc, etc.
}
But really, then it's better to just use plain old C:
char* inputString(void)
{
char* s = strdup(xxx);
return s;
}
Assuming that you are doing this is C and not C++.
There are two approaches, either inputString must allocate the memory or the caller of inputString must allocate the memory.
if inputString allocates the memory your function will probably look something like:
char* inputString(void)
{
int len = strlen (MyInternalString) + 1;
char* s = malloc (len);
strncpy(s, MyInternalString, len);
return s;
} //similar to what Rustram illustrated
you should also include:
void freeString(char* str)
{
free(str);
}
as well. This makes it clear to the user that they are required to manage the memory of the returned string themselves.
Alternatively you can write inputString where the user is expected to provide the required memory. This will then look something like
int inputString(char* str, int maxLen) //
{
if (maxLen >= myInternalStringLength + 1)
{
strncpy(str, myInternalString, maxLen)
}
return myInternalStringLength + 1;
}
Here the user of my string can check the return code to see if the buffer that he allocated was big enough. If it was too small, then he can always realloc a bigger one
Your main now becomes:
int main()
{
char *s = NULL;
int len = inputString(s, 0);
s = alloca(len); //allocates the memory on the stack
len = inputstring(s, len);
printf("%s",s);
} //no need to free the memory because the memory alloca'ed gets
//freed at the end of the stack frame
int main()
{
std::string s;
inputString(s);
printf("%s",s.c_str());
}
and inputString function:
void inputString(std::string& s)
{
//Some code line to input a string and set s point to this string
std::cin >> s;
}