serial stream and defined variables - c++

Hopefully an easy question from the newb...
If I have a defined variable:
#define LOCK_OUT 0xA00A
and I use it in a serial stream like this:
iprintf("%s Sent to the system. \r\n", LOCK_OUT);
on my serial terminal, will I see the text representation of LOCK_OUT or the numeric representation? For instance:
"LOCK_OUT Sent to the system."
in particular, I have a loop that checks an array of defined macros, and I want to use the selected macro (once found) in the output serial stream. so this would be the loop:
int UDPDATA;
for (int i = 0, i < UDP_Size; i++)
{
if (MACRO_ARRAY[i] == UDPDATA iprintf("%s Sent to system \r\n", MACRO_ARRAY[i]);
}
and I want the macro name sent to the serial stream, not the value it represents. I hope I'm explaining this correctly...
vs
"0xA00A Sent to the system."
I'm looking to do the first, not sure if it's possible... Thanks!

Because, macros are substitutions, you would have to do something like this:
#include <stdio.h>
#define STRINGIFY(x) #x
#define LOCK_OUT 0xA00A
int main() {
// %#04x prints 4 hexadecimal places
printf("%s %#04x Sent to the system. \r\n", STRINGIFY(LOCK_OUT), LOCK_OUT);
return 0;
}

Nope, what #define macro does is pure substitution without semantic parsing.
If you define LOCK_OUT as 0xA00A, the compiler will replace LOCK_OUT with 0xA00A first, and then interprete it as a integer value.

Related

printf all characters in a string using HEX i.e. printf("%X", string.c_str())

I'm on an embedded Linux platform which uses C++ but also printf for logging.
I receive data in string type - "\241\242" - but they're unprintable characters.
On the sender side, I type in a hex number in string format i.e. "A1A2" but the sender encodes it as the number 0xA1A2 so on the receiver, I cannot use printf("%s", thing.c_str())
I can use printf("%X") but only for one character at a time in a for loop printf("%X", thing[i]). The for-loop would be ok except that since I need to use the logging macro, each hex character comes out on a separate line.
QUESTION
Is there a way to use ONE printf("%X") to print all the characters in the string as hex?
Something like printf("%X\n", uuid.c_str());
The output of below code.
500E00
A1A2
I think it's printing the pointer from .c_str() as a hex number.
// Example program
#include <iostream>
#include <string>
using namespace std;
int main()
{
string uuid = "\241\242";
printf("%X\n", uuid.c_str());
for(int i=0; i < uuid.size(); i++)
{
printf("%hhX", uuid[i]);
}
}
Is there a way to use ONE printf("%X") to print all the characters in the string as hex?
No.
Is there a way
You can write your own printf with your own specifier that will do whatever you want. You might be interested in printk used in linux kernel for inspiration, I think that would be %*pEn or %*ph or %*phN.
On glibc you can add your own format specifier https://www.gnu.org/software/libc/manual/html_node/Customizing-Printf.html .

Reading large strings in c++ [duplicate]

I am trying to read in a string of length in 10^5 order. I get incorrect string if the size of string grows beyond 4096.
I am using the following code
string a;
cin>>a;
This didn't work then I tried reading character by character by following code
unsigned char c;
vector<unsigned char> a;
while(count>0){
c = getchar();
a.push_back(c);
count--;
}
I have done necessary escaping for using getchar this also had the 4096 bytes problem. Can someone suggest a workaround or point to correct way of reading it.
It is because your terminal inputs are buffered in the I/O queue of the kernel.
Input and output queues of a terminal device implement a form of buffering within the kernel independent of the buffering implemented by I/O streams.
The terminal input queue is also sometimes referred to as its typeahead buffer. It holds the characters that have been received from the terminal but not yet read by any process.
The size of the input queue is described by the MAX_INPUT and _POSIX_MAX_INPUT parameters;
By default, your terminal is in Canonical mode.
In canonical mode, all input stays in the queue until a newline character is received, so the terminal input queue can fill up when you type a very long line.
We can change the input mode of terminal from canonical mode to non-canonical mode.
You can do it from terminal:
$ stty -icanon (change the input mode to non-canonical)
$ ./a.out (run your program)
$ stty icanon (change it back to canonical)
Or you can also do it programatically,
To change the input mode programatically we have to use low level terminal interface.
So you can do something like:
#include <iostream>
#include <string>
#include <stdio.h>
#include <termios.h>
#include <unistd.h>
int clear_icanon(void)
{
struct termios settings;
int result;
result = tcgetattr (STDIN_FILENO, &settings);
if (result < 0)
{
perror ("error in tcgetattr");
return 0;
}
settings.c_lflag &= ~ICANON;
result = tcsetattr (STDIN_FILENO, TCSANOW, &settings);
if (result < 0)
{
perror ("error in tcsetattr");
return 0;
}
return 1;
}
int main()
{
clear_icanon(); // Changes terminal from canonical mode to non canonical mode.
std::string a;
std::cin >> a;
std::cout << a.length() << std::endl;
}
Using this test-program based on what you posted:
#include <iostream>
#include <string>
int main()
{
std::string a;
std::cin >> a;
std::cout << a.length() << std::endl;
}
I can do:
./a.out < fact100000.txt
and get the output:
456574
However, if I copy'n'paste from an editor to the console, it stops at 4095. I expect that's a limit somewhere in the consoles copy'n'paste handling. The easy solution to that is of course to not use copy'n'paste, but redirect from a file. On some other systems, the restruction to 4KB of input may of course reside somewhere else. (Note that, at least on my system, I can happily copy and paste the 450KB of factorial result to another editor window, so in my system it's simply the console buffer that is the problem).
This is much more likely to be a platform/OS problem than a C++ problem. What OS are you using, and what method are you using to get the string fed to stdin? It's pretty common for command-line arguments to be capped at a certain size.
In particular, given that you've tried reading one character at a time, and it still didn't work, this seems like a problem with getting the string to the program, rather than a C++ issue.

removing trailing zeroes for a float value c++

I am trying to set up a nodemcu module to collect data from a temperature sensor, and send it using mqtt pubsubclient to my mqtt broker, but that is not the problem.
I am trying to send the temperature in a format that only has one decimal, and at this point I've succesfully made it round up or down, but the format is not right. as of now it rounds the temp to 24.50, 27.80, 23.10 etc. I want to remove the trailing zereos, so it becomes 24.5, 27.8, 23.1 etc.
I have this code set up so far:
#include <math.h>
#include <PubSubClient.h>
#include <ESP8266WiFi.h>
float temp = 0;
void loop {
float newTemp = sensors.getTempCByIndex(0);
temp = roundf((newTemp * 10)) / 10;
serial.println(String(temp).c_str())
client.publish("/test/temperature", String(temp).c_str(), true);
}
I'm fairly new to c++, so any help would be appreciated.
It's unclear what your API is. Seems like you want to pass in the C string. In that case just use sprintf:
#include <stdio.h>
float temp = sensors.getTempCByIndex(0);
char s[30];
sprintf(s, "%.1f", temp);
client.publish("/test/temperature", s, true);
Regardless of what you do to them, floating-point values always have the same precision. To control the number of digits in a text string, change the way you convert the value to text. In normal C++ (i.e., where there is no String type <g>), you do that with a stream:
std::ostrstream out;
out << std::fixed << std::setprecision(3) << value;
std::string text = out.str();
In the environment you're using, you'll have to either use standard streams or figure out what that environment provides for controlling floating-point to text conversions.
The library you are using is not part of standard C++. The String you are using is non-standard.
As Pete Becker noted in his answer, you won't be able to control the trailing zeros by changing the value of temp. You need to either control the precision when converting it to String, or do the conversion and then tweak the resultant string.
If you read the documentation for the String type you are using, there may be options do do one or both of;
control the precision when writing a float to a string; or
examine characters in a String and manually remove trailing zeros.
Or you could use a std::ostrstream to produce the value in a std::string, and work with that instead.

Query regarding SPOJ TEST

