How to empty a string in Arduino c language - c++

I wrote the below in arduino code language (c or c++ ?)
And i got puzled, i'm not sure if this is a limitation from C or C++.
My function should split a text string and return word number x
In my function i need to clean a string variable, that resets its contend until X is reached
For readability X is called wordcount.
How do i clean the string Wordsample make it empty again ?
On a side note, if the word isnt found then this function should also return nothing
As the results are used to make other strings from.
String GetSubString (String A,int Wordcount) //for readability start counting B from 1
{ int CounterX;
String WordSampleN;
String result ;
for (int i = 0; i < A.length(); i++)
{ // split string
WordSampleN = WordSampleN + A[i];
if ((A[i] == ' ') || (A[i] =='\n'))
{ CounterX++;
if (CounterX == Wordcount)
{ result = WordSampleN;
}
if (CounterX <> WordCount)
{ WordSampleN = ''; // <== ERROR IS HERE
}
}
}
return result;}
On a side note, if possible I would like to keep use strings of any size, not fixed strings.

There is no concept of an 'empty character'. You cannot initialize your String (object) this way. Instead, use an empty (small-"s") string "";
WordSampleN = "";
This will call the String constructor that takes a c-style string, and initialize your String object with the empty string.

Related

makeValidWord(std::string word) not working properly

I'm programming a hash table thing in C++, but this specific piece of code will not run properly. It should return a string of alpha characters and ' and -, but I get cases like "t" instead of "art" when I try to input "'aRT-*".
isWordChar() return a bool value depending on whether the input is a valid word character or not using isAlpha()
// Words cannot contain any digits, or special characters EXCEPT for
// hyphens (-) and apostrophes (') that occur in the middle of a
// valid word (the first and last characters of a word must be an alpha
// character). All upper case characters in the word should be convertd
// to lower case.
// For example, "can't" and "good-hearted" are considered valid words.
// "12mOnkEYs-$" will be converted to "monkeys".
// "Pa55ive" will be stripped "paive".
std::string WordCount::makeValidWord(std::string word) {
if (word.size() == 0) {
return word;
}
string r = "";
string in = "";
size_t incr = 0;
size_t decr = word.size() - 1;
while (incr < word.size() && !isWordChar(word.at(incr))) {
incr++;
}
while (0 < decr && !isWordChar(word.at(decr))) {
decr--;
}
if (incr > decr) {
return r;
}
while (incr <= decr) {
if (isWordChar(word.at(incr)) || word.at(incr) == '-' || word.at(incr) == '\'') {
in =+ word.at(incr);
}
incr++;
}
for (size_t i = 0; i < in.size(); i++) {
r += tolower(in.at(i));
}
return r;
}
Assuming you can use standard algorithms its better to rewrite your function using them. This achieves 2 goals:
code is more readable, since using algorithms shows intent along with code itself
there is less chance to make error
So it should be something like this:
std::string WordCount::makeValidWord(std::string word) {
auto first = std::find_if(word.cbegin(), word.cend(), isWordChar);
auto last = std::find_if(word.crbegin(), word.crend(), isWordChar);
std::string i;
std::copy_if(first, std::next(last), std::back_inserter(i), [](char c) {
return isWordChar(c) || c == '-' || c == '\'';
});
std::string r;
std::transform(i.cbegin(), i.cend(), std::back_inserter(r), std::tolower);
return r;
}
I am going to echo #Someprogrammerdude and say: Learn to use a debugger!
I pasted your code into Visual Studio (changed isWordChar() to isalpha()), and stepped it through with the debugger. Then it was pretty trivial to notice this happening:
First loop of while (incr <= decr) {:
Second loop:
Ooh, look at that; the variable in does not update correctly - instead of collecting a string of the correct characters it only holds the last one. How can that be?
in =+ word.at(incr); Hey, that is not right, that operator should be +=.
Many errors are that easy and effortless to find and correct if you use a debugger. Pick one up today. :)

Recursion: swapping an e for an a in a string

