C++ Putting a string into a structure of vectors of strings - c++

I have a problem in putting string value into a "structure of vectors of strings".
The simplest reproducible code is as follows:
#include <vector>
#include <string>
#include <iostream>
using namespace std;
struct ttt {
string name;
unsigned int ID;
vector<unsigned int> numList;
};
int main() {
vector<ttt> b;
b.reserve(3);
b[0].ID = 1;
b[0].numList.push_back(3);
b[0].numList.push_back(4);
string dd ("Desk");
b[0].name = dd;
cout << b[0].ID << b[0].name << b[0].numList[2] << endl;
return 0;
}
The code compiles, but it failed to put "Desk" string into b[0].name, a structure element. Segmentation Fault arose at the spot.
I also tried below lines but all of them failed.
b[0].name.push_back(dd);
b[0].name += dd;
My compiler is GCC g++ 4.7.7 20120313,
and I used below compile command.
/usr/bin/g++ --std=gnu++0x -Werror -Wall -Wextra -Warray-bounds
Any help would be deeply appreciated, sincerely.

There are two errors:
Assigning b[0] directly without calling push_back or without initializing it in a constructor call beforehand.
Another offending line is
b[0].numList[2]
because you only have called push_back() twice, and indexing is 0-based.
It would be much better to initialize the vector directly like this:
#include <string>
#include <vector>
#include <iostream>
using namespace std;
struct ttt {
string name;
unsigned int ID;
vector<unsigned int> numList;
};
int main() {
vector<ttt> b{{"Desk", 1, { 3, 4 }}};
cout << b[0].ID << b[0].name << b[0].numList[1] << endl;
}
Live Example

You may not use the subscript operator for an empty vector to assign new values to it. Use instead push_back member function.
For example
std::vector<ttt> b;
b.reserve( 3 );
//...
b.push_back( ttt() );
b.back().ID = 1;
//...

