0

I have a function on a small micro that sends one character at a time out the UART port.

USART_0_write('x');

This causes a character x to go out the serial port.

I have created this function that works:

char source[] = "Test Text.";
for (uint8_t i=0; i < strlen(source); i++){
    USART_0_write(source[i]);
}

All I want to do is simply dynamically update what string I'm sending, without creating a different array for each thing I send.

I basically want to do what I assume strcpy does, but I can't get that function to work. I got a version using strcpy to compile once, but it must have been a memory leak because when I ran it, all the I/O ports on the chip went screwy.

strcpy(source,"Different String");

I want to do something like this then call my first function again and have it print the new updated string out the serial port.

I understand the concept of pointers, but everything I read the syntax explanation I can't understand. I have tried a ton of different combinations, putting starts before and after everything. No matter what it's a total fail.

I read over this great explanation, however, like most explanations out there, the thing stops JUST SHORT of actually providing the single line of code that actually makes it all work at the bottom when it talks about dynamically updating a string: https://www.cs.bu.edu/teaching/cpp/string/array-vs-ptr/

Thank you.

ADDITIONAL INFORMATION:

(I edited my post and added this, since you can't add a new post below without "answering" your own question, and the comment reply section doesn't allow for any formatting and limited to 500 characters, which is dumb).

I am trying to create a menu by doing the following:

my_string = "Menu item 1";
sendString(my_string); //function to iterate through characters sending them
my_string = "Menu item 2";
sendString(my_string); //function to iterate through characters sending them
my_string = "Menu item 3";
sendString(my_string); //function to iterate through characters sending them

Now there is probably a way to do this that requires a masters degree. I'm just trying to get this stupid menu working. I'm literally creating individual functions that create a new character array for each line, which is the way wrong way to do it, but it's the only thing I can figure out after fighting with this for hours.

kjav
  • 93
  • 1
  • 7
  • It's not totally clear what you're trying to do. Can you post some example input with expected output, and the code you've tried? – ahota Nov 17 '18 at 19:13
  • I guess what's unclear is what you mean by the strings changing as you send them. Supposing you're in the for loop and `i` is halfway to `strlen(source)`, are you wanting to change `source` to have different contents? – ahota Nov 17 '18 at 19:18
  • I am trying to make a menu that is sent out the serial port line by line. My plan is to make a holder for a string of text (whatever you want to call that) then send that string to a function that iterates through it one character at a time sending (this part works), then I need to change the string I'm sending for the next line. Like this: my_string = "Item 1: Slam Head in Door"; sendString(my_string); my_string = "Item 2: Bang Head on Desk"; sendString(my_string); my_string = "Item 3: Just Give Up"; sendString(my_string); – kjav Nov 17 '18 at 19:24
  • ^^^ Even stack overflow is impossible to use. I can't see any way to make a new post with formatting without "answering" my question. Why is everything so frustrating?????? You can't use formatting when responding and you're limited to 500 characters which is useless. – kjav Nov 17 '18 at 19:26
  • If it is not answered, you can always edit your question to provide more information.... – Leonardo Alves Machado Nov 17 '18 at 19:30
  • You may want to simply try `char source[1024] = "Test Text.";`, make sure to use `strncpy`, and understand what this is doing before you continue further. – William Pursell Nov 17 '18 at 19:31
  • `for (uint8_t i=0; i < strlen(source); i++){` is really bad style. Maybe the compiler will optimize it away, but you're computing the length of the string (an expensive operation) on every iteration of the loop. Don't do that. – William Pursell Nov 17 '18 at 19:32
  • I have added more info to the original post above. – kjav Nov 17 '18 at 19:33
  • I don't care about bad form right now, I just need the menu to work for now. I can't believe I've been hung up for hours trying to update a string of text. – kjav Nov 17 '18 at 19:34

4 Answers4

3

Assume what you wrote is literally what you tried....

source[] is a 10-byte array.

"Different String" is 17 bytes long.

You overflowed source[] and clobbered who-knows-what.

dopamane
  • 1,315
  • 2
  • 14
  • 27
0

Based on your last comment, it seems like you need to store the contents of menus in an array of strings. In C, this would be a char **, e.g. char **menu;.

If you have 3 items in your menu, then you can allocate the memory for the menu like so: char **menu = (char **)malloc(3 * sizeof(char *));

Then you need to fill in the items in the menu, e.g.:

menu[0] = (char *)malloc(64 * sizeof(char)); // 64 as an example
menu[1] = (char *)malloc(64 * sizeof(char));
...
strcpy(menu[0], "Item 1");
strcpy(menu[1], "Item 2");
...

and so on. Then you can iterate over the three items in your menu, and send each one to your function.

for(int i = 0; i < 3; i++) {
    sendString(menu[i]);
}
ahota
  • 439
  • 5
  • 16
  • Thank you. I would have never figured out that top line. Now I can't figure out how to send this to a function, or where I need to declare/scope things from. I want to call the menu print function from inside my main(). I declared the menu (your top line) and populated it before main(), then I added another function called void sendString(menu) before main() but it won't compile. And I can't show you what I tried because all I can do is "comment" to my post, which doesn't format. So I don't know how to even explain what I'm doing. – kjav Nov 17 '18 at 19:44
  • You can't put arbitrary code like the menu initialization outside of a function. What I would suggest is: 1. create a global `char **menu`, 2. create an `initializeMenu` function that creates all the items, and 3. call that function in `main()` before doing the for loop. You can make a GitHub Gist for your code to share it. – ahota Nov 17 '18 at 19:47
  • Is there a way I can make another new post with code and formatting??!?!?!? I don't understand how to use what you are posting, and I would post what I'm doing, but stack won't let me. Why is everything impossible? – kjav Nov 17 '18 at 19:50
  • 1
    Take a look at this: https://gist.github.com/ahota/9abfe02bf7e462b1d497208560c7c171. GitHub Gist is just a way of sharing formatted text/code. I put an example of what I mentioned there. – ahota Nov 17 '18 at 19:57
  • I added code but it posted it above for some reason. Can't understand why this simple task is so incredibly complicated. – kjav Nov 17 '18 at 20:04
0

This is NOT an "answer" but it's the only way I can trick stackoverflow into letting me post code.

void makeMenu(void){
    char **menu = (char **)malloc(3 * sizeof(char *));

    menu[0] = (char *)malloc(64 * sizeof(char)); // 64 as an example
    menu[1] = (char *)malloc(64 * sizeof(char));
    menu[2] = (char *)malloc(64 * sizeof(char));

    strcpy(menu[0], "Welcome to the menu. Make selection:");
    strcpy(menu[1], "1: Turn on light");
    strcpy(menu[1], "2: Turn off light");

}

void sendMenu(**menu){
    for (uint8_t i=0; i < 3; i++){
        sendSingleLine(menu[i]);
    }
}

void sendSingleLine(*string_to_send){
    for (uint8_t i=0; i < strlen(string_to_send); i++){
        USART_0_write(string_to_send[i]);
    }
}

int main(void){
makeMenu();
    sendMenu();
}

^^^ tried this, won't compile.

kjav
  • 93
  • 1
  • 7
  • Your `sendSingleLine` function argument needs a type, i.e. `*string_to_send` should be `char *string_to_send`. Same goes for `sendMenu`. – ahota Nov 17 '18 at 20:10
  • @ahota is this what you had in mind? I think there's a problem with makeMenu because those variables won't be global right? I think this is what you were asking me to do above. I don't think I'm passing things between functions correctly either. – kjav Nov 17 '18 at 20:13
  • Yeah this is essentially what you need to do. I noticed you need to be passing `menu` when you call `sendMenu()` in `main`. Did you look at the gist I linked in the comment under my answer? – ahota Nov 17 '18 at 20:15
  • I don't see any gist. Not sure what that is. I don't see any links in the comments. I've never been comfortable with stack overflow's layout. A million bits of clutter makes the information hard to pick out. – kjav Nov 17 '18 at 20:29
0

Thanks for the help everyone but I'm out of time. Defeated on this one. I've been at this for a while - I've written low level drivers and radio systems, etc but never have to deal with text. This is the sort of thing they teach on first day Python coding. lol.

Here's how I worked around it. Ugly but it works. I just call uart_menu() and it prints. Done. If I can figure out how to send my arrays to the function without having to re-write it each time that would be helpful.

void uart_menu(void){
    char line1[] = "Test Menu:\n";
    for (uint8_t i=0; i < strlen(line1); i++){
        USART_0_write(line1[i]);
    }

    char line2[] = "1: Turn on 0xA2\n";
    for (uint8_t i=0; i < strlen(line2); i++){
        USART_0_write(line2[i]);
    }

    char line3[] = "2: Turn off 0xA2\n";
    for (uint8_t i=0; i < strlen(line3); i++){
        USART_0_write(line3[i]);
    }

    char line4[] = "3: Turn on All Addresses\n";
    for (uint8_t i=0; i < strlen(line4); i++){
        USART_0_write(line4[i]);
    }

    char line5[] = "4: Turn off All Addresses\n";
    for (uint8_t i=0; i < strlen(line5); i++){
        USART_0_write(line5[i]);
    }

}
kjav
  • 93
  • 1
  • 7
  • 1
    It's a shame you're giving up. You were about 95% of the way there. This is the gist I was talking about: https://gist.github.com/ahota/9abfe02bf7e462b1d497208560c7c171. Hope it helps. – ahota Nov 17 '18 at 20:36
  • Thank you so much. That is very helpful. I wasn't aware of what gist was. – kjav Nov 17 '18 at 20:54
  • Glad to hear it helped! If it solved the issue, would you mind accepting my answer? If there's still more you need, I'd suggest posting a new question. – ahota Nov 17 '18 at 21:22