why strupr does not accept const char arrays?

e.g in

        strcat(genBuf, getArg(i)? strupr((char*)ARG_NAMES[i]) : strlwr((char*)ARG_NAMES[i])); strcat(genBuf, "\r\n");

where

const char* ARG_NAMES[]={"wdog ", "enet ", "check inet ", "email ",
                           "sms ", "cloud ", "log ", "alarm ",
                           "night only ", "armed ", "away ", "persistent halt ",
                           "autorun ", "irrigate ", "spare14 ", "spare15 ",
                           "siren ", "test ", "tank heater", "infra heater"
                          };

the compiler warns

C:\Users\Guy\Google Drive\sync\arduino sw\_14\_14.ino:1510:53: warning: invalid conversion from 'const char*' to 'char*' [-fpermissive]

         strcat(genBuf, getArg(i)? strupr(ARG_NAMES[i]) : strlwr(ARG_NAMES[i])); strcat(genBuf, "\r\n");

and i have to cast ARG_NAMES to char* to remove the warning

Thanks for our time

because const should not be modified. why don't you write them in uppercase in definition? after you run the strupr they will be uppercased in ARG_NAMES

Juraj:
because const should not be modified. why don't you write them in uppercase in definition? after you run the strupr they will be uppercased in ARG_NAMES

I've never heard of those functions. Is this C/C++ we're talking about?

krupski:
I've never heard of those functions. Is this C/C++ we're talking about?

here are the standard functions

strupr() is not in all implementations
https://www.microchip.com/webdoc/AVRLibcReferenceManual/group__avr__string.html

Juraj:
because const should not be modified. why don't you write them in uppercase in definition? after you run the strupr they will be uppercased in ARG_NAMES

Thanks, I did not realize that these function overwrite my input.

I wrote my own function inspired by this page

void strUpper(char* dest, const char* srce) {
  char c;
  while((c=*srce++)!='\0') {
    *dest++=(c>='a')&&(c<='z') ? c-32 : c;
  }
  *dest='\0';
}

that i call with

   if(getArg(i)) strUpper(genBuf+strlen(genBuf), ARG_NAMES[i]);

Juraj:
here are the standard functions
C Library -

strupr() is not in all implementations
https://www.microchip.com/webdoc/AVRLibcReferenceManual/group__avr__string.html

I didn't see it mentioned in the first link you provided. If it's "not in all implementations", then it's non-standard (or Microsoft).

guy_c:
Thanks, I did not realize that these function overwrite my input.

I wrote my own function inspired by this page

void strUpper(char* dest, const char* srce) {

char c;
 while((c=*srce++)!='\0') {
   *dest++=(c>='a')&&(c<='z') ? c-32 : c;
 }
 *dest='\0';
}




that i call with



if(getArg(i)) strUpper(genBuf+strlen(genBuf), ARG_NAMES[i]);

Why not just use toupper() in your function instead of the comparisons?

I hope you provide enough storage for the destination string... you can't simply pass a pointer to your function unless it points to a pre existing area large enough to hold all the chars in the source....

@krupski thanks, i cooied the code like a parrot.. indeed toupper is neater and yes i check manually that genBuf does not overflow; how? After filling, i print to the monitor and paste the printout to a word processor to count the characters

guy_c:
@krupski thanks, i cooied the code like a parrot.. indeed toupper is neater and yes i check manually that genBuf does not overflow; how? After filling, i print to the monitor and paste the printout to a word processor to count the characters

What you can do (although some people here will say it can't be done or it shouldn't be done or the earth will stop rotating if it's done), but you can dynamically allocate storage for the destination string on the fly.

I do this with my little "readline" function. I pass it a bare pointer, it allocates buffer memory as needed and returns the read-in string. Of course, I must manually free the memory after each use. This is exactly how the GNU readline library works.

Here's my readline code - you can see how it works and adapt the idea for your use:

///////////////////////////////////////////////////////////////////////////////
//
//  Readline function for Arduino
//  Copyright (c) 2016 Roger A. Krupski <rakrupski@verizon.net>
//
//  Last update: 06 June 2016
//
//  This program is free software: you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with this program. If not, see <http://www.gnu.org/licenses/>.
//
///////////////////////////////////////////////////////////////////////////////

char *readline (const char *prompt)
{
#define BSIZE 16 // initial buffer size and size increment

    int c, chars, len;
    char *buf;

    chars = BSIZE;
    len = 0;
    buf = NULL;

    Serial.print (prompt); // print prompt, if any

    while (1) { // continuous until break

        while (! (Serial.available()); // wait for a serial char

        c = Serial.read(); // grab it

        if (len == 0 || len == chars) {
            chars += BSIZE; // increase buffer size
            buf = (char *) realloc (buf, (chars * sizeof (char))); // allocate more buffer
            if (!buf) {
                return buf; // if buf is null then malloc failed
            }
        }

        switch (c) {
            case EOF: {
                *(buf + len) = c; // return the EOF
                return buf;
            }

            case 0x0D:
            case 0x0A: {
                *(buf + len) = 0; // end of line
                return buf;
            }

            case 0x08:
            case 0x7F: { // backspace
                if (len > 0) { // if we CAN backspace....
                    len--; // move pointer back
                    (buf + len) = 0; // invalidate char
                    Serial.print (0x08); // backup
                    Serial.print (0x20); // erase char
                    Serial.print (0x08); // move back
                }
                break;
            }

            default: { // printable characters
                if (isprint (c)) {
                    *(buf + len) = c; // put char into buffer
                    len++; // prepare for another char
                    Serial.print ((char)(c)); // echo received char
                }
                break;
            }

        }
    }
}

And, yes it "blocks" (as some blockhead will tell you). So what? The Arduino isn't a multitasking system anyway. What's going to be happening while a user is typing? And if you DO need to so something while inside readline, use the dang timers and interrupts!

but you can dynamically allocate storage for the destination string on the fly.

Of course you can, problems do not occur until you start to allocate more space & variables on the fly. If you dedicate the heap for this purpose there is no chance of fragmentation.
Uhm, what do you do to remove characters from the buffer ?

Deva_Rishi:
Of course you can, problems do not occur until you start to allocate more space & variables on the fly. If you dedicate the heap for this purpose there is no chance of fragmentation.
Uhm, what do you do to remove characters from the buffer ?

As I said, I free the buffer after each use. Here's how I use the function:

    char *buf;
    buf = readline ("Please type here: ");
    Serial.print ("\r\nYou typed ");
    Serial.println (buf);
    free (buf);

krupski:
What you can do (although some people here will say it can't be done or it shouldn't be done or the earth will stop rotating if it's done), but you can dynamically allocate storage for the destination string on the fly.

the earth will not stop, only the MCU after it can't allocate space in fragmented heap.