The first error reported by Valgrind on that code is
==28307== Conditional jump or move depends on uninitialised value(s)
==28307== at 0x40154F: void std::vector<unsigned int, std::allocator<unsigned int> >::emplace_back<unsigned int>(unsigned int&&) (vector.tcc:94)
==28307== by 0x4012D7: std::vector<unsigned int, std::allocator<unsigned int> >::push_back(unsigned int&&) (stl_vector.h:933)
==28307== by 0x400F00: main (39273136.cpp:17)
Whilst this might seem a bit cryptic, a bit of experience suggests to check whethe the this argument to push_back() is initialised. Looking through the code, we see:
vector<ttt> b;
b.reserve(3);
b[0].ID = 1;
b[0].numList.push_back(3);
You've told the vector to prepare to have 3 elements, but then you never add any ttt objects to it. When you access b[0], you're using uninitialised memory (Valgrind doesn't complain about the assignment to b[0].ID because the memory has been allocated and belongs to b - but calling push_back attempts to read vector members that may be random garbage).
The obvious solution is to emplace_back() (or otherwise create) the elements of b.

when you call reserve() on a vector, it doesn't create any instances of the contained type. It only allocates the space for the elements.. So when you try to access these locations in the vector, you get undefined behaviour. You must push elements into the vector first or zero-initialize them with a call like vector<ttt> b(6); before trying to do any read or write on them.
Editing just the one line where you declare the vector of ttts and removing the reserve() call fixes this program.
Also beware, because you try to access b[0].numList[2] , the third element, but you only did push_back for two elements.
#include <vector>
#include <string>
#include <iostream>
using namespace std;
struct ttt {
string name;
unsigned int ID;
vector<unsigned int> numList;
};
int main() {
vector<ttt> b(3); //create 3 zero-init elements in vector b
b[0].ID = 1;
b[0].numList.push_back(3);
b[0].numList.push_back(4);
string dd ("Desk");
b[0].name = dd;
cout << b[0].ID << b[0].name << b[0].numList[2] << endl;
//^beware, this hasn't been initialized
return 0;
}
Output: 1Desk0

Related

Vector of an array of structs resets strings to be blank. C++

So I'm having a very confusing issue where I'm attempting to print a string from a vector of arrays of structs to the console. Integers print just fine however strings stored within these structs get set to "". I have no idea what's going on here but after setting up a test as shown bellow this issue is still persisting. Any help figuring this out would be greatly apricated.
Should also mention I'm still new to c++ so I apologise if the issue here is something simple.
#include <iostream>
#include <string>
#include <vector>
#include "Header.h"
//Test struct
struct testStruct
{
string testString;
int testInt;
};
testStruct testArray[1] = {
testArray[0] = {"String works", 69}
};
int main()
{
srand(time(NULL));
vector < testStruct > test;
test.push_back({ testArray[0] });
cout << test[0].testString << "\n"; // prints "", should print "String works"
cout << test[0].testInt << "\n"; // prints 69
characterCreation();
checkPlayerStats();
introduction();
return 0;
}
This surprised me. The following code is legal (syntactically at least)
testStruct testArray[1] = {
testArray[0] = {"String works", 69}
};
but if you replace it with the sensible version
testStruct testArray[1] = {
{"String works", 69}
};
then your program works as expected.
I expect your version has undefined behaviour because you are assigning (here testArray[0] = ...) to an array element that has not yet been created.
testStruct testArray[1] = {
This defines this array. This array, then, gets constructed. At what point, exactly, this array gets constructed is immaterial for the purposes of this question. It's sufficient to note that what goes inside { ... } gets evaluated and used to construct this array.
testArray[0] = {"String works", 69}
This expression constructs the first value of the array. This expression assigns a value to testArray[0].
The problem is that testArray[0] is not constructed yet, this is what's going on right now. This is undefined behavior. Just like what came first: the chicken or the egg. This is undefined.
You are seeing the results of undefined behavior, in the results of your program. The results of the program can be anything, and this just happens to be what shakes down, due to what your compiler and C++ library happen to produce, in terms of the executable code, before the dust settles.
So first of all you need to use std::vector, and std::cout as you havent used using namespace std.
But your main problem is:
testStruct testArray[1] = {
testArray[0] = {"String works", 69}
};
First of all it shouldnt be global as it does not need to be.
Second of all this is not correct:
testArray[0] = {"String works", 69}
You should not do this inside an array. What you probably meant to do is this:
testStruct testArray[1] = {{"String works", 69}}; // uses aggragate initialization.
So now this will have the correct output, with the following program:
#include <iostream>
#include <string>
#include <vector>
#include "Header.h"
//Test struct
struct testStruct
{
string testString;
int testInt;
};
int main()
{
testStruct testArray[1] = {{"String works", 69}};
srand(time(NULL));
vector < testStruct > test;
test.push_back({ testArray[0] });
cout << test[0].testString << "\n"; // prints "String works".
cout << test[0].testInt << "\n"; // prints 69.
characterCreation();
checkPlayerStats();
introduction();
return 0;
}
Assuming you have the Header.h header file

C++ Dumping stack trace to *.exe.stackdump

Was writing some code for an assignment to take integers as input and place them in an array to be printed.
I'm cleaning up all of my pointers as far as I can tell but I keep getting the runtime error:
1 [main] new 3444 cygwin_exception::open_stackdumpfile: Dumping stack trace to new.exe.stackdump
body of code:
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
int array[10];
int * p = array;
int *readNumbers()
{
int i=0;
for(i=0;i<10;i++)
{
string number;
int numb;
cout << "enter digit " << i << " of 10" << endl;
getline(cin, number);
istringstream (number) >> numb;
array[i]=numb;
}
return p;
delete p;
}
void printNumbers(int *numbers,int length)
{
int i;
for(i=0;i<length;i++)
{
cout << i << " " << *(numbers+i) << endl;
}
}
and the main calling code:
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
extern int *readNumbers();
extern void printNumbers(int *,int);
int main()
{
int * q = readNumbers();
printNumbers(q,10);
delete q;
return 0;
}
So just looking for a solution to the stack dump...
Also I'm sure the method I used to apply the string number returned by cin to the values contained in array[10] is not what the question was looking for so any notes on that would be great.
Thanks
It is not a good practice to return a pointer to a memory allocated inside a function, in this case, you are not even allocating it inside a function, you have done it in a global space.
It is a good practice to activate all your warnings during the compile, even treat them as error when you are doing an assignment.
As a tip, you can allocate the memory in your main function and then pass the pointer to the readNumbers function.T This way it remains inside the same scope and it is easier to manage.
also, the same way you pass the lenght of the array to the printnumbers function you should pass it to the readnumbers one instead of hardcoding it.
Your delete are invalid, you can only delete something you've allocated with new.
The first one is harmless because it's after a return, so never executed (BTW you should look at compiler warnings).
The second one might produce your crash.
Also I'm sure the method I used to apply the string number returned by cin to the values contained in array[10] is not what the question was looking for so any notes on that would be great.
That's OK. What's dubious is spreading the size of the array everywhere, what happens if you want to change it ?

c++ strings vs vector<char> vs dynamic arrays

I was trying to use char* pointers to refer to strings and vector<char> & dynamic arrays & I have a doubt with the following results :-
CODE 1:-
#include <iostream>
#include <string>
using namespace std;
int main()
{
cout<<"executing...\n";
string s="abcde";
char *c=&s[0];
cout<<c<<"\n";
s.~string();
cout<<c<<"\n";
cout<<"executed";
return 0;
}
The output of this code is :-
executing...
abcde
abcde
executed
CODE 2:-
#include <iostream>
#include <vector>
using namespace std;
int main()
{
cout<<"executing...\n";
vector<char> v {'a','b','c','d','e'};
char *p=&v[0];
cout<<p<<"\n";
v.~vector();
cout<<p<<"\n";
cout<<"executed";
return 0;
}
The output for this code is :-
executing...
abcde
executed
CODE 3 (with dynamic arrays):-
#include <iostream>
using namespace std;
int main()
{
cout<<"executing...\n";
char* c=new char[20] {'a','b','c','d','e'};
char *p=c;
cout<<p;
delete[] c;
cout<<"\n"<<p<<"\n";
cout<<"executed";
return 0;
}
The output for this code is similar to CODE 2:-
executing...
abcde
executed
I want to know why CODE 1 produces an output different from CODE 2 & CODE 3 ? What problem does string have that it behaves differently from vector<char> & dynamic arrays ?
All the snippets of code access data that has been deleted, which has no defined behavior. Therefore, any further assumption is meaningless and left to the single case. Whether you're accessing a vector, char*, string there's no difference: it's always the same violation.
Well I guess this example is good enough to show that your objects of string & vector are deleted twice hence leading to undefined behaviour :-
#include <iostream>
using namespace std;
class X
{
int x;
public:
X()
{
cout<<"constructing\n";
}
// other member functions...
~X()
{
cout<<"destroying\n";
}
};
int main()
{
X object;
object.~X();
return 0;
}
Output will be :-
constructing
destroying
destroying
When behaviour is undefined there is no use of thinking about "WHY SUCH AN OUTPUT", etc stuffs !! Even I had a doubt regarding the reference counting of C++ strings but as many people are saying strings are no longer reference counted so CODE 1 is also producing undefined behaviour. However I liked you experimenting with codes. It's necessary to learn a language properly. Keep it up !!!

Why won't my project include vectors or arrays?

So I'm still learning C++ and I can't figure out what I am doing wrong. I am using the Code::Blocks IDE and despite including the vector and array header it gives me a big list of errors and says nothing was declared in this scope. The code is very basic:
#include <iostream>
#include <vector>
#include <array>
#include <string>
using namespace std;
int main()
{
string b = const, 10;
vector<string> string1(b);
array<string, b> string2;
return 0;
}
Ok, for the record, THIS IS WHAT I WAS TRYING TO DO:
"Declare a vector object of 10 string objects and an array object of 10 string
objects. Show the necessary header files and don’t use using. Do use a const for
the number of strings."
You errors are, line by line...
string b = const, 10;
That one simply makes no sense, I don't know what you were expecting there. Assign a string to b instead.
string b = "whatever";
vector<string> string1(b);
vector<T> contains no constructor that takes a T. In your case, no constructor which takes a string. If your compiler supports it, you could use:
vector<string> string1 = {b};
If it doesn't, easy enough to just...
vector<string> string1;
string1.push_back(b);
array<string, b> string2;
array<T,size_t> takes a T (string) and the number of elements, a size_t, as its template arguments. b is a string, not a size_t, so this makes no sense. Pass the size as the second template argument.
array<string, 10> string2;
Per #Benjamin Lindley's comment, perhaps you meant to declare a const int with a value of 10 in that first line. If so, then...
int main()
{
const int b = 10;
vector<string> string1(b);
array<string, b> string2;
return 0;
}

Wrong code about c++ char*. Any body view?

#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
#define attr_size 3
int main(){
const char* attr[attr_size];
int i=0;
for(i=0;i<attr_size;i++){
char* t=(char*)malloc(sizeof(int));
sprintf(t,"%d",i);
string temp="attr";
temp+=t;
attr[i]=temp.c_str();
cout<<attr[i]<<endl;
free(t);
}
for(i=0;i<attr_size;i++){
cout<<attr[i]<<endl;
}
}
And the result is:
attr0
attr1
attr2
attr2
attr
attr2
Actually, I want to get the result that:
attr0
attr1
attr2
attr0
attr1
attr2
Maybe something wrong with loop. Anybody help me?
The problem is that the c_str return a pointer that is temporary. So when the loop continue it's iteration the object you got the pointer from is destructed and the pointer is no longer valid, leading to undefined behavior when you later dereference that pointer.
If you want an array of strings, why not declare it as an array of strings?
There are also other problems with your code, like you only allocating four bytes for a string that can be 12 (with sign and string terminator) characters.
I would suggest you remake your program like this:
#include <iostream>
#include <array>
#include <sstream>
const size_t ATTR_SIZE = 3;
int main()
{
std::array<std::string, ATTR_SIZE> attr;
for (int i = 0; i < ATTR_SIZE; ++i)
{
std::istringstream is;
is << "attr" << i;
attr[i] = is.str();
}
for (const std::string& s : attr)
std::cout << s << '\n';
}
The above uses some C++11 features like std::array (you can use std::vector instead) and range-base for loop (you can use normal iteration instead).