Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 13 of 13

Thread: Super Easy Christmas Eve Challenge (strcpy)

  1. #1
    Senior Member
    Join Date
    Apr 2017
    Posts
    206

    Super Easy Christmas Eve Challenge (strcpy)

    I have a an array of strings and I want top copy to another array, but I can't get strcpy to work. No compile errors, it just wont run

    Anyone lend me a hand?


    Code:
    const char *Old[10] = {"Red", "Green", "Blue"};
    char *New[10];
    
    void setup() {
      Serial.begin(9600);
      while (!Serial);
    }
    
    void loop() {
    
      CopyStringsDarnIt(Old);
    
      for (int k = 0; k < 10; k++) {
        Serial.println(New[k]);
      }
    
    }
    
    void CopyStringsDarnIt(const char *old[]) {
    
      Serial.println("ok upto here");
    
      for (int k = 0; k < 10; k++) {
        Serial.println(k);
        strcpy(New[k], Old[k]);
        Serial.println("strcpy fails why....");
      }
    
    }

  2. #2
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    4,588
    All you need for strcpy is:
    Code:
    strcpy (str2,str1);
    Don't have to do element by element.

  3. #3
    Senior Member
    Join Date
    Apr 2017
    Posts
    206
    strcpy(New, Old); fails to compile

  4. #4
    Junior Member
    Join Date
    Jul 2016
    Posts
    12
    Quote Originally Posted by mjs513 View Post
    All you need for strcpy is:
    Code:
    strcpy (str2,str1);
    Don't have to do element by element.
    No, the source isnít an array of strings. The problem is that strcpy() doesnít allocate memory so you need to make sure dst is pointing to a large enough buffer to hold the string.

    On a side note - always use the n-variants like strncpy() to avoid problems.

  5. #5
    Senior Member
    Join Date
    Apr 2017
    Posts
    206
    sorry guys I don't understand what you are saying I should do.

    strncpy(New, Old); fails to compile

    Can some one edit this code directly?

  6. #6
    Junior Member
    Join Date
    Jul 2016
    Posts
    12
    You need to have something like

    char New[10][10];

    And then use your original code. Otherwise the destination pointers will point to NULL or random memory.

  7. #7
    Senior Member
    Join Date
    Apr 2017
    Posts
    206
    nope. fails to compile

    can someone edit the code above and not provide a one-liner? snippets are not helping

  8. #8
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    4,588
    You can try this as a test:
    Code:
    String Old[3] = {"Red", "Green", "Blue"};
    String New[3];
    
    void setup(){
      
      /* copy to sized buffer (overflow safe): */
      std::copy(Old, Old + 3, New);
    
      for (int k = 0; k < 3; k++) {
        Serial.println(New[k]);
      }
    }
    
    void loop(){}
    EDIT: Ref - http://www.cplusplus.com/reference/algorithm/copy/

  9. #9
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    21,302
    You're facing 2 problems here.

    1: The New array is merely an array of pointers to strings, but it does not have the memory for the actual strings, only pointers to them. So all 10 entries are NULL. 7 of the 10 pointers of Old are also NULL, since you initialized the array with addresses for only 3 existing strings.

    2: Your program isn't checking for NULL pointers. If a string pointer is NULL, it's not pointing to an actual string you can use.

    Here's a version of your original program which these problems fixed. Pay careful attention to the 2nd line which creates the 3 buffers where the string data is actually copied.

    Code:
    const char *Old[10] = {"Red", "Green", "Blue"};
    char buffer1[32], buffer2[32], buffer3[32];
    char *New[10] = {buffer1, buffer2, buffer3};
    
    void setup() {
      Serial.begin(9600);
      while (!Serial);
    }
    
    void loop() {
    
      CopyStringsDarnIt(Old);
    
      for (int k = 0; k < 10; k++) {
        if (New[k] == NULL) {
          Serial.println("string is NULL, can't print");
        } else {
          Serial.println(New[k]);
        }
      }
      delay(10000);
    
    }
    
    void CopyStringsDarnIt(const char *old[]) {
    
      Serial.println("ok upto here");
    
      for (int k = 0; k < 10; k++) {
        Serial.println(k);
        if (Old[k] == NULL) {
          Serial.println("Old string is NULL, nothing to copy");
        } else if (New[k] == NULL) {
          Serial.println("New string is NULL, no buffer to copy into");
        } else {
          strcpy(New[k], Old[k]);
          Serial.println("strcpy works");
        }
      }
    }

  10. #10
    Senior Member
    Join Date
    May 2015
    Location
    USA
    Posts
    329
    My version:

    Code:
    const String Old[] = {"Red", "Green", "Blue"};
    String New[10];      // caution: fixed size
    
    void setup() {
      Serial.begin(115200);
      while (!Serial);
    }
    
    void loop() {
    
      CopyStringsDarnIt();
    
      for (auto k:New) {
        if (k)
           Serial.println(k);
      }
    
      for (;;);
    
    }
    
    void CopyStringsDarnIt() {
    
      Serial.println("ok upto here");
    
      int i = 0;
    
      for (auto k:Old) {
        New[i++] = k;
        Serial.println(k);
      }
    
    }
    Last edited by jonr; 12-25-2019 at 05:01 AM.

  11. #11
    Senior Member
    Join Date
    Apr 2017
    Posts
    206
    Paul,

    Your fix worked--i'm slowly starting to understand char in C--not real easy or intuitive, I'd love to know how people wrote word processors in C.

    At any rate, I'll bet you are dying to know what this is for...i'm converting my graphing function to a library and reworking the code so you can pass up to 5 data points for plotting as well as different repaint methods. Close to done, but testing has only started. It's made for the ILI9341_t3 library and fonts.


  12. #12
    Junior Member
    Join Date
    Jul 2016
    Posts
    12
    Quote Originally Posted by KrisKasprzak View Post
    Your fix worked--i'm slowly starting to understand char in C--not real easy or intuitive, I'd love to know how people wrote word processors in C.
    C is all about pointers. Unless you understand pointers, you will always struggle in C. There is no such thing as "understanding char" - char is just the size of the data you are pointing to. C is also very forgiving when it comes to shooting yourself in the foot - if you ask it to do it, it will happily do so. Today a lot of people never learn to deal with memory management and/or pointers as they learn programming via high level languages where these concepts are not really that big.

    That said, pointers are really not that difficult if you spend an hour or so reading up on them. The concepts are fairly straight forward, the real problem with pointers in C is the syntax. You can quickly spiral into black holes of *s and &s that makes things impossible to read. Here https://cdecl.org/ can come in handy as it allows you to type in a declaration and see in plain text what you actually told the compiler you wanted.

    One more thing should be noted - if you are learning about pointers, also dig into the topic of data types. C often tricks newcomers into just using int for numbers for example. This is a dreaded practice that will get you into trouble where you least expect it, especially if you are coming from a scripting language such as Python or similar where you don't really have to care about what numbers you store in your variables. In C, everything has a size and all data types have limits for what data they can store. If you want to get into the nitty gritty details, you will have to find a copy of the C standard and read up on the details but the gist of it is that you should not rely on assumptions about the data size you can store in the different datatypes in C. The standard defines how they relate and some bounds for the data types but if you really want to know what is going on, use the much more well defined data types from stdint.h such as int32_t, uint32_t et al. Then you have control over the expected range the variable can store regardless of what platform your code is running on.

  13. #13
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    4,588
    Quote Originally Posted by KrisKasprzak View Post
    Paul,

    Your fix worked--i'm slowly starting to understand char in C--not real easy or intuitive, I'd love to know how people wrote word processors in C.

    At any rate, I'll bet you are dying to know what this is for...i'm converting my graphing function to a library and reworking the code so you can pass up to 5 data points for plotting as well as different repaint methods. Close to done, but testing has only started. It's made for the ILI9341_t3 library and fonts.

    Happy Holidays all

    Yeah - Paul's method is a lot better than what I posted as usual. BTW: I did test your old library with the ILI9488 and ILI9341_t3n libraries so should be fun when your new library is ready.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •