run into a snag with writing to files

Hi guys,

I am still messing around with binary files I am just creating a very simple phone book type of program(console)


anyway my program gets stuck in an infinite loop and just prints "adam" so after a few minutes of debugging by printing the size of the C style strings I cam to the conclusion that the size of the pointer is been stored not the actual size of the array,so the question is how would I determine the size of the actual string? I was reading on stackoverflow and they said to possibly use strlen but that is not always perfect and has flaws,

so is there anyway to actually get the length of a string so I am getting the right amount of data into my variables

thanks

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137

#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <map>

using namespace std;

struct Person{

  int age;
  string name;
  string phoneNumber;

};


void writeToFile(vector<Person> &people,map<string,vector<int> > &sizes){

    ofstream out;
    out.open("binsecond.dat",ios::binary | ios::out | ios::app);
    if(!out.is_open()){
        cout << "error opening file" << endl;
    }

    for(int i = 0; i < people.size(); i++){

        const char* nameCStr = people.at(i).name.c_str();
        const char* phoneNumberCstr = people.at(i).phoneNumber.c_str();

        vector<int> vecSize;
        vecSize.push_back(sizeof(nameCStr));
        cout << "size of nameCstr 2 " << sizeof(nameCStr) << endl;
        vecSize.push_back(sizeof(phoneNumberCstr));

        sizes[people.at(i).name] = vecSize;

        out.write((char*) &people.at(i).age,sizeof(int));
        out.write(nameCStr,sizeof(nameCStr));
        out.write(phoneNumberCstr,sizeof(phoneNumberCstr));
    }
    out.close();
}

void readFomFile(vector<Person> &people,map<string,vector<int> > &sizes){

   ifstream in;
   stringstream ss;
   in.open("binsecond.dat",ios::binary | ios::in);

   if(!in.is_open()){

      cout << "error opening file" << endl;
   }

   in.seekg(0,ios::end);
   int sizeOfFile = in.tellg();

   in.seekg(0,ios::beg);

   int nameSize = 0;
   int phoneNumberSize = 0;
   int i = 0;

   while(in.tellg() < sizeOfFile){

      cout << in.tellg() << endl;

      nameSize = sizes[people.at(i).name].at(0);
      phoneNumberSize = sizes[people.at(i).name].at(1);
      string nameTwo;
      string phoneNumberTwo;

      cout << "name size " << nameSize << endl;
      cout << "phone Number size" << phoneNumberSize << endl;

      int age = 0;
      char* name = new char[nameSize];
      char* phoneNumber = new char[phoneNumberSize];

      in.read((char*)&age,sizeof(age));
      cout << age << endl;
      in.seekg(sizeof(int),ios::beg);
      in.read(name,sizeof(nameSize));
      in.seekg(nameSize,ios::beg);
      in.read(phoneNumber,sizeof(phoneNumberSize));
      in.seekg(phoneNumberSize,ios::beg);

      ss << name;
      ss >> nameTwo;

      ss.str("");
      ss.clear();

      ss << phoneNumber;
      ss >> phoneNumberTwo;

      ss.str("");
      ss.clear();

      cout << phoneNumberTwo << endl;
      //cout << nameTwo << endl;

   }

}

int main()
{

    vector<Person> people;
    vector<int> sizeVec;
    map<string,vector<int> > sizes;
    Person adam;
    adam.age = 22;
    adam.name = "adam";
    adam.phoneNumber = "0851512934";

    Person mark;
    mark.age = 21;
    mark.name = "mark";
    mark.phoneNumber = "0867778171";

    Person james;
    james.age = 28;
    james.name = "james";
    james.phoneNumber = "0876725262";

    people.push_back(adam);
    people.push_back(james);
    people.push_back(mark);

    writeToFile(people,sizes);
    readFomFile(people,sizes);
}
Last edited on
so the question is how would I determine the size of the actual string?
my_std_string.length() returns the number of characters in the string.

strlen(some_c_string) is OK to use as long as the c-string is properly null-terminated.

I see there's more problems than just that, I'm testing out your program now.
Why append, btw?
Why do you seek back to the beginning of the stream? <EDIT: I see you're getting filesize>

Doing
ss << name;
Relies on name being properly null-terminated. If you don't want to null-terminate your strings, you can't use this method. Still working on some fixes.

Also, it's not that good of a file if it requires previous information stored in memory (i.e. the lengths of the strings). I am going to change it so that you just use null-terminated strings instead.
Last edited on
true Ganado,

