We are trying to initialize a character array but it we get an error saying that we can not as we can not mix integers and chars, but we dont have have integers initialized.
thanks in advance
void setup()
{
Serial.begin(9600); //Set the serial monitor.
lcd.begin(16, 2); //Set the LCD
}
char line1 [5] = {0};
char line2 [] = {0};
void loop()
{
if (Serial.available() > 0) { //If the serial monitor is open it will read a value.
line1 = Serial.read();
delay(10);
Serial.print(line1);
lcd.print(line1);
}
}
I am not an arduino guy, but I did stay at a Holiday Inn last night with access to Google :)
http://arduino.cc/en/Serial/Read
Serial.read() returns a single byte (as an int). You're trying to assign that to a char array.
You can't do that. You can assign something to a specific element in an array:
line1[0] = 'c';
for example, but you can't assign to an array itself.
It seems like you're looking for Serial.readBytes()
http://arduino.cc/en/Serial/ReadBytes
Which would look like:
Serial.readBytes(line1, 5);
in your case where 5 is the length of your buffer (array). This would read (at most) 5 bytes into your line1 buffer.
Edit to add: That being said, it appears arduino's "C-Like" language is very much like C in that it expects "Strings" (char arrays) to be null terminated when passing them to Serial.print(). The advice above doesn't do that and in fact would cause problems.
What you would need to do is read up to one byte less than the length of your array, and then null terminate the "string" using the number of bytes actually read which is what bytesRead() returns to you (arrays are zero indexed):
int numBytesRead = 0;
...
numBytesRead = Serial.readBytes(line1, 4);
line1[numBytesRead] = '\0';
Serial.print(line1);
Option B is to do as I originally mentioned, but loop and print one byte at a time from your line1 array using the index:
int numBytesRead = 0;
numBytesRead = Serial.readBytes(line1, 5);
int i;
for (i = 0; i < numBytesRead; i++) {
Serial.print(line1[i]);
}
According to the docs Serial.print() automagically knows to send a single byte/char when that's all that's passed to it.
Related
I am trying to convert uint8_t readData[10] = "123456789" ; to unsigned long to do some math on this value, in Arduino. I'm using strtoul function. strtoul works fine if I define above array by my self and it converts this array to unsigned long successfully. But if I put some values in this array by reading DS1307 NVRAM, then strtoul fails to convert the array into unsigned long and gives 0 answer. I checked values in readData array, after reading NVRAM, using for loop, and found that values are same that i have saved in the NVRAM.
I am using NodeMCU board along with DS1307. My code and its Output is given below.
// Example of using the non-volatile RAM storage on the DS1307.
// You can write up to 56 bytes from address 0 to 55.
// Data will be persisted as long as the DS1307 has battery power.
#include "RTClib.h"
RTC_DS1307 rtc;
uint8_t readData[9] = "0"; //**this will store integer values from DS1307 NVRAM.
unsigned long convertedL1 = 0; //this will store converted value
uint8_t savedData[10] = "123456789"; //I have already filled this array for testing strtoul function.
unsigned long convertedL2 = 0; //this will store converted value of savedData array
void setup () {
Serial.begin(9600);
delay(3000);
#ifndef ESP8266
while (!Serial); // wait for serial port to connect. Needed for native USB
#endif
if (! rtc.begin()) {
Serial.println("Couldn't find RTC");
delay(3000);
while(1);
}
rtc.readnvram(readData,9,2); //Read NVRAM from address 2 to 11.
delay(20);
Serial.println("Prinitng values( using loop) stored in readData array, after reading NVRAM :");
for (int i = 0; i <9; i++) {
Serial.print(readData[i]);
}
Serial.println();
//Converting both arrays of same type using stroul
convertedL1 = (unsigned long)strtoul((char *)&readData[0],NULL,10);
convertedL2 = (unsigned long)strtoul((char *)&savedData[0],NULL,10);
Serial.print("converted value of readData array = ");
Serial.println(convertedL1);
Serial.println();
Serial.print("converted value of savedData array = ");
Serial.println(convertedL2);
}//setup end
void loop () {
// Do nothing in the loop.
}
the Output on Serial Monitor is:
Prinitng values( using loop) stored in readData array, after reading NVRAM :
123456789
converted value of readData array = 0
converted value of savedData array = 123456789
Why strtoul function works with one array and not with other.I searched many forums but couldn't find any solution.
Can anyone, please have a look at my code and kindly suggest me the solution. Any help will be highly appreciated.
Seems likely the reason for the difference is that your savedData array is null terminated but your readData array is not. strtoul requires that the array be null terminated.
Change your code like this
uint8_t readData[10] = "0"; // one extra byte for null terminator
...
rtc.readnvram(readData,9,2); //Read NVRAM from address 2 to 11.
readData[9] = '\0'; // add the null terminator
I was work with system, that read some symbols from the specific keyboard, pass it to the ATmega8, and then pass it to the display one-by-one(this step work correctly), but if I want to show all symbols array, I discovered that the dynamic array on first position save null, on the second save empty symbol, and the subsequent characters saved correctly. I don't see any mistakes in code, so I need a help.
This code function must return the 4-elements char array of symbols reading serial from the keyboard.
char* askPass(void){
int i;
char key;
#define PS 4
char* pass = (char*)calloc(PS, sizeof(char));
clear:
lcd_clear();
lcd_gotoxy(0, 0);
lcd_puts("Enter the password:");
lcd_gotoxy(0, 1);
lcd_puts(">>");
free(pass);
pass = (char*)calloc(0, sizeof(char));
for (i=0;i<PS;i++) pass[i] = '';
for (i=0; i<PS; i++) {
key = '-';
key = readKey();
lcd_gotoxy(3+i, 1);
if (key == 'C') {
goto clear;
} else if (key == '-'){
lcd_putchar('|');
delay_ms(10);
lcd_gotoxy(3+i, 1);
lcd_putchar(' ');
delay_ms(10);
lcd_gotoxy(3+i, 1);
i--;
} else {
pass = (char*)realloc(pass, i*sizeof(char));
*(pass+i) = key;
lcd_putchar(*(pass+i));
delay_ms(20);
}
}
/// there is an error:
/// serial input: 1234
/// lcd output: !* 34!
/// correct output: !1234!
lcd_gotoxy(0,2);
lcd_puts("!");
for (i=0; i<PS; i++) {
if (!(*(pass+i))) lcd_putchar('*');
else lcd_putchar(*(pass+i));
}
lcd_puts("!");
// end error block
return pass;
} // can't return correct array value
/*
All tests show this:
Serial input word: abcd
Output: !* cd!
Correct output: !abcd!
*/
You start my allocating 4 bytes with:
char* pass = (char*)calloc(PS, sizeof(char));
Then you call free(pass) before you even use the allocated data, only to then allocates zero bytes with:
pass = (char*)calloc(0, sizeof(char));
If makes no sense to allocate only to free without using the allocation, or to allocate zero bytes. The act of allocating zero bytes is undefined, but nothing good or useful will happen by attempting to write to such an allocation as you do.
Continuously reallocation to add one byte at a time is ill-advised also. It would be better to allocate a buffer of a reasonable length to start with and if you need to extend, extend by a number of characters in on chunk.
It is unclear in any case why you are dynamically allocating and reallocating to allow input of an arbitrary number of characters that you are not using. It would be simpler and more deterministic, to simply accept the four characters in a fixed length array and discard any extraneous input.
There is no such thing as an "empty character", calloc already initialised the allocation to zero (a nul character).
I am pretty certain this code has many other issues, but it is had to determine what you are trying to do in order to advise; you would well to use a debugger.
I've been searching for ways of emptying a char array in C/C++. I have come up with this code:
char testName[20];
for(int i = 0; i < sizeof(testName); ++i)
{
testName[i] = (char)0;
}
It has been working for a while now but when I try to strlenthe result is always two more than the typed in word. For instance I input the word dog the output would be five. Why is that so? Is my char array not cleared?
Here is my code:
char testName[20];
void loop()
{
if(Serial.available())
{
Serial.println("Waiting for name...");
index = 0;
for(int i = 0; i < sizeof(testName); ++i)
{
testName[i] = (char)0;
}
while(Serial.available())
{
char character = Serial.read();
testName[index] = character;
index++;
}
Serial.print("Name received: ");
Serial.println(testName);
Serial.print("The sentence entered is ");
Serial.print(strlen(testName));
Serial.println(" long");
delay(1000);
}
delay(1000);
}
Screenshot of the output:
Output as text:
Name received: dog
The sentence entered is 5 characters long
Don't use C style arrays in modern C++. When you require a fixed size array, use std::array instead. From a memory storage point of view, they are identical.
You can then clear the array with: myarray.fill('\0')
If your definition of "emptying char array" is set all elements of an array to zero, you can use std::memset.
This will allow you to write this instead of your clear loop:
const size_t arraySize = 20; // Avoid magic numbers!
char testName[arraySize];
memset(&(testName[0]), 0, arraySize);
As for "strange" results of strlen():
strlen(str) returns "(...) the number of characters in a character array whose first element is pointed to by str up to and not including the first null character". That means, it will count characters until it finds zero.
Check content of strings you pass to strlen() - you may have white characters there (like \r or \n, for example), that were read from the input stream.
Also, an advice - consider using std::string instead of plain char arrays.
Small note: memset() is often optimized for high performance. If this in not your requirement, you can also use std::fill which is a more C++ - like way to fill array of anything:
char testName[arraySize];
std::fill(std::begin(testName), std::end(testName), '\0');
std::begin() (and std::end) works well with arrays of compile-time size.
Also, to answer #SergeyA's comment, I suggest to read this SO post and this answer.
Yet another quick way of filling an array with zeroes, in initialization only:
char testName[20] = {};
same as
char testName[20] = {0};
Since it is a C99 feature, compiler could complain with the following
warning: ISO C forbids empty initializer braces
More here.
Anyway, looking at the OP code, there's no need at all of initializing/filling the array, it could be better like this:
#define MAX_LENGTH 20
char testName[MAX_LENGTH];
void loop()
{
if(Serial.available())
{
Serial.println("Waiting for name...");
index = 0;
while(Serial.available())
{
if(index < MAX_LENGTH)
testName[index++] = Serial.read();
}
if(index < MAX_LENGTH)
{
testName[index] = 0;
Serial.print("Name received: ");
Serial.println(testName);
Serial.print("The sentence entered is ");
Serial.print(strlen(testName));
Serial.println(" long");
}
else
Serial.print("Name too long ...");
delay(1000);
}
delay(1000);
}
For posterity. The OP example is an Arduino sketch. Assuming here that the input is taken through the built-in Serial Monitor of the Arduino IDE. At the bottom of the Serial Monitor window is a pop-up menu where the line ending can be selected as:
No line ending
newline
Carriage return
Both NL & CR
Whatever option is selected in this menu is appended to whatever is entered in the box at the top of the Serial Monitor when the Send button is clicked or the return key is hit. So the extra two characters are most certainly the result of having the "Both NL & CR" menu option selected.
Picking the "No line ending" option will solve the problem.
FWIW, in this application, the array does not need to be "cleared". Just append a '\0' char to the last char received to make it a C-string and all will be good.
I'm working on my project and now I'm stuck with a problem that is, how can I convert a char array to a byte array?.
For example: I need to convert char[9] "fff2bdf1" to a byte array that is byte[4] is 0xff,0xf2,0xbd,0xf1.
Here is a little Arduino sketch illustrating one way to do this:
void setup() {
Serial.begin(9600);
char arr[] = "abcdef98";
byte out[4];
auto getNum = [](char c){ return c > '9' ? c - 'a' + 10 : c - '0'; };
byte *ptr = out;
for(char *idx = arr ; *idx ; ++idx, ++ptr ){
*ptr = (getNum( *idx++ ) << 4) + getNum( *idx );
}
//Check converted byte values.
for( byte b : out )
Serial.println( b, HEX );
}
void loop() {
}
The loop will keep converting until it hits a null character. Also the code used in getNumonly deals with lower case values. If you need to parse uppercase values its an easy change. If you need to parse both then its only a little more code, I'll leave that for you if needed (let me know if you cannot work it out and need it).
This will output to the serial monitor the 4 byte values contained in out after conversion.
AB
CD
EF
98
Edit: How to use different length inputs.
The loop does not care how much data there is, as long as there are an even number of inputs (two ascii chars for each byte of output) plus a single terminating null. It simply stops converting when it hits the input strings terminating null.
So to do a longer conversion in the sketch above, you only need to change the length of the output (to accommodate the longer number). I.e:
char arr[] = "abcdef9876543210";
byte out[8];
The 4 inside the loop doesn't change. It is shifting the first number into position.
For the first two inputs ("ab") the code first converts the 'a' to the number 10, or hexidecimal A. It then shifts it left 4 bits, so it resides in the upper four bits of the byte: 0A to A0. Then the second value B is simply added to the number giving AB.
Assuming you want to parse the hex values in your string, and two letters always make up one byte value (so you use leading zeros), you can use sscanf like this:
char input[] = "fff2bdf1";
unsigned char output[4];
for (int i=0; i<4; i++) {
sscanf(&input[i*2], "%02xd", &data[i]);
}
Just shift 0 or 1 to its position in binary format :)
char lineChars[8] = {1,1,0,0,0,1,0,1};
char lineChar = 0;
for(int i=0; i<8;i++)
{
lineChar |= lineChars[i] << (7-i);
}
Example 2. But is not tested!
void abs()
{
char* charData = new char;
*charData = 'h';
BYTE* byteData = new BYTE;
*byteData = *(BYTE*)charData;
}
Hello I have a chunk of memory (allocated with malloc()) that contains bits (bit literal), I'd like to read it as an array of char, or, better, I'd like to printout the ASCII value of 8 consecutively bits of the memory.
I have allocated he memory as char *, but I've not been able to take characters out in a better way than evaluating each bit, adding the value to a char and shifting left the value of the char, in a loop, but I was looking for a faster solution.
Thank you
What I've wrote for now is this:
for allocation:
char * bits = (char*) malloc(1);
for writing to mem:
ifstream cleartext;
cleartext.open(sometext);
while(cleartext.good())
{
c = cleartext.get();
for(int j = 0; j < 8; j++)
{ //set(index) and reset(index) set or reset the bit at bits[i]
(c & 0x80) ? (set(index)):(reset(index));//(*ptr++ = '1'):(*ptr++='0');
c = c << 1;
}..
}..
and until now I've not been able to get character back, I only get the bits printed out using:
printf("%s\n" bits);
An example of what I'm trying to do is:
input.txt contains the string "AAAB"
My program would have to write "AAAB" as "01000001010000010100000101000010" to memory
(it's the ASCII values in bit of AAAB that are 65656566 in bits)
Then I would like that it have a function to rewrite the content of the memory to a file.
So if memory contains again "01000001010000010100000101000010" it would write to the output file "AAAB".
int numBytes = 512;
char *pChar = (char *)malloc(numBytes);
for( int i = 0; i < numBytes; i++ ){
pChar[i] = '8';
}
Since this is C++, you can also use "new":
int numBytes = 512;
char *pChar = new char[numBytes];
for( int i = 0; i < numBytes; i++ ){
pChar[i] = '8';
}
If you want to visit every bit in the memory chunk, it looks like you need std::bitset.
char* pChunk = malloc( n );
// read in pChunk data
// iterate over all the bits.
for( int i = 0; i != n; ++i ){
std::bitset<8>& bits = *reinterpret_cast< std::bitset<8>* >( pByte );
for( int iBit = 0; iBit != 8; ++iBit ) {
std::cout << bits[i];
}
}
I'd like to printout the ASCII value of 8 consecutively bits of the memory.
The possible value for any bit is either 0 or 1. You probably want at least a byte.
char * bits = (char*) malloc(1);
Allocates 1 byte on the heap. A much more efficient and hassle-free thing would have been to create an object on the stack i.e.:
char bits; // a single character, has CHAR_BIT bits
ifstream cleartext;
cleartext.open(sometext);
The above doesn't write anything to mem. It tries to open a file in input mode.
It has ascii characters and common eof or \n, or things like this, the input would only be a textfile, so I think it should only contain ASCII characters, correct me if I'm wrong.
If your file only has ASCII data you don't have to worry. All you need to do is read in the file contents and write it out. The compiler manages how the data will be stored (i.e. which encoding to use for your characters and how to represent them in binary, the endianness of the system etc). The easiest way to read/write files will be:
// include these on as-needed basis
#include <algorithm>
#include <iostream>
#include <iterator>
#include <fstream>
using namespace std;
// ...
/* read from standard input and write to standard output */
copy((istream_iterator<char>(cin)), (istream_iterator<char>()),
(ostream_iterator<char>(cout)));
/*-------------------------------------------------------------*/
/* read from standard input and write to text file */
copy(istream_iterator<char>(cin), istream_iterator<char>(),
ostream_iterator<char>(ofstream("output.txt"), "\n") );
/*-------------------------------------------------------------*/
/* read from text file and write to text file */
copy(istream_iterator<char>(ifstream("input.txt")), istream_iterator<char>(),
ostream_iterator<char>(ofstream("output.txt"), "\n") );
/*-------------------------------------------------------------*/
The last remaining question is: Do you want to do something with the binary representation? If not, forget about it. Else, update your question one more time.
E.g: Processing the character array to encrypt it using a block cipher
/* a hash calculator */
struct hash_sha1 {
unsigned char operator()(unsigned char x) {
// process
return rc;
}
};
/* store house of characters, could've been a vector as well */
basic_string<unsigned char> line;
/* read from text file and write to a string of unsigned chars */
copy(istream_iterator<unsigned char>(ifstream("input.txt")),
istream_iterator<char>(),
back_inserter(line) );
/* Calculate a SHA-1 hash of the input */
basic_string<unsigned char> hashmsg;
transform(line.begin(), line.end(), back_inserter(hashmsg), hash_sha1());
Something like this?
char *buffer = (char*)malloc(42);
// ... put something into the buffer ...
printf("%c\n", buffer[0]);
But, since you're using C++, I wonder why you bother with malloc and such...
char* ptr = pAddressOfMemoryToRead;
while(ptr < pAddressOfMemoryToRead + blockLength)
{
char tmp = *ptr;
// temp now has the char from this spot in memory
ptr++;
}
Is this what you are trying to achieve:
char* p = (char*)malloc(10 * sizeof(char));
char* p1 = p;
memcpy(p,"abcdefghij", 10);
for(int i = 0; i < 10; ++i)
{
char c = *p1;
cout<<c<<" ";
++p1;
}
cout<<"\n";
free(p);
Can you please explain in more detail, perhaps including code? What you're saying makes no sense unless I'm completely misreading your question. Are you doing something like this?
char * chunk = (char *)malloc(256);
If so, you can access any character's worth of data by treating chunk as an array: chunk[5] gives you the 5th element, etc. Of course, these will be characters, which may be what you want, but I can't quite tell from your question... for instance, if chunk[5] is 65, when you print it like cout << chunk[5];, you'll get a letter 'A'.
However, you may be asking how to print out the actual number 65, in which case you want to do cout << int(chunk[5]);. Casting to int will make it print as an integer value instead of as a character. If you clarify your question, either I or someone else can help you further.
Are you asking how to copy the memory bytes of an arbitrary struct into a char* array? If so this should do the trick
SomeType t = GetSomeType();
char* ptr = malloc(sizeof(SomeType));
if ( !ptr ) {
// Handle no memory. Probably should just crash
}
memcpy(ptr,&t,sizeof(SomeType));
I'm not sure I entirely grok what you're trying to do, but a couple of suggestions:
1) use std::vector instead of malloc/free and new/delete. It's safer and doesn't have much overhead.
2) when processing, try doing chunks rather than bytes. Even though streams are buffered, it's usually more efficient grabbing a chunk at a time.
3) there's a lot of different ways to output bits, but again you don't want a stream output for each character. You might want to try something like the following:
void outputbits(char *dest, char source)
{
dest[8] = 0;
for(int i=0; i<8; ++i)
dest[i] = source & (1<<(7-i)) ? '1':'0';
}
Pass it a char[9] output buffer and a char input, and you get a printable bitstring back. Decent compilers produce OK output code for this... how much speed do you need?