Issues with declaring and writing to arrays with Arduino and C++ - c++

I'm messing around with an Arduino board for the first time.
I have an array declared like this (I know don't judge me), it's for storing each character of the LCD as a sort of cache:
char* lcd_characters[] = {"","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","",""};
Then later on I'm trying to write to a specific slot of the array, like this, to save that letter to it:
new_char = String(message.charAt(i));
...blah blah blah...
lcd_characters[pos] = new_char; << error here
However it is giving me this error:
error: cannot convert 'String' to 'char*' in assignment
The funny thing is when I do this (below) it do assign the letter to it, however I have a var which is a single letter but can't assign it.
lcd_characters[pos] = "H";
Can someone help me out please. Thanks. I'm brand new to C and been ok so far.
Basically I want an array of characters and then I want to write on the array positions with a new value.
Why does it even matter what type of string I'm writing to that array position, I should be able to write a number or boolean there too and call it later. Is there something wrong with the way the array is declared initially?
Edit:
I tried...
lcd_characters[pos] = new_char.c_str();
however that's giving me the similar error:
invalid conversion from 'const char*' to 'char'
Wtf? All I want to do is say this array position equals this new value. That's it. I've done this a million times in javascript, ruby, python (even php) etc. I just want to go, this array... x[12] equals my letter in new_char !!!! Ahh.

A few remarks:
Are you using C or C++? String is a C++ class, but you are creating a an array of c strings (char *).
You are creating an array of strings (char* var[] equals to char**), but your naming suggests you want an array of characters. A c string is basically an array of characters, so stick with that (char * or char []).
I would recommend you go for only C code in this case:
char lcdChars[4] = {' ', ' ', ' ', ' '}; // init with spaces
lcdChars[2] = 'x'; // write x to position 3
Note: A string in C++ can output a C string (char *) by calling stringInstance.c_str().

Related

How to create a C++ multidimensional array of names with basic types

I'm trying to instantiate and easily access an array of names in C++ using basic types in contiguous memory. I'm astounded that this is extremely difficult or complicated to do in C++ WITH ONLY basic types.
For some background, I am programming a microcontroller with limited memory, modest processing power, and it is handling serial communication over a network to 36 other microcontrollers sending continuous sensor data which is uploaded to a webserver. The shorter the refresh rate of the data, the better, so I prefer basic program features.
Not that I'm saying the more complicated stuff I've looked in other forums for, like an array of strings, has worked.
In my desperation, I was able to get this to work.
char names_array[] = "Bob\0\0Carl";
printf("%s",names_array); //outputs Bob
printf("%s",names_array + 5); //outputs Carl
This is a horrible solution though. My indexing is dependent on the longest name in the array, so if I added "Megan" to my list of names, I'd have to add a bunch of null characters throughout the entire array.
What I want to do is something like this:
char names_array[2] = {"Bob","Carl"}; //does not compile
printf("%s",names_array[0]);
printf("%s",names_array[1]);
//Error: A value of type "const char *" cannot be used to
//initialize an entity of type "char" in "main.cpp"
but that didn't work.
I want to loop through the names in my list and do something with each name, so at this point, this is my best solution.
char name0[] = "Bob";
loop_code(name0);
char name1[] = "Carl";
loop_code(name1);
.
.
.
I expect there's a reasonable way to make an array of pointers, each to an array of char terminated by null(s). I must be doing something wrong. I refuse to believe that a language like C++ is incapable of such a basic memory allocation.
You can, e.g., get an array of pointers to null-terminated strings:
const char* names_array[] = { "Bob", "Carl" };
and then
std::printf("%s", names_array[0]);
std::printf("%s", names_array[1]);
The problem with your attempt
char names_array[2] = {"Bob","Carl"};
is that you declare names_array to be an array of characters. This should never compile because what the = {"Bob","Carl"} essentially attempts to do is initialize each character in that array of characters with an entire array of characters of its own. A character is just a character, you cannot assign an entire array of characters to just an individual character. More precisely, initialization of a character array from a string literal is a special case of initialization [dcl.init.string] that allows a single string literal to be used to initialize an entire character array (because anything else doesn't make sense). What you actually want would be something more like an array of character arrays. However, the problem there is that you'd have to effectively pick a fixed maximum length for all strings in the array:
char names_array[][5] = { "Bob", "Carl" }; // each subarray is 5 characters in length
which would be potentially wasteful. You can flatten a series of multiple strings into one long array and then index into that, like you did with your first approach. The downside of that, as you've found out, is that you then need to know where each string starts in that array…
If you just want an array of string constants, a more modern C++ approach would be something like this:
#include <string_view>
using namespace std::literals;
constexpr std::string_view names[] = {
"Bob"sv,
"Carl"sv
};
The advantage of std::string_view is that it also has information about the length of the string. However, while std::string_view is compatible with most of the C++ standard library facilities that handle strings, it's not so simple to use it together with functions that expect C-style null-terminated strings. If you need null-terminated strings, I'd suggest to simply use an array of pointers to strings as shown at the very beginning of this answer…
char can has only one character.
If you want to use char, you can do it like
char name0[3] = "Bob";
char name1[4] = "Carl";
char *nameptr[2] = {&name0[0], &name1[0]};
Acutally, this pretty hard.
I suggest to you, use std::string.
std::string name[2] = {"Bob","Carl"};
this code is acceptable.

How to properly remove a character from a char array (with or without converting to a string)?

Sorry in advance for any possible duplicate question. I have been Googling a solution for my compiler error, for a week now, tried different workarounds from various answers around here, yet I keep getting some errors.
I am currently learning C++, trying to build a program that does basic stuff like vowel/consonant count, letter removal etc. Everything works fine until I get to the custom letter removal part. Basically, it's near impossible to do that using character functions (according to my knowledge), while converting to a string seems to spawn other kinds of errors.
Here is the code fragment where I keep getting errors:
if (strcmp (service, key4) ==0)
{
string str(s);
cout<<endl<<"Please insert the letter you would like removed from your "<<phrasal<<":"<<endl;
cin>>letterToRemove;
s.erase(remove(s.begin(), s.end(),letterToRemove), s.end());
cout<<endl<<s<< "\n"<<endl;
}
and here are initialized variable I used:
int main()
{
char s[1000], phrasal[10], service[50], key1[] = "1", key2[] = "2", key3[] = "3", key4[] = "4", key5[] = "5", key6[] = "6", key0[] = "0", *p, letterToRemove;
int vowel=0, vowel2=0, consonant=0, consonant2=0, b, i, j, k, phrase=0, minusOne, letter, idxToDel;
void pop_back();
char *s_bin;
As you can see, the original 's' is a char array. In the first code sample I have tried converting it into a string array (string str(s)), but that results in the following compiling errors:
error: request for member 'erase' in 's', which is of non-class type 'char[1000]'
error: request for member 'begin' in 's', which is of non-class type 'char[1000]'
error: request for member 'end' in 's', which is of non-class type 'char[1000]'
error: request for member 'end' in 's', which is of non-class type 'char[1000]'
The other workaround I've tried was this:
if(strcmp(service, key4)==0)
{std::string s(s);
cout<<endl<<"Please insert the letter you would like removed from your "<<phrasal<<":"<<endl;
cin>>letterToRemove;
s.erase(remove(s.begin(), s.end(),letterToRemove), s.end());
cout<<endl<<s<< "\n"<<endl;
}
Now here's the funny part, I get no errors whatsoever for this one, but the debug crashes as soon as I select the custom letter removal feature. Here's what it says:
"terminate called after throwing an instance of 'std::length_error'
what(): basic_string::_S_create
         This application has requested the Runtime to terminate it in an unusual way. Please contact the application's support team for more information."
Any help would be much appreciated, stuck at this one for a week now!
P.S. Is it okay if I or a moderator deletes this question after it's been answered? I'm quite sure I'm not the first one who asks this, but, as before-hand mentioned, I keep getting these errors, even after following answers from similar questions.
For a char array you have to use
std::remove instead of erase, and insert the null-terminator manually:
auto newEnd = std::remove(std::begin(s), std::end(s), letterToRemove);
*newEnd = '\0';
If you have a generic array, that may or may not have decayed to a pointer, and you have the number of elements in the array but no other terminator (i.e. it's not a C-style zero-terminated string), then here's a solution:
First I want to you think abut how the array looks in memory. For example if we have an array of characters
char array[X] = { 'A', 'B', 'C', 'D', ... };
This array will look like this in memory
+---+---+---+---+-----+
| A | B | C | D | ... |
+---+---+---+---+-----+
If you wanted to remove the letter 'B' from that array you find the position of the letter, then you copy the next letter ('C') into its place, and the next next letter ('D') into the next letter place, etc.
You can of course do this using a single loop:
size_t index_to_remove = 1; // The index of 'B'
for (size_t i = index_to_remove = 1; i < element_count - 1; ++i)
array[i] = array[i + 1];
The above loop is simple, easy to figure out, and easy to step through in a debugger. It is also not very effective, especially if the array is large.
All the above copying can actually be done using a single call to the memmove function:
memmove(&array[index_to_remove],
&array[index_to_remove + 1],
element_count - index_to_remove - 1);
The above call will basically do the same as our loop above but in a more efficient and optimized way.
Using either of the above methods, the loop or the memmove call, will leave the array like this:
+---+---+---+-----+
| A | C | D | ... |
+---+---+---+-----+
Important note: Remember to change element_count after you "removed" the character, so it reflects the new size.
For your first workaround :
string str(s);
This statement declare a string named str and is content is initialized with the content of s
This statement as no effect on you object s
So you need to call str.erase() not s.erase()

Is this the correct syntax for an array of pointers to size-3 character arrays?

I'm trying to make my own version of an "Autocorrect" program that checks for words that are similar to a given word. To accomplish this, I need to look at distances between letters on a standard keyboard, so that I have a metric for how "close" a word is to another word.
In my program I've started to write an array
const char[3]* KEY_DISTS[] = { "aa0", "ab5", "ba5", "ac3", "ca3", "ad2", "da2" ,... };
which is supposed to mean "The distance between 'a' and 'a' is 0, the distance between 'a' and 'b' is 5, the distance between 'b' and 'a' is 5, " etcetera.
That information I will next put in a map that maps pairs of characters to integers, but I'm wondering whether it's written correctly so far and whether you have any suggestions for me.
const char[3]* KEY_DISTS[]
should mean "A constant array of pointers to character arrays of size 3", right?
The declaration matching the title would be:
const char (*arr[])[4] = { &"aa0" };
Note that "arr" is an array of four chars (it includes terminating '\0') and that you need to take the address of string literal (which are lvalues and have static storage duration, so this is fine).
Sounds like you could have a 2D array instead:
const char arr[][4] = { "aa0" };

C++ comparing a char to a string literal [duplicate]

This question already has answers here:
c++ compile error: ISO C++ forbids comparison between pointer and integer
(5 answers)
Closed 5 years ago.
Beginning programmer here...
I'm writing a very simply program for my computer science class and I ran into an issue that I'd like to know more about. Here is my code:
#include <iostream>
using namespace std;
int main(int argc, const char * argv[])
{
char courseLevel;
cout << "Will you be taking graduate or undergraduate level courses (enter 'U'"
" for undergraduate,'G' for graduate.";
cin >> courseLevel;
if (courseLevel == "U")
{
cout << "You selected undergraduate level courses.";
}
return 0;
}
I'm getting two error messages for my if statement:
1) Result of comparison against a string literal is unspecified (use strncmp instead).
2) Comparison between pointer and integer ('int' and 'const char*').
I seem to have resolved the issue by enclosing my U in single quotes, or the program at least works anyway. But, as I stated, I'd simply like to understand why I was getting the error so I can get a better understanding of what I'm doing.
You need to use single quotes instead.
In C, (and many other languages) a character constant is a single character1 contained in single quotes:
'U'
While a string literal is any number of characters contained in double quotes:
"U"
You declared courseLevel as a single character: char courseLevel; So you can only compare that to another single char.
When you do if (courseLevel == "U"), the left side is a char, while the right side is a const char* -- a pointer to the first char in that string literal. Your compiler is telling you this:
Comparison between pointer and integer ('int' and 'const char*')
So your options are:
if (courseLevel == 'U') // compare char to char
Or, for sake of example:
if (courseLevel == "U"[0]) // compare char to first char in string
Note for completeness: You can have mulit-character constants:
int a = 'abcd'; // 0x61626364 in GCC
But this is certainly not what you're looking for.
Rapptz is right, but I think some more elaboration should help...
courseLevel == "U"
In C and C++, double-quotes create string literals - which are arrays of characters finishing with a numerical-0 ASCII-NUL terminating sentinel character so programs can work out where the text ends. So, you basically are asking if a character is equal to an array of characters... they just can't be compared. Similar questions that are valid are:
does this character variable hold a specific character value: courseLevel == 'U'
does this character variable appear in a specific array: strchr(courseLevel, "U")
does this character variable match the first element in a specific array: courseLevel == "U"[0]
Of course, the first one of these is the one that makes intuitive sense in your program.
The reason why you get an error is because string literals in C and C++ end with a null terminated character \0 while single characters don't. So when you compare to a char to a string literal you're comparing the character literal to a char array {'U','\0'}.

Conversion from int to char to display ncurses key bindings

I'm working on a little console game with ncurses. In the main menu I want the user to be able to set the control keys. Now as far as I understood, in ncurses you can access e.a. the a-key by the int value of the char 'a'. Using the key ingame with 'a' works flawlessly, however I'm stuck with the menu:
For each key binding I have stored an int-value that is defaulted to e.a. 'a'. When the game starts, I read the 'a' binding correctly from the int-value and can use it ingame. However, it is not displayed correctly. I want it to be like this: "Left: a". I do it like this:
std::string key = "Left: " + static_cast<char>(_value);
_value being the int-value I stored and initialized as 'a'. I also tried it without the cast, btw.
Now what's being displayed is strange. Instead of "a" it says "~T^C". For the letters "s" and "d" it doesn't display anything at all. "w" becomes some very strange encoding question marks.
I suppose it's got something to do with the encoding of the characters in int-values or something. So what can I do to get it displayed the right way?
Thanks a lot!
You're adding together the adress of string literal and ASCII value of _value. String key is then constructed from whatever happens to be at that garbage adress.
Remember that string literals are of type array of N const char and that arrays decay to pointer to their first element when passed to functions and operators etc., which yields you const char*. The built in + operator for pointers doesn't do string concatenation. You need to construct a std::string from at least one of operands for overloaded operator to kick in:
std::string key = std::string("Left: ") + static_cast<char>(_value);