My problem is that I need to do a recursion for a string and change any e for an a. Every time I enter a word it only prints out the last letter.
My code so far:
string ReplaceEsWithAs(string s)
{
if (s.length() == 1)
{
if (s == "e")
{
s = "a";
return s;
}
else
{
return s;
}
}
else
{
return ReplaceEsWithAs(s.substr(1));
}
}
The only return statements in the function are under the condition
if (s.length() == 1)
It makes sense that the function return always returns a string with one character in it.
In the recursive part, you use:
return ReplaceEsWithAs(s.substr(1));
which calls the function with all but the first character of the string.
If you call with "abcd" from main, you call with "bcd" in the recursive call, then you call with "cd", then you call with "d", which returns "d", which is returned all the way.
You are just discarding the first character in every recursive call.
You need to use:
string ReplaceEsWithAs(string s)
{
if (s.length() == 1)
{
if (s == "e")
{
return "a";
}
// No need for an else
return s;
}
// No need for an else.
return ReplaceEsWithAs(s.substr(0,1)) + ReplaceEsWithAs(s.substr(1));
}
Here is an implementation just by looping through and mutating the string:
string ReplaceEsWithAs(string s) {
for (size_t i = 0; i < s.length(); i++) {
if (s[i] == 'e') {
s[i] = 'a';
}
}
return s;
}
You can access the individual chars in a string by index using []. This code uses a standard for loop to loop through each character. (size_t is an unsigned integer type that is generally used for indices.) For each char s[i], it checks if it's 'e', and if so, sets it to 'a'. Then it just returns the changed string.
This is better than a recursive approach because
it's easier to understand at a glance
it modifies the string in-place, meaning it doesn't have to do needless substring and concatenating (+)
it uses less memory
it won't cause the call stack to overflow for a long input string
Also, the standard library provides a function to do replace operations like this. See this answer.

std::string returning inappropriate value

I wrote a program which perform string compression using counts of repeated characters. The program in C++ is :
#include<iostream>
#include<cstring>
std::string compressBad(std::string str)
{
std::string mystr = "";
int count = 1;
char last = str[0];
for (int i = 0; i < str.length();++i)
{
if(str[i] == last)
count++;
else
{
std::string lastS = last+"";
std::string countS = std::to_string(count);
mystr.append(lastS);
mystr.append(countS);
//mystr = mystr + last + count;
count = 1;
last = str[i];
}
}
std::string lastS = last+"";
std::string countS = std::to_string(count);
mystr.append(lastS);
mystr.append(countS);
return mystr;
//return mystr+last+count;
}
int main()
{
std::string str;
std::getline(std::cin, str);
std::string str2 = compressBad(str);
std::cout<<str2;
/*if (str.length() < str2.length())
std::cout<<str;
else
std::cout<<str2;*/
std::cout<<std::endl;
return 0;
}
Few example on running this are :
Input : sssaaddddd
Output : ùÿÿ*425
Output it should print : s3a2d5
Second example:
Input : sssaaddd
Output: ùÿÿ*423
Output it should print : s3a2d3
I also implemented the same concept in Java and there it is working fine. The java implementation is here
Why is this problem happening with above code.
There may be other issues in your code, but I think that this line might be to blame:
std::string lastS = last+"";
Here, you're trying to convert the character last to a string by concatenating the empty string to the end. Unfortunately, in C++ this is interpreted to mean "take the numeric value of the character last, then add that to a pointer that points to the empty string, producing a new pointer to a character." This pointer points into random memory, hence the garbage you're seeing. (Notice that this is quite different from how Java works!)
Try changing this line to read
std::string lastS(1, last);
This will initialize lastS to be a string consisting of just the character stored in last.
Another option would be to use an ostringstream:
std::ostringstream myStr;
myStr << last << count;
// ...
return myStr.str();
This eliminates all the calls to .append() and std::to_string and is probably a lot easier to read.
last + "" doesn't do what you think.
just do
mystr.append(1, last);

get all the std::string's or first word's before character '='

I wanted to retrieve all the values/words before '='
Ex:
A = my first variable, I wanted to get all the strings;
var2 = I wanted to get this variable also;
var3 = jcdksjfckjdsckjdscjkdsbckjdsncjsjd;
Now I wanted to retrieve all the variables (A, var2, var3) from the above text (c++ std::string).
Update: One possible way is
vector<string> myClass::getVariablesFromDescription(string f_description)
{
vector<string> l_variables;
stringstream l_desc;
l_desc << f_description;
string l_temp;
string l_prvStr = string();
for(int i=0; l_desc >> l_temp ; i++ )
{
if(l_temp == string("="))
{
l_variables.push_back(l_prvStr);
}
l_prvStr = l_temp;
}
return l_variables;
}
You can create a new string, start copying the original byte-by-byte there and stop when you detect a '='.
string example = "var69 = asdfghjkl";
string var_name;
for(int i=0; i<example.size(); i++)
{
if(example[i] == '=') break;
var_name += example[i];
}
I cannot comment yet, but you asked for a hint.
find returns a position of where the = sign is. You also know you started at 0. Then you can get the string from 0 to position and just copy that out.

Basic C++: convert from char to string

I'm a little confused by the class code. Here's what I'm trying to do:
//Program takes "string text" and compares it to "string remove". Any letters in
//common between the two get deleted and the remaining string gets returned.
#include <string>
#include "genlib.h"
string CensorString1(string text, string remove);
int main() {
CensorString1("abcdef", "abc");
return 0;
}
string CensorString1(string text, string remove) {
for (int i = 0; text[i]; i++){
for (int n = 0; remove[n]; n++){
if (i != n){
string outputString = ' '; //to store non repeated chars in,
//forming my return string
outputString += i;
}
}
}
return outputString;
}
I'm getting an error on the "outputString += 1" saying: "cannot convert from "char" to
std::basic_string
I'm also getting an error on the "return outputString" saying: undeclared identifier
???????
I get that I'm putting a "char" on a "string" variable but what if shortly that "char" will soon be a string? Is there a way to pass this?
I'm always forgetting libraries. Can someone recommend a couple of standard/basic libraries I should always think about? Right now I'm thinking , "genlib.h" (from class).
C++ is kicking my ass. I can't get around constant little errors. Tell me it's going to get better.
There are many errors in your code:
Your outputString needs to be in the outer scope (syntax)
You compare i to n instead of text[i] to remove[n] (semantic)
You are adding i to the output instead of text[i] (semantic)
You ignore the return of CensorString1 (semantic)
Here is your modified code:
string CensorString1(string text, string remove) {
string outputString;
for (int i = 0; text[i] ; i++){
for (int n = 0; remove[n] ; n++){
if (text[i] != remove[n]){
outputString += text[i];
}
}
}
return outputString;
}
This has some remaining issues. For example, using text[i] and remove[n] for termination conditions. It is also very inefficient, but it should be a decent start.
At any rate, strings are always double-quoted in C and C++. Single-quoted constants are char constants. Fix that and you should probably be all right.
Also, look at this SO question: How do you append an int to a string in C++?
Good luck at Stanford!
There are some problems there:
string outputString = ' '; will try to construct a string from a char, which you can't do. You can assign a char to a string though, so this should be valid:
string outputString;
outputString = ' ';
Then, outputString is only visible within your if, so it won't act as an accumulator but rather be created and destroyed.
You're also trying to add character indices to the string, instead of characters, which is not what I think you want to be doing. It seems like you're mixing up C and C++.
For example, if you want to print the characters of a string, you could do something like:
string s("Test");
for (int i=0;i<s.length();i++)
cout << s[i];
Finally, I'd say that if you want to remove characters in text that also appear in remove, you'd need to make sure that none of the characters in remove match your current character, before you add it to the output string.
This is an implementation of what I think you want, your code has multiple problems which just showed up described in multiple other answers.
std::string CensorString1(std::string text, std::string remove) {
std::string result;
for (int i = 0; i<text.length(); i++) {
const char ch = text[i];
if(remove.find(ch) == -1)
result.append(1,ch);
}
return result;
}