im trying to get a letter from a string in processing
so lets say the sketch receives the string "x193" it would need to be able to isolate the x and the 193 and put them in different variables.
You don't really need to get and put the 'x' as it is always the same, so just get what is after it, until the end of the string. Something like:
String[] a = {"x1", "x12", "x123"};
String[] onlyNumbers = new String[3];
void setup(){
for (int i = 0; i length; i++){
String stirp = a[i].substring(a[i].indexOf('x')+1, a[i].length());
onlyNumbers[i] = stirp;
}
println(onlyNumbers);
}
If you need performance you can also use StringBuilder, wich is much faster.
You need something like this:
String inQuestion = "x193";
String myCharacter = inQuestion.substring(0, 1);
See http://www.processing.org/reference/String_substring_.html
Related
i created char array
char Jan1[] = "1,2,3,4";
char Jan2[] = "5,7,3,4";
char Jan3[] = "10,9,3,4";`
the above char arrays i want to use it as shown below in for loop each time it will iterate and print, print is an example i am processing this string further in code, but it is giving error. if instead of yy i use Jan1 then it is printing properly. what is the other way i can use yy as to get print char array as string.
for(int i=1;i<=2;i++)
{
char yy[4];
sprintf(yy,"Jan%d",i);
String presentMonth = String(yy);
Serial.print(presntMonth);
}
So by the comments it seems that what you want is to print the contents of the JanX variable based on an index variable.
Missunderstanding
First of all you need to understand the difference between strings as datatypes and variable names. The former are ways to represent a sequence of characters (used mainly, but not only, to display output messages to any sort of output like a file, a console etc..). The latter are names that you use while coding and they can be whatever you want but they will never appear in the final program.
This for instance creates a String (datatype) named hello which contains the sequence of characters h e l l o.
String hello = "Hello";
Nothing prevents me to assign goodbye to it:
hello = "Goodbye"
Serial.print(hello); // This will print "Goodbye"
In general (apart from very hacky ways) you can't retrieve the name of the variable from your program and have them ready in your executable.
Issue
char Jan1[] = {'1','2','3'};
String yy = "Jan1"
Serial.print(yy); // This will print "Jan1"
To print the items in Jan1 you need to iterate through the values.
void printItems(char* s,int N){
for ( i = 0; i<N; i++ )
{ Serial.print(s[i]); }
}
Since Arduino provides the String class, however, it would be better to do this:
String Jan1 = "1,2,3,4";
Serial.print(Jan1); // This iterates under the hood, takes care of the length, and all the good stuff.
Solution
You want to do something a little more advanced, you want to point to a particular string based on a variable, then print the content of the retrieved string.
I can think of two ways for doing so: by using an list of strings or via a hashmap.
List of strings
String list[] = {"1,2,3,4" , "4,5,6,7", ... };
for(int i = 0; i < sizeof(list)/sizeof(String) ; i++ ){
Serial.print(list[i])
}
Hashmap
The reason I am thinking about this is because you want a string as the "index" that let's you lookup the string, so you can "search" by name. The easiest and quickest method I can think of is to declare an array of structs string_name;string_content and use strcmp to iterate through the array of structs until the needed one is found.
typedef struct{ String name; String content;} element_t;
element_t dict[] = { {"Jan1","1,2,3,4"} , {"Jan2","2,3,4,5"} ... }'
// Note this is not even close to perfect (for instance lacks check if key does not exists)
String lookup(element_t DICT, int DICT_SIZE, String key){
// Iterate through the elements, use strcmp to retrieve it
for(int i = 0; i < DICT_SIZE ; i++ ){
if(strcmp(DICT[i].name,key) {
return DICT[i].content;
}
}
}
// Now create the key, as in your code, and then lookup.
for(int i=1;i<=2;i++)
{
char yy[4];
sprintf(yy,"Jan%d",i);
String presentMonth = lookup(dict,dict_size,yy);
Serial.print(presntMonth);
}
I'm desperatly trying to get arduino to divide a string from processing into two sets of variables. In the code below I've decided to just type the important parts but x and y does of course contain the correct values. Any solution would be appreciated. These are my two attempts so far:
Attempt 1 doesn't work at all.
1.Processing:
myPort.write(x + "," + y + "\n");
1.Arduino:
String tempX = Serial.readStringUntil(44);
String tempY = Serial.readStringUntil(10);
String x = tempX.substring(0,tempX.length() -1);
String y = tempY.substring(0,tempY.length() -1);
Attempt 2 where x works correctly but not y.
2.Processing:
String [] dataToSend = new String [2];
dataToSend [0] = x;
dataToSend [1] = y;
String joinedData = join(dataToSend, ":");
myPort.write(joinedData);
2.Arduino:
String x = Serial.readStringUntil(":");
Serial.read(); //next character is comma, so skip it using this
String y = Serial.readStringUntil('\0');
First, don't worry about combining them on the Processing side. Sending two strings one right after the other is the same as sending one long string. It's all being broken into bytes on the Serial line and nobody can tell where one print line stops and the next starts.
myport.write(x);
myport.write(',');
myport.write(y);
myport.write('\n')
will work just as good.
Then on the Arduino side you most likely want to shy away from the String class. Read the data character by character into a char array.
char myArray[howLongTheStringIs];
char x[howLongXIs];
char y[howLongYIs];
int index = 0;
This gets called over and over in loop and picks up serial data as it comes in:
while (Serial.available()){
char c = Serial.read();
myArray[index] = c; // add c to the string
myArray[++index] = 0; // null terminate our string
if(c == '\n'){ // if we are at the end of the string
handleString();
}
}
Then you have a function to parse your string there are lots of ways to do that:
If you don't know anything about the strings other than the separator use strtok:
void handleString(){
char* ptr = strtok(myArray, ":"); // get up to the ":" from the string
strcpy(x, ptr); // copy into x
ptr = strtok(NULL, "\n"); // get from the separator last time up to the next "\n"
strcpy(y, ptr); // copy into y
index = 0 // reset our index and
myArray[0] = 0; // and clear the string
}
That's all untested and uncompiled and written in the reply box, so if I made a little typo in there please forgive and correct. But something like this should work. If you already know the exact lengths of the strings (or can send them from the processing code) then the handleString method can be simpler. If you've got something short to do with x and y and don't need them after that then maybe you can just keep pointers to where they are in myArray. It all depends on what the larger picture goal of your code is. But something like this should get the job done.
I'm trying to concatenate the current DateTime to my devices Mac Address in the following format: aa:bb:cc:dd:ee:ffYYmmDDhhMMss so I can hash it and send it to a web service every time I collect new data (so I'll have to hash it in every loop)
I managed to concatenate the two values (mac address + datetime) and converted it to char array
addressDateTime.toCharArray(thisThing, 28);
However, I'm kind of lost as to how to continue.
I've also tried to read the resulting char* with this cycle but I'm not understanding why it doesn't work:
void loop() {
while (!timeClient.update()) {
timeClient.forceUpdate();
}
String addressDateTime = getPayload(); //this gets the *aa:bb:cc:dd:ee:ffYYmmDDhhMMss* string
char* hashThis;
addressDateTime.toCharArray(hashThis, 28);
for (int i = 0; i < sizeof(hashThis); i++) {
char str[3];
sprintf(str, "%02x", hashThis[i]);
Serial.print(str);
}
delay(5000);
}
Am I converting the String to char* correctly?
How should I go about Hashing the char*?
Or can I Hash the String without converting it to to char*?
Update:
My code's looking like this atm
while (!timeClient.update()) {
timeClient.forceUpdate();
}
String addressDateTime = getPayload();
char hashThis[30];
addressDateTime.toCharArray(hashThis, 30);
for (int i = 0; i < sizeof(hashThis); i++) {
Serial.printf("%02x", hashThis[i]);
}
delay(5000);
}
So I managed to convert the String to Char* Except that the output is looking like this 33433a37313a42463a31443a34323a463431393035303531343038323700 instead of (for example) aa:bb:cc:dd:ee:ff190505141037
After figuring out why my char* array outputs like that I still have to hash it.
Thanks for helping me get this far, I still have ways to go
You're not allocating space to store the C string that you're getting from addressDateTime.
hashThis is a char* which is a pointer to a character. It hasn't been set to anything so it's just... random. Which will almost certainly make your program crash or at least misbehave badly.
Given your code, the quickest fix is to change
char* hashThis;
to
char hasThis[30];
addressDateTime.toCharArray(hashThis, 30);
I changed 28 to 30 because aa:bb:cc:dd:ee:ffYYmmDDhhMMss is actually 29 characters long and also requires an extra byte for the C string null terminator character. I'm not 100% sure if the toCharArray() method sets the null terminator; if it doesn't, you'd need to add
hasThis[29] = '\0';
You can avoid that by just using the String c_str() method, which returns a char* to the internal buffer that String uses to hold the string.
In that case you could rewrite
char* hashThis;
addressDateTime.toCharArray(hashThis, 28);
as
char* hashThis = addressDateTime.c_str();
By the way, you can also just do
Serial.printf("%02x", hashThis[i]);
and dispense with the snprintf(). Kudos on getting the right buffer size there, though!
UPDATE
In your updated question, you said that you're expecting to see output that looks like:
aa:bb:cc:dd:ee:ff190505141037
instead of:
33433a37313a42463a31443a34323a463431393035303531343038323700
Your code is
for (int i = 0; i < sizeof(hashThis); i++) {
Serial.printf("%02x", hashThis[i]);
}
You're writing each character as a two digit hexadecimal number, so you're going to see the number in hexadecimal that represents the character, not the character itself. If you want to see the characters, do:
for (int i = 0; i < strlen(hashThis); i++) {
Serial.printf("%c", hashThis[i]);
}
or (better)
for (int i = 0; i < strlen(hashThis); i++) {
Serial.print(hashThis[i]);
}
or (best)
Serial.println(hashThis);
Note that I changed your sizeof to a strlen. If for some reason you put a shorter string in hashThis, strlen will do the right thing whereas sizeof will always return the length that hashThis was declared with rather than the length of the string in it.
I am trying to take input and add them in an arraylist, using BufferedReader.
The code is taking endless inputs and it is not advancing to further lines (not exiting the for-loop).
Please find my below code:
public class ALinput {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int n2 = br.read();// number of items in the list
ArrayList<String> list2 = new ArrayList<String>();
for(int i =1;i<=n2;++i)
{
list2.add(br.readLine());
}
System.out.println(list2);//printing list before sorting
Collections.sort(list2);//sorting the list
System.out.println("After sorting "+list2);
}
}
I have taken n2 as number of elements in the array list.
if input n2 = 5;
the readLine keeps on taking text input endlessly without exiting after 5 strings are added to the arraylist.
Its not coming out of the for loop. Please help me understand the mistake I am doing here.
It actually isn't going forever, the character code for a zero is 48, one is 49, two is 50, and so on. so when you type in a 5, the computer reads it's character value, and stores n2 as 53, and let's you type in 52 inputs. why 52 instead of 53?
well theres a second mistake, br.read() only looks at the first byte of input, so one character. the first time br.readLine() is called, it finishes reading whatever was on the line after the first number you typed. to fix these problems, just change
int n2 = br.read();
to
int n2 = Integer.parseInt(br.readLine());
and voila! done!
P.S. you might want to surround the Integer.parseInt() in a try catch block, in case the user types in something besides a number.
can some one help me to rectify this error i have am using VS2010 ASP.Net C#3.0 i found this could on net but it is not working as it give me the error as show in the Screen shot. I am not able to understand the error message
Code reference from http://weblogs.asp.net/abdullaabdelhaq/archive/2009/06/27/displaying-arabic-number.aspx
CODE :
protected void Button1_Click(object sender, System.EventArgs e)
{ //Call Function
this.Label1.Text = "Arabic Number : <b>" + TranslateNumerals(this.TextBox1.Text) + "</b>";
}
public static string TranslateNumerals(string sIn)
{
System.Text.UTF8Encoding enc = new System.Text.UTF8Encoding();
System.Text.Decoder utf8Decoder = null;
utf8Decoder = enc.GetDecoder();
dynamic sTranslated = new System.Text.StringBuilder();
char[] cTransChar = new char[2];
byte[] bytes = {217,160 };
// Start Converting characters into Arabic mode.
char[] aChars = sIn.ToCharArray();
foreach (char c in aChars)
{
if (char.IsDigit(c))
{
bytes[1] = 160 + Convert.ToInt32(char.GetNumericValue(c));
utf8Decoder.GetChars(bytes, 0, 2, cTransChar, 0);
sTranslated.Append(cTransChar[0]);
}
else
{
sTranslated.Append(c);
}
}
return sTranslated.ToString();
}
The compiler is complaining about your request to implicitly convert the result of the integer addition (160 + Convert.ToInt32...) to a byte. This is a narrowing conversion; integers have a wider range than bytes do, and the compiler wants you to acknowledge, with an explicit cast operator, that you're aware that this could produce runtime errors.
Assuming that adding 160 actually does something useful to a character, I'd advise using something like this instead.
if (c >= '0' && c <= '9')
{
bytes[i] = (byte)((int)c + 160);
}
...which will properly produce, as the i'th value of the array bytes, a byte with a value 160 greater than the char c, if c represents an ASCII digit between 0 and 9.
Don't use the function char.IsDigit, which will return true even if c is a digit outside of the ASCII digit range. I don't run into this much, but since you're explicitly writing multilingual code, you'll want to handle that case.
I haven't reviewed the rest of the post you link to, but given these two quite obvious errors, I wouldn't put much faith in the correctness of the rest of it, frankly.
You could add a cast like (byte) in front of the 160.
I'm a little confused why such a large function is required to do that.
Updated answer:
Given that there are only 10 possible numerals to convert between, you can do something like this to make it slightly more readable. I think, anyway, I don't usually code in c#, and I'm on a mac right now... feel free to bash my code.
public static string TranslateNumerals(string sIn)
{
var sb = new System.Text.StringBuilder();
char[] arabic = { '٠', '١', '٢', '٣', '٤', '٥', '٦', '٧', '٨', '٩'};
foreach (char c in sIn) {
int idx;
// if it wasn't a number, just append it, otherwise convert it
if(!Integer.tryParse("" + c, idx)) {
sb.Append(c);
} else {
sb.Append(arabic[idx]);
}
}
return sb.toString();
}
// backwards array (which appears frontwards here)
{ '٩','٨','٧','٦','٥','٤','٣', '٢', '١', '٠'};