Matthew Sheldon
Matthew Sheldon

Reputation: 11

C-String implementation in C++ outputs incorrectly

I was recently working on a problem teaching new users of C++, which I myself am, how to use cstrings and the different implementations of them compared to the imported string object in C++. As I was working on the problem, I came across an error where, despite initializing the size of the cstring to an appropriate length for the operations that were being done, the cstring was being outputted strangely.

When I would go to print out the cstring using cout, it would print some of the cstring correctly, but oftentimes the first several characters were random characters that had nothing to do with the operations being done to the cstring. However, I found a way to definitively prevent those characters from being printed; however, I am curious as to why this works as well as what the issue is here.

I found that adding cout << ""; on its own line prior to printing the cstring resolved the issue of the random characters being outputted when printing the cstring. However, this seems like only a temporary fix and I am looking to find a more educated approach to solving this issue.

Below I have included the code that was causing the errors.

#include <iostream>
#include <vector>
#include <string>
#include <cstring>

using namespace std;

int main() {
    vector<string> words = {"Hello,", "and", "welcome", "to", "the", "world", "of", "C++!"};
    
    // Calculate the total number of characters in the words vector 
    // (including an additional character for space)
    int length = 0;
    for(int i = 0; i < words.size(); i++) {
        length += words.at(i).length() + 1;
    }
    
    cout << ""; // Removing this line of code will cause the output to do strange things
    
    // Initialize the cstring to be of size length
    char cstring[length];
    // Build the cstring using cstring library functions
    for(int i = 0; i < words.size(); i++) {
        strcat(cstring, (words.at(i) + " ").c_str());
    }
    
    // Null-terminate the cstring
    cstring[length-1] = '\0';
    
    // Output the cstring
    cout << cstring << " " << strlen(cstring) << endl;
    
    return 0;
}

If the line of code containing cout << ""; is removed, the output looks something like this, with a random amount and random set of characters at the beginning of the output each time:

`k+��Hello, and welcome to the world o 39

However, by including the line, I am able to achieve the desired output:

Hello, and welcome to the world of C++! 39

Upvotes: 1

Views: 312

Answers (1)

Vlad from Moscow
Vlad from Moscow

Reputation: 310970

For starters variable length arrays is not a standard C++ feature

// Initialize the cstring to be of size length
char cstring[length];

Secondly you defined an uninitialized array. So using strcat invokes undefined behavior

strcat(cstring, (words.at(i) + " ").c_str());

This statement

// Null-terminate the cstring
cstring[length-1] = '\0';

is redundant because the function strcat appends also the terminating zero provided that the character array you declared has a space to accommodate the zero character (and you forgot to reserve a space for the terminating zero in the array).

If the compiler supports variable length arrays then the program can look the following way

#include <iostream>
#include <string>
#include <vector>
#include <cstring>

int main() 
{
    std::vector<std::string> words = 
    {
        "Hello,", "and", "welcome", "to", "the", "world", "of", "C++!"
    };
    
    // Calculate the total number of characters in the words vector 
    // (including an additional character for space)
    size_t length = words.size();

    for ( const auto &s : words ) length += s.length();
    
    // Initialize the cstring to be of size length
    char cstring[length + 1];
    cstring[0] = '\0';
    
    // Build the cstring using cstring library functions
    for ( const auto &s : words )
    {
        std::strcat( cstring, ( s + ' ' ).c_str() );
    }
    
    // Output the cstring
   std:: cout << cstring << ' ' << length << std::endl;
   
    return 0;
}

The program output is

Hello, and welcome to the world of C++!  40

Upvotes: 1

Related Questions