C++ Converting to String eventually stops working - c++

The below method is called every second 4 times, for a while it works fine, I get the following output:
++++++++++++++++
^
^
++++++++++++++++
However after a few hundred calls, the line
String str = String(tosend);
Seems to stop working somehow and I get the output
++++++++++++++++
^
++++++++++++++++
So for whatever reason 'str' has no value. As I'm typing this it seems if I leave the application running long enough it starts working again and I get the correct output. What on earth is wrong here? I'm baffled.
void Transmit(char tosend)
{
String str = String(tosend);
const char *tosend_ready = str.c_str();
Serial.println("++++++++++++++++");
Serial.println(str);
Serial.println(tosend);
Serial.println("++++++++++++++++");
vw_send((uint8_t *)tosend_ready, strlen(tosend_ready));
vw_wait_tx();
delay(100);
}

I've no idea what String is, but this implementation can get you rid of it (looks like embedded anyway, so you shouldn't care about C-isms... right?)
void Transmit(char tosend)
{
const char buf[2] = { tosend, '\0' };
Serial.println("++++++++++++++++");
Serial.println(buf);
Serial.println(tosend);
Serial.println("++++++++++++++++");
vw_send(buf, 2);
vw_wait_tx();
delay(100);
}

Related

C++ Recognize UTF-8 or Hebrew languague

I'm working on some code that his target it recognize if the strings equal
Have two type of string - string 1 came from text file , string 2 came from server side from chat packet
i try very different options , this my last trying but nothing success the sentence not recognize has equal at all for example this string on text file "בדיקה" and the string that came from packet side is "בדיקה" too and still nothing equal
`
if(gSentenceEvent.IsRunning())
{
std::string s = lpMsg->message;
int Len = strlen(gSentenceEvent.RandomSentence);
std::string str;
str.assign(gSentenceEvent.RandomSentence, gSentenceEvent.RandomSentence + Len);
if (str.compare(s) == 0)
{
gSentenceEvent.SetRunning(false);
gNotice.GCNoticeSendToAll(0,0,0,0,0,0,gMessage.GetMessage(1130));
gNotice.GCNoticeSendToAll(0,0,0,0,0,0,gMessage.GetMessage(1127),lpObj->Name);
}
else
{
gNotice.GCNoticeSendToAll(0,0,0,0,0,0,"%s Try %s\n",lpObj->Name,s);
gNotice.GCNoticeSendToAll(0,0,0,0,0,0,"Answer Is %s\n",str);
}
}
`
if someone have any idea for solving the issue i will be happy to hear some ways that recognize it well
Thanks in advance !
trying convert the text for wstring as well but still nothing
when i check the hex value of both sentence even they equal
gNotice.GCNoticeSendToAll(0,0,0,0,0,0,"%.2X",lpMsg->message);
gNotice.GCNoticeSendToAll(0,0,0,0,0,0,"%.2X",gSentenceEvent.RandomSentence);
that really came different from example "בדיקהה 3" On both sides
ServerSide = 22B6970
TextFile = D9C0B0

Why a "no matching function" error for call by reference with literal number?

The problem asks to create a program that asks the user to enter some text and that text will be surrounded by asterisks depending on the width of the screen for example if the user inputs "Hello world" the output should be:
****************
* Hello World! *
****************
I've tried to create the functions but I'm stuck becaus of a compiler error with the shown minimal code.
Question: Why does it tell me no matching function for within_width(text, 80)?
Some of the code I have is below:
#include <iostream>
#include <string>
void display_header (std::string &header) {
std::string text;
header = text;
}
bool within_width (std::string& text, unsigned short int& max_width) {
}
int main() {
std::string text;
std::cout << "Please enter header text: ";
std::getline(std::cin, text);
if (within_width(text, 80)) {
// call the display_header function and pass in the text
// inputted by the user
} else {
std::cout << text;
}
return 0;
}
This declaration of the function
bool within_width (std::string& text, unsigned short int& max_width)
asks for an unsigned short int variable, because it has a reference parameter, see the second &.
To satisfy it, you need to put the value 80 into a variable and give the variable as parameter.
unsigned short int MyWidth=80;
if (within_width(text, MyWidth))
Alternatively (but I assume you are not allowed) you can use a call by value parameter
bool within_width (std::string& text, unsigned short int max_width)
Then you could call as shown.
I won't give a full answer to the exercise here, just some clues.
the display_header() and within_width() functions need to know the string given in parameters but may not modify it ; thus the type of this parameter should be const std::string & (the const was missing).
the second parameter of the within_width() function is just an integer that will be compared to the length of the string ; you don't need to pass it by reference (or at least const), rather by value. Here, the (non-const) reference prevents from passing the literal constant 80.
(it seems to be the main concern of the question after edition)
You need to reason step by step.
all of this depends on the size of the string (12 for Hello World!) ; this information is available via size(text) (or text.size())
(https://en.cppreference.com/w/cpp/iterator/size)
(https://en.cppreference.com/w/cpp/string/basic_string/size)
This size will have to be compared to max_width
Displaying the line with header will require 4 more characters because * will be prepended and * will be appended.
Thus the two surrounding lines will have the length size(header)+4 too.
In order to create such a string made of *, you could use a constructor of std::string taking two parameters : the count of characters and the character to be repeated.
(https://en.cppreference.com/w/cpp/string/basic_string/basic_string)
Send all of this to std::cout in the correct order.
Edit: Just noticing that this answer probably goes far beyond the scope of the task you have been given (just filling in some skeleton that has been provided by your teacher).
I'll still leave it here to illustrate what could be done with arbitrary input. Maybe you want to experiment a little further than what you have been asked...
bool within_width(...)
Pretty simple: string.length() <= max – just wait a second, you need to consider asterisks and spaces at beginning and end of output, so: max - 4
But you can do better, you can split the string, best at word boundaries. That's a bit difficult more difficult, though:
std::vector<std::string> lines;
// we'll be starting with an initially empty line:
auto lineBegin = text.begin();
auto lineEnd = text.begin();
for(auto i = text.begin(); i != text.end(); ++)
// stop condition empty: we'll stop from inside the loop...
{
// ok, we need to find next whitespace...
// we might try using text.find_first_of("..."), but then we
// need to know any whitespace characters ourselves, so I personally
// would rather iterate manually and use isspace function to determine;
// advantage: we can do other checks at the same time, too
auto distance = std::distance(lineBegin, i);
if(std::distance(lineBegin, i) > maxLineLength)
{
if(lineEnd == lineBegin)
{
// OK, now we have a problem: the word itself is too long
// decide yourself, do you want to cut the word somewhere in the
// middle (you even might implement syllable division...)
// or just refuse to print (i. e. throw an exception you catch
// elsewhere) - decide yourself...
}
else
{
lines.emplace_back(lineBegin, lineEnd);
lineBegin = lineEnd; // start next line...
}
}
// OK, now handle current character appropriately
// note: no else: we need to handle the character in ANY case,
// if we terminated the previous line or not
if(std::isspace(static_cast<unsigned char>(*i)))
{
lineEnd = i;
}
// otherwise, we're inside a word and just go on
}
// last line hasn't been added!
lines.emplace_back(lineBegin, lineEnd);
Now you can calculate maximum length over all the strings contained. Best: Do this right when adding a new line to the vector, then you don't need a separate loop...
You might have noticed that I didn't remove whitespace at the end of the strings, so you wouldn't need to add you own one, apart, possibly, from the very last string (so you might add a lines.back() += ' ';).
The ugly part, so far, is that I left multiple subsequent whitespace. Best is removing before splitting into lines, but be aware that you need to leave at least one. So:
auto end = text.begin();
bool isInWord = false; // will remove leading whitespace, if there is
for(auto c : text)
{
if(std::isspace(static_cast<unsigned char>(c)))
{
if(isInWord)
{
*end++ = ' '; // add a single space
isInWord = false;
}
}
else
{
*end++ = c;
isInWord = true;
}
}
This would have moved all words towards the beginning of the string, but we yet to drop the surplus part of the string yet contained:
text.erase(end, text.end());
Fine, the rest is pretty simple:
iterate over maximum length, printing a single asterisk in every loop
iterate over all of your strings in the vector: std::cout << "* " << line << "*\n";
repeat the initial loop to print second line of asterisks
Finally: You introduced a fix line limit of 80 characters. If console is larger, you just won't be using the entire available width, which yet might be acceptable, if it is smaller, you will get lines broken at the wrong places.
You now could (but that's optional) try to detect the width of the console – which has been asked before, so I won't go any deeper into.
Final note: The code presented above is untested, so no guarantee to be bugfree!

weird behaviour of strstr in qt program

I'm a beginner, made a function which takes input from lineedit converts it into a array and then searches it to find a word. If the word is found it prints successs in a label, otherwise prints error.Problem is that it every time prints error no matter what i enter.
What am I doing wrong.
void MainWindow::on_consoleEdit_returnPressed()
{
QString text = ui->consoleEdit->text();
char enteredCmd[4096];
strcpy(enteredCmd, "Some string data");
text = enteredCmd;
//enteredCmd contains all the data that text string contains
char *open = strstr(enteredCmd, "open");
if(open != NULL) {
ui->answerLabel->setText("SUCCESS");
}
else {
ui->answerLabel->setText("ERROR");
}
}
You are testing same string every time, see this:
char enteredCmd[4096];
strcpy(enteredCmd, "Some string data");
text = enteredCmd;
this overrides text value with copy of this "Some string data" string.
Anyway you made this to complicated. QString have lots of functionality useful for you.
void MainWindow::on_consoleEdit_returnPressed()
{
QString text = ui->consoleEdit->text();
if(text.contains("open")) {
ui->answerLabel->setText("SUCCESS");
} else {
ui->answerLabel->setText("ERROR");
}
}
Your code is not searching on the text from the line edit. Your code is actually searching for "open" on the string enteredCmd, which always contains "Some string data". Thus, you should always get "ERROR" printed to your answer label.
Here's what I think you are trying to do, using QString instead of strstr:
void MainWindow::on_consoleEdit_returnPressed()
{
QString text = ui->consoleEdit->text();
if(text.contains(QStringLiteral("open"))) {
ui->answerLabel->setText("SUCCESS");
}
else {
ui->answerLabel->setText("ERROR");
}
}
QString is designed to work with many languages so it requires some conversion to get text to a C style eight bit string. You might try something like this:
char *myChar = text.toLatin1().data();

Printf doesnt pop

I'm new to programming in c++ and I'm facing a problem following lynda.com tutorials. It seems okay on the tutorial video but this isnt working with me.
#include <stdio.h>
enum { max_string = 127 };
static char string[max_string + 1 ] = "";
int main( int argc, char ** argv ) {
printf("Type a string: ");
fgets(string, max_string, stdin);
printf("The string is %s", string);
return 0;
}
And when I run this something blank appears and I need when I right something like "hey" in the blanket space, this happens:
hey
Type a string: The string is hey
This is completely strange for me and I have no idea what Im doing wrong tbh.
I'm using Eclipse btw.
Could someone help me out?
It appears that your standard output stream is line-buffered, meaning that text you print doesn't appear until you've printed a complete line. It should be unbuffered if you're writing to an interactive device; perhaps something is preventing the system from being aware that the output device is interactive.
Adding
fflush(stdout);
after your first printf should force the "Type a string: " prompt to appear immediately (and even if your output is unbuffered, fflush(stdout) is harmless).
I was about to suggest changing your second printf from:
printf("The string is %s", string);
to:
printf("The string is %s\n", string);
to ensure that your program's output ends with a newline (some systems can misbehave if it isn't) -- but fgets() actually leaves the newline in your string (unless the input line was very long). Eventually you'll want to be able to deal with that kind of thing.

Arduino opening SD filename as string

I am trying to open up a file that I calculate the name into a string. However, it is just giving me compile errors as shown.
for(int i=1;;i++)
{
String temp = "data";
temp.concat(i);
temp.concat(".csv");
if(!SD.exists(temp))//no matching function for call to sdclass::exists(String&)
{
datur = SD.open(temp,FILE_WRITE);
}
}
I am a java person, so I don't see why this isn't working. I tried a few string object methods but none seem to have worked. I am a bit new at arduino programming but I understand java much better. The point of this for loop is to make a new file each time the arduino reboots.
SD.open expects a character array instead of a String, you need to convert it using the toCharArray method first. Try
char filename[temp.length()+1];
temp.toCharArray(filename, sizeof(filename));
if(!SD.exists(filename)) {
...
}
Completed Code:
for(int i=1;;i++)
{
String temp = "data";
temp.concat(i);
temp.concat(".csv");
char filename[temp.length()+1];
temp.toCharArray(filename, sizeof(filename));
if(!SD.exists(filename))
{
datur = SD.open(filename,FILE_WRITE);
break;
}
}
You will find a number of functions take char arrays instead of strings.