I decided to go with strlen method

still a few snags,

first off I get stuck in an infinite while loop,the loop should terminate because in.tellg() well eventually be less than sizeOfFile (which is 1872 bytes) I printed tellg quite often to debug it and it sets itself to -1 and the while loop continues to execute

second my name seems to be equal to adam0 and number then equals three numbers out of the 10 followed by weird characters.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <map>
#include <string.h>

using namespace std;

struct Person{

  int age;
  string name;
  string phoneNumber;

};


void writeToFile(vector<Person> &people,map<string,vector<int> > &sizes){

    ofstream out;
    out.open("binsecond.dat",ios::binary | ios::out | ios::app);
    if(!out.is_open()){
        cout << "error opening file" << endl;
    }

    for(int i = 0; i < people.size(); i++){

        const char* nameCStr = people.at(i).name.c_str();
        const char* phoneNumberCstr = people.at(i).phoneNumber.c_str();

        vector<int> vecSize;
        vecSize.push_back(strlen(nameCStr)+1);
        cout << "size of nameCstr 2 " << sizeof(nameCStr) << endl;
        vecSize.push_back(strlen(phoneNumberCstr)+1);

        sizes[people.at(i).name] = vecSize;

        out.write((char*) &people.at(i).age,sizeof(int));
        out.write(nameCStr,sizeof(nameCStr));
        out.write(phoneNumberCstr,sizeof(phoneNumberCstr));
    }
    out.close();
}

void readFomFile(vector<Person> &people,map<string,vector<int> > &sizes){

   ifstream in;
   stringstream ss;
   in.open("binsecond.dat",ios::binary | ios::in);

   if(!in.is_open()){

      cout << "error opening file" << endl;
   }

   in.seekg(0,ios::end);
   int sizeOfFile = in.tellg();

   in.seekg(0,ios::beg);

   int nameSize = 0;
   int phoneNumberSize = 0;
   int i = 0;
   int pos = 0;

   cout << "size of file" << sizeOfFile << endl;

   while(in.tellg() < sizeOfFile){

      cout << in.tellg() << endl;

      nameSize = sizes[people.at(i).name].at(0);
      phoneNumberSize = sizes[people.at(i).name].at(1);
      string nameTwo;
      string phoneNumberTwo;

      cout << "name size " << nameSize << endl;
      cout << "phone Number size" << phoneNumberSize << endl;

      int age = 0;
      char* name = new char[nameSize-1];
      char* phoneNumber = new char[phoneNumberSize];

      in.read((char*)&age,sizeof(age));
      cout << age << endl;
      pos += sizeof(int);
      in.seekg(pos,ios::beg);
      cout << "tell g : " << in.tellg() << endl;
      in.read(name,nameSize);
      pos+=nameSize;
      in.seekg(pos,ios::beg);
      cout << "tell g : " << in.tellg() << endl;
      in.read(phoneNumber,phoneNumberSize);
      pos+=phoneNumberSize;
      in.seekg(pos,ios::beg);
      cout << "tell g : " << in.tellg() << endl;

      ss << name;
      ss >> nameTwo;

      ss.str("");
      ss.clear();

      ss << phoneNumber;
      ss >> phoneNumberTwo;

      ss.str("");
      ss.clear();

      cout << "phone num " << phoneNumberTwo << endl;
      cout << "name " << nameTwo << endl;

   }

}

int main()
{

    vector<Person> people;
    vector<int> sizeVec;
    map<string,vector<int> > sizes;
    Person adam;
    adam.age = 22;
    adam.name = "adam";
    adam.phoneNumber = "0851512934";

    Person mark;
    mark.age = 21;
    mark.name = "mark";
    mark.phoneNumber = "0867778171";

    Person james;
    james.age = 28;
    james.name = "james";
    james.phoneNumber = "0876725262";

    people.push_back(adam);
    people.push_back(james);
    people.push_back(mark);

    writeToFile(people,sizes);
    readFomFile(people,sizes);

}
Last edited on
So, my issue with your method is that the file by itself is somewhat useless, because how would you know the lengths of each string a priori? All the information you need should be self-contained WITHIN the file itself.

I'm actually decided not to do a null-terminated string approach, because I find that tedious that you have to read each character at a time for the duration of the string until you find a '\0'. It's certainly possible, though, and uses less data.

sizeof(nameCStr) is the same as as saying sizeof(char*) which is a constant 8 bytes on 64-bit addressing machines.
Rule of thumb: The result sizeof is a compile-time constant in C++. Always treat it as such.

I think your method of map<string,vector<int> > is overly complicated.

(PS: I also see now why you're doing append, because you need to get the filesize). I used std::ate for that.

Here's my solution, let me know what questions you have about it.
The format of my file is
[age][name length][name][phone number length][phone number],
where:
- age is sizeof(int)
- name length is sizeof(std::string::size_type)
- name is variable
- phone number length is sizeof(std::string::size_type)
- phone number is variable

What I'm doing is writing the size of the string in advance, before the string itself, so that we know in advance what the length of the string is. No information is needed besides what's contained in the file itself.

Not tested when strings are 0 length, you might have to tweak it a bit for that.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#include <iostream>
#include <fstream>
#include <vector>

using namespace std;

struct Person{

  int age;
  string name;
  string phoneNumber;

};

void writeToFile(const vector<Person> &people){

    ofstream out("binsecond.dat",ios::binary | ios::out);
    
    if(!out.is_open()){
        cout << "error opening file" << endl;
        return;
    }

    for(size_t i = 0; i < people.size(); i++){

        const Person& person = people.at(i);
        
        int age                          = person.age;
        const std::string& name          = person.name;
        const std::string& phone         = person.phoneNumber;
        std::string::size_type name_len  = person.name.length();
        std::string::size_type phone_len = person.phoneNumber.length();
 
        //
        // [age]  [name length][name]  [phone number length][phone number]
        //
        
        // age:
        out.write((char*)&age, sizeof(age));

        // name:
        out.write((char*)&name_len, sizeof(name_len));
        out.write(name.c_str(), name_len);
        
        // phone:
        out.write((char*)&phone_len, sizeof(phone_len));
        out.write(phone.c_str(), phone_len);  
    }
}



void readFomFile(){

    ifstream in("binsecond.dat", ios::ate | ios::binary);

    if(!in.is_open()){
        cout << "error opening file" << endl;
        return;
    }

    int sizeOfFile = in.tellg();
    in.seekg(0,ios::beg);

    while (in.tellg() < sizeOfFile) {

        // Reading age:
        int age;
        in.read((char*)&age,sizeof(age));

        // Reading name length:
        std::string::size_type name_len;
        in.read((char*)&name_len, sizeof(name_len));
        
        // Reading name:
        std::string name;
        name.resize(name_len);
        in.read(&name[0], name_len);
        
        // Reading phone length:
        std::string::size_type phone_len;
        in.read((char*)&phone_len, sizeof(phone_len));
        
        // Reading phone:
        std::string phone;
        phone.resize(phone_len);
        in.read(&phone[0], phone_len);   
        
        cout << "age: " << age << '\n';
        cout << "name: " << name << '\n';
        cout << "phone: " << phone << '\n';
        cout << '\n';  

        // TODO: push_back to a vector or something if you want.
    }

}

int main()
{
    vector<Person> people;

    Person adam;
    adam.age = 22;
    adam.name = "adam";
    adam.phoneNumber = "0851512624";

    Person mark;
    mark.age = 21;
    mark.name = "mark";
    mark.phoneNumber = "0867778171";

    Person james;
    james.age = 28;
    james.name = "james";
    james.phoneNumber = "0876725262";

    people.push_back(adam);
    people.push_back(james);
    people.push_back(mark);

    std::cout << "\nWRITING...\n";
    writeToFile(people);
    
    std::cout << "\nREADING...\n";
    readFomFile();
}


WRITING...

READING...
age: 22
name: adam
phone: 0851512624

age: 28
name: james
phone: 0876725262

age: 21
name: mark
phone: 0867778171


Let me know what lines you want me to explain.
Last edited on
Hi Ganado

yeah the design flaw was my main issue I got the program to execute normally by clearing the binary file and saving then running the program,the program runs fine and does what I want it to do

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <map>
#include <string.h>

using namespace std;

struct Person{

  int age;
  string name;
  string phoneNumber;

};


void writeToFile(vector<Person> &people,map<string,vector<int> > &sizes){

    ofstream out;
    out.open("binsecond.dat",ios::binary | ios::out | ios::app);
    if(!out.is_open()){
        cout << "error opening file" << endl;
    }

    for(int i = 0; i < people.size(); i++){

        const char* nameCStr = people.at(i).name.c_str();
       // cout << "name c str = " << people.at(i).name.c_str() << endl;
        const char* phoneNumberCstr = people.at(i).phoneNumber.c_str();
       // cout << "phone number c str = " << people.at(i).phoneNumber.c_str() << endl;

        vector<int> vecSize;
        vecSize.push_back(strlen(nameCStr)+1);
        vecSize.push_back(strlen(phoneNumberCstr)+1);

        sizes[people.at(i).name] = vecSize;

        out.write((char*) &people.at(i).age,sizeof(int));
        out.write(nameCStr,strlen(nameCStr)+1);
        out.write(phoneNumberCstr,strlen(phoneNumberCstr)+1);
    }
    out.close();
}

void readFomFile(vector<Person> &people,map<string,vector<int> > &sizes){

   ifstream in;
   stringstream ss;
   in.open("binsecond.dat",ios::binary | ios::in);

   if(!in.is_open()){

      cout << "error opening file" << endl;
   }

   in.seekg(0,ios::end);
   int sizeOfFile = in.tellg();

   in.seekg(0,ios::beg);

   int nameSize = 0;
   int phoneNumberSize = 0;
   int i = 0;
   int pos = 0;

   while(in.tellg() < sizeOfFile){

      nameSize = sizes[people.at(i).name].at(0);
      phoneNumberSize = sizes[people.at(i).name].at(1);
      string nameTwo;
      string phoneNumberTwo;

      int age = 0;
      char* name = new char[nameSize];
      char* phoneNumber = new char[phoneNumberSize];

      in.read((char*)&age,sizeof(age));

      pos += sizeof(int);
      in.seekg(pos,ios::beg);

      in.read(name,nameSize);
      pos+=nameSize;
      in.seekg(pos,ios::beg);

      in.read(phoneNumber,phoneNumberSize);
      pos+=phoneNumberSize;
      in.seekg(pos,ios::beg);

      ss << name;
      ss >> nameTwo;

      ss.str("");
      ss.clear();

      ss << phoneNumber;
      ss >> phoneNumberTwo;

      ss.str("");
      ss.clear();

      i++;

      // print the info from file
      cout << "name " << nameTwo << endl;
      cout << "phone no. " << phoneNumberTwo << endl;
      cout << "age " << age << endl;

   }

}

int main()
{

    vector<Person> people;
    vector<int> sizeVec;
    map<string,vector<int> > sizes;
    Person adam;
    adam.age = 22;
    adam.name = "adam";
    adam.phoneNumber = "0851512624";

    Person mark;
    mark.age = 21;
    mark.name = "mark";
    mark.phoneNumber = "0867778171";

    Person james;
    james.age = 28;
    james.name = "james";
    james.phoneNumber = "087672562";

    people.push_back(adam);
    people.push_back(james);
    people.push_back(mark);

    writeToFile(people,sizes);
    readFomFile(people,sizes);
}


name adam
phone no. 0851512624
age 22
name james
phone no. 087672562
age 28
name mark
phone no. 0867778171
age 21

Process returned 0 (0x0)   execution time : 0.032 s
Press any key to continue.


the problem with the design flaw is that it will only essentially work once,as when the program executes twice since it is in append mode it will make the file bigger and create more people that was in the map(3).

I will have a look through your solution now :) thanks for putting in the time to do this :)
Hi Ganado,

your method is so much cleaner,very good idea to actually include the size of the variables in the file,saving you needing to know the size in advance all you need to do is know the file format,

question what is the difference between ios::app and ios::ate? and why do you use ate instead of app?

thanks
I followed the same approach but my results seem to be wrong for some reason


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137

#include <iostream>
#include <vector>
#include <fstream>

using namespace std;


struct Person{

   int age;
   string name;
   string number;

};

void addPerson(vector<Person> &people){

   int age;
   string name,phoneNumber;

   cout << "enter age" << endl;
   cin >> age;
   cout << "enter name" << endl;
   cin >> name;
   cout << "enter phpone number" << endl;
   cin >> phoneNumber;

   Person p;
   p.age = age;
   p.name = name;
   p.number = phoneNumber;

   people.push_back(p);

}

void writeToFile(vector<Person> &people){

  ofstream out;

  out.open("binthird.dat",ios::out | ios::binary | ios::app);

  cout << "size " << people.size() << endl;

  for(int i = 0; i < people.size(); i++){


        string::size_type name_len  = people.at(i).name.length();
        string::size_type phone_len = people.at(i).number.length();
        // age
        out.write((char*)&people.at(i).age,sizeof(int));

        // name
        out.write((char*)&name_len,sizeof(name_len));
        out.write(people.at(i).name.c_str(),name_len);

        // number
        out.write((char*)&phone_len,sizeof(phone_len));
        out.write(people.at(i).name.c_str(),phone_len);

  }
  out.close();

}

void readFromFile(vector<Person> &people){

  ifstream in;
  in.open("binthird.dat",ios::binary | ios::in);

  if(!in.is_open()){

    cout << "failure opening file" << endl;
  }

  int sizeOfFile = 0;
  in.seekg(0,ios::end);
  sizeOfFile = in.tellg();

  in.seekg(0,ios::beg);

  while(in.tellg() < sizeOfFile){

     int age;
     string name,phoneNumber;

     // age
     in.read((char*)&age,sizeof(int));

     //name

     string::size_type name_len;
     in.read((char*) &name_len,sizeof(name_len));

     name.resize(name_len);
     in.read((char*) &name[0],name_len);
     cout << "name " << name << endl;

     // phone number

     string::size_type phone_len;
     in.read((char*) &phone_len,sizeof(phone_len));

     phoneNumber.resize(phone_len);
     in.read((char*) &phoneNumber[0],phone_len);

     Person p;
     p.age = age;
     p.name = name;
     p.number = phoneNumber;

     cout << "age " << age << endl;
     cout << "name" << name << endl;
     cout << "phone Number" << phoneNumber << endl;

     people.push_back(p);

  }



}



int main()
{
    vector<Person> people;
//    addPerson(people);
//    addPerson(people);
//    writeToFile(people);
     readFromFile(people);

    return 0;
}


name bill
age 77
namebill
phone Numberbill
name jeff
age 89
namejeff
phone Numberjeff   Ñ


that is my output

maybe the file pointer is not incrementing after it reads name?
Last edited on
difference between app and ate

I used ate so that the file was immediately at the end so that I could immediately called tellg to get to the file size.

The actual difference I think is described best by this post: https://stackoverflow.com/a/12929451

If you look at e.g. this reference [ https://en.cppreference.com/w/cpp/io/ios_base/openmode ], you will see:

app --- seek to the end of stream before each write
and

ate --- seek to the end of stream immediately after open
This means that ios::app only writes at the end, but that ios::ate reads and writes at the end by default. However, with ios::ate you can seek freely in the file, but with ios::app you will always write at the end, no matter what position you set for the writing pointer.


_______________________________________________________

About your code:

You have a copy-paste mistake.
1
2
3
4
5
6
7
        // name
        out.write((char*)&name_len,sizeof(name_len));
        out.write(people.at(i).name.c_str(),name_len);

        // number
        out.write((char*)&phone_len,sizeof(phone_len));
        out.write(people.at(i).name.c_str(),phone_len);

Look closely. :)
Last edited on

Look closely. :)


wow I don't know how I made such a simple mistake.

final question when you resize the string using

name.resize(name_len);

is the null terminating character included in the size?

thanks
is the null terminating character included in the size?

Short answer: No, don't worry about the null character. If you want to store "beef", and need to pre-allocate the size, a my_string.resize(4); is 100% good.

Further info if interested:

my_string.c_str(); is guaranteed to be null-terminated.
Behind the scenes (sort of), the standard requires that my_string[my_string.size()] returns a null character, but this index should not be set.
i.e. you should not do my_string[my_string.size()] = 'a'; // undefined behavior
but char c = my_string[my_string.size()] is OK.
https://en.cppreference.com/w/cpp/string/basic_string/operator_at

The null-character does not denote the end of an std::string, so you can have null characters in the middle of an std::string. However, if you were to call my_string.c_str(), algorithms that expect null-terminated strings will cut off your data.

This example illustrates that by printing the strings:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
using namespace std;

int main() {
	
	std::string a = "Normal string";
	std::string b = "Funky string";
	
	// insert 1 null character after "Funky" (index 5)
	b.insert(5, 1, '\0');
	
	const char* pa = a.c_str();
	const char* pb = b.c_str();
	
	std::cout << a  << '\n'; // "Normal string"
	std::cout << b  << '\n'; // "Funky string" (null character not rendered to console)
	std::cout << pa << '\n'; // "Normal string"
	std::cout << pb << '\n'; // "Funky"
	
	return 0;
}

Normal string
Funky string
Normal string
Funky

Last edited on
Topic archived. No new replies allowed.