I might be wrong in asking an SPOJ problem on this forum but I wanted to understand one mechanism which I wanted to know from the enriched community here.
Your program is to use the brute-force approach in order to find the Answer to Life, the Universe, and Everything. More precisely... rewrite small numbers from input to output. Stop processing input after reading in the number 42. All numbers at input are integers of one or two digits.
Example
Input:
1
2
88
42
99
Output:
1
2
88
My Solution:
#include <iostream>
using namespace std;
int main()
{
int n,i=0;
int a[100] = {0};
while((cin>>n))
{
a[i] = n;
i++;
continue;
}
for(int j = 0;a[j]!=42;j++)
cout<<a[j]<<endl;
return 0;
}
Good Solution:
#include <iostream>
using namespace std;
int main()
{
int n;
while(true)
{
cin>>n;
if(n == 42)
break;
cout<<n<<endl;
}
return 0;
}
My query is what happens to the input in the good solution?We would be running the loop only till the number is not 42.How does Good solution handle the remaining input?I got some hint that it is somewhat related to buffering and all.Please provide me some explanation or links or study material or at least some keyword to google etc to get clarity on this.
Remaining input in good solution will be ignored by "good solution".
If you need more info read:
object
std::cin
extern istream cin;
Standard input stream
Object of class istream that represents the standard input stream oriented to narrow characters (of type char). It corresponds to the C stream stdin.
The standard input stream is a source of characters determined by the environment. It is generally assumed to be input from an external source, such as the keyboard or a file.
object
stdin
FILE * stdin;
Standard input stream
The standard input stream is the default source of data for applications. In most systems, it is usually directed by default to the keyboard.
stdin can be used as an argument for any function that expects an input stream (FILE*) as one of its parameters, like fgets or fscanf.

initialising an array with the content of a text file in C

I wrote the code below to read data from a text file and store the values in an array. my code is not reading the file.
library headers being used
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <conio.h>
my main
int main()
{
FILE *fpoo;
float NumArr[5];
//i equally tried "c:\Fly_u.txt"
fpoo= fopen ("Fly_u.txt","r");
if(fpoo!=NULL)
for (int i=0;i<6;i++)
{
fscanf(fpoo,"%d\n",NumArr[i]);
{
else
{
printf("me");
}
for (int i=0;i<6;i++)
{
printf("%f",NumArr[i]);
}
fclose(fpoo);
_getche();
return 0;
}
//content of the text file is as follows
0.99247
0.14727
-0.00041387
-1.737
0.20475
-0.052151
0.14755
-0.0233
-0.32606
0.092085
0.059199
-0.025587
0.0097565
0.13639
0.12007
The use of fscanf() is incorrect:
you need to use the format specifier for float which is %f, not int
you need to pass the address of a float (i.e. a float*), not a float
Change:
fscanf(fpoo,"%d\n",NumArr[i]);
to:
fscanf(fpoo,"%f\n", &NumArr[i]);
fscanf() returns the number of successful assignments, which in this case should be 1. Recommend checking inputs were successfully read before attempting to use them later.
If you specify "Fly_u.txt" as the file name then it must be in the same directory as the working directory of the process. Remember to esacpe '\' when constructing paths, or just use '/' (which also works on Windows).
The for loops will result in undefined behaviour as array indexes run from 0 to N - 1. So for float NumArr[5]; the valid indexes are 0, 1, 2, 3, 4 but the terminating condition on both for loops is i < 6 which use an index of 5: illegal. Either increase the size of NumArr or adjust the terminating condition on the for loops.
Try this
fscanf(fpoo,"%f\n",&NumArr[i]);
^ ^
^ ^
that is, pass the address of the variables that you want to store the data in. Note the %f instead of %d also.
You don't specify the problem, but if you are having trouble with the return from fopen check your file path and try passing the full path to your file. As #hmjd says, what you do now assumes that the file exists in the same location as your executable.
'I equally tried "c:\Fly_u.txt"' This is wrong because \ has a special meaning in C strings. What you should have used is "c:\\Fly_u.txt".