简体   繁体   中英

How to print an array of const chars?

I have written the following code to save in an char * array and print the following content: band1.txt band2.txt ... band3.txt The code seems right but what is printed on the console is very weird.

Code:

const char ** current_band =  new const char * [103];

stringstream sstm;
string str;

for (i=0;i<103;i++){
    current_band[i] = new char[11];
}

for (i=0;i<103;i++){

    sstm.str("");
    sstm << "band" << i+1 << ".txt";
    str = sstm.str(); 

    current_band[i] = str.c_str();
    cout << current_band[i] << endl;
    cout << i << endl;
}

for (i=0;i<103;i++){
    cout << current_band[i] << endl;
    cout << i << endl;
}  

Console:

band1.txt

0

band2.txt

1

...

band103.txt

102

And then for the last loop:

band103.txt

0

band102.txt

1

band103.txt

2

band102.txt

3

...

band102.txt

101

band103.txt

102

How is this even possible?

EDIT: Actually i want the "bands" to be char* in order to call the ifstream current_band_file(current_band) constructor that wants such an argument

You have undefined behavior by using pointers to already destroyed objects.

Simply don't use raw pointers and raw arrays and such stuff yet.

std::string is your friend for strings, std::vector is your friend for arrays.


Example:

#include <iostream>
#include <string>
#include <vector>
using namespace std;

auto main()
    -> int
{
    vector<string>  band_names;

    for( int i = 1; i <= 103; ++i )
    {
        band_names.push_back( "band" + to_string( i ) );
    }

    for( string const& name : band_names )
    {
        cout << name << endl;
    }
}

As a minimal change to you existing code you can change:

current_band[i] = str.c_str();

to:

strcpy(current_band[i], str.c_str());

However, moving away from this mixed C and C++ to more idiomatic C++ (like Cheers and hth. - Alf's answer) will serve you better for the future.

Sticking with things like char[11] over std::string means you're stuck with:

  • The arbitrary choice of max length 11 even though probably there is no good technical reason for that limit.
  • Dealing with handling all the details of memory allocation which a proper C++ implementation hides.
  • The much less natural to read lower level code style.

As a band-aid you could replace:

current_band[i] = str.c_str();

with

if ( str.size() >= 11 )
    throw std::runtime_error("string too long");
std::strcpy(current_band[i], str.c_str());

However it would be a much better idea to replace this whole thing with:

std::vector<std::string> current_band(103);
int i = 0;
for (auto &s : current_band)
{
    // your sstm stuff, storing to s
}

Here's an alternative way that's a little more robust, readable and more likely to be correct.

#include <vector>
#include <iostream>
#include <string>
#include <sstream>

using namespace std;


int main()
{
    vector<string> bands;
    bands.reserve(103);
    for(size_t i = 1 ; i <= 103 ; ++i) {
        ostringstream ss;
        ss << "band" << i;
        bands.emplace_back( ss.str() );
    }

    for (size_t index = 0 ; index < bands.size() ; ++index) {
        cout << index << " : " << bands[index] << endl;
    }

    return 0;
}

output:

Compiling the source code....
$g++ -std=c++11 main.cpp -o demo -lm -pthread -lgmpxx -lgmp -lreadline 2>&1

Executing the program....
$demo 
0 : band1
1 : band2
2 : band3
...
100 : band101
101 : band102
102 : band103

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM