How do I print a C string? (Not a String)

I am trying to be a good programmer and learn to not use the String class.
Mostly out of necessity because my current project is using a lot of RAM in Strings.

Background, and why I didn’t post my whole sketch.
I have an old-style rotary telephone dial with a Wemos D1 Mini counting the pulses then sending the dialed number to an Arduino Uno over I2C. In my original sketch, dialedNumber was initialized as a String. And the sketch works. But I need to free up more RAM - thus I am trying to convert my Strings to strings.

In the code segment below, the receiveEvent function receives the characters dialed. Wire.read() works similar to Serial.read().

I dialed “01”, and the char c in the receiveEvent() function correctly prints each character as it’s received.

When I try to print the accumulated string, I get trash:

dialed= bbbbb'aaaa'aaaa

(It is printing meaningless data. It should be “01”.)

So, here’s my question(s).

  1. Am I correctly building the string: dialedNumber inside the receiveEvent() function?
  2. How do I print this accumulated string?

Again,if you really need to see my whole sketch, I’ll post it upon request, but it’s pretty long.
Assistance would be greatly appreciated.

char dialedNumber[11] = {0};            //This contains the phone number from the dialer


//---------------------- receiveEvent() ----------------------
// function that executes whenever data is received from the I2C master
void receiveEvent(int howMany) {     //We don't need the count, but the var is not optional.
  while (0 < Wire.available()) {
    char c = Wire.read();                   //receive byte as a character
    Serial.print(c);                        //print the character
    strcat(dialedNumber, c);                //Accumulate the chars into a string.
  } 


  Serial.print(F("dialed= "));
  Serial.println(&dialedNumber[0]);
  //Serial.println(dialedNumber);      //This is how I did it when dialedNumber was a String.
}

Am I correctly building the string: dialedNumber inside the receiveEvent() function?

No

strcat() needs both arguments to be strings, ie zero terminated arrays of chars.

Put each character in the dialedNumber array as it is received, increment the array index and put '\0' in the array at the new position to terminate the string

Print dialedNumber like this

  Serial.println(dialedNumber);

Whoopeee! That works. Thanks
(The Whoopee is because I am finally getting to understand C strings better.)

Question about the termination:

void receiveEvent(int howMany) {
  byte i = 0;
  char c;
  while (0 < Wire.available()) {
    c = Wire.read();                          //receive byte as a character
    //Serial.print(c);                        //print the character
    dialedNumber[i++] = c;
  }
  dialedNumber[i] = '\0';                     //Terminate the accumulated string

Consider these two lines:

dialedNumber[i] = 0;
dialedNumber[i] = '\0';

Are they the same?

Another approach, for non-global variables:

void receiveEvent(char * dialedNumber, int howMany) { //howMany = max # of characters to store (not counting zero terminator)
  int count=0;
  while (0 < Wire.available()) {
    char c = Wire.read();                   //receive byte as a character
    Serial.print(c);                        //print the character
    *dialedNumber++ = c;                //Accumulate the chars into a string.
     if ( (++count) == howMany) break;    //done
     }
   *dialedNumber=0;  //zero terminate in every case.
}

For all intents and purposes, they are the same. There is a subtle difference.

The first line uses an int (integer) zero, which gets converted to a char (character) of zero (the null character) before being stored. I am not sure whether this happens at compile time (which it could) or at run time.

The second line uses '\0' which is a special C/C++ literal for the char (character) of zer0 (the null character). No conversion is needed.

jremington:
Another approach, for non-global variables:

void receiveEvent(char * dialedNumber, int howMany) { //howMany = max # of characters to store (not counting zero terminator)

int count=0;
  while (0 < Wire.available()) {
    char c = Wire.read();                  //receive byte as a character
    Serial.print(c);                        //print the character
    *dialedNumber++ = c;                //Accumulate the chars into a string.
    if ( (++count) == howMany) break;    //done
    }
  *dialedNumber=0;  //zero terminate in every case.
}

jremington:
Another approach, for non-global variables:

void receiveEvent(char * dialedNumber, int howMany) { //howMany = max # of characters to store (not counting zero terminator)

int count=0;
  while (0 < Wire.available()) {
    char c = Wire.read();                  //receive byte as a character
    Serial.print(c);                        //print the character
    *dialedNumber++ = c;                //Accumulate the chars into a string.
    if ( (++count) == howMany) break;    //done
    }
  *dialedNumber=0;  //zero terminate in every case.
}

Thanks for the tip. As I may have mentioned before, pointers are a weak area in my grey knowledgebase which is what kept me from learning to not use the String class. So I definitely want to try this solution as well.

vaj4088:
For all intents and purposes, they are the same. There is a subtle difference.

The first line uses an int (integer) zero, which gets converted to a char (character) of zero (the null character) before being stored. I am not sure whether this happens at compile time (which it could) or at run time.

The second line uses '\0' which is a special C/C++ literal for the char (character) of zer0 (the null character). No conversion is needed.

I asked because I saw both in the examples, and it works either way in my test. But I think I prefer the '\0' format since it's terminating a string, not a number. Less ambiguous.

You guys are really helping to get me over my fear of pointers.
I do have another question, but it's different enough that I will start a new thread.