Cannot push C style strings into std::vector - c++

I'm trying to push some const char* into a vector, but the vector remains unpopulated after performing the operations I would presume to fill it.
Here's my attempt, where dict is my command-line argument.
test.cc
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
using namespace std;
int main(int argc, char **argv)
{
ifstream dict;
size_t dict_size;
dict.open(argv[1]); // Dictionary
vector<const char*> dictionary;
string line;
getline(dict, line);
while(!dict.fail()) {
dictionary.push_back(line.c_str());
getline(dict, line);
}
dict_size = dictionary.size();
for(int i = 0; i < dict_size; i++)
cout << "dictionary[" << i << "] is " << dictionary[i] << endl;
}
dict
Hello
World
Foo
Bar
After compiling this, I get the following output:
dictionary[0] is
dictionary[1] is
dictionary[2] is
dictionary[3] is
However, if I change the dictionary's type to vector and push back line instead of line.c_str(), I get the expected output:
dictionary[0] is Hello
dictionary[1] is World
dictionary[2] is Foo
dictionary[3] is Bar
I'm not terribly familiar with C style strings, so maybe it has something to do with null termination?

You are storing dangling pointers.
std::string::c_str() isn't a pointer to some permanent copy of data — just think, that would be leaked!
Store the std::strings instead.

Your code invokes undefined behavior, because after you do
dictionary.push_back(line.c_str());
On the next line that pointer may get deleted:
getline(dict, line); // line now is a different string

You are pushing into the dictionary pointers that point to the same address and at the last iteration it fills the memory area with an empty string. If you don't care about memory leakage you can try like this:
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
using namespace std;
int main(int argc, char **argv)
{
ifstream dict;
size_t dict_size;
dict.open(argv[1]); // Dictionary
vector<char *> dictionary;
while(!dict.fail()) {
string * line = new string();
getline(dict, *line);
if(line->length()>0)
{
dictionary.push_back((char *)line->c_str());
}
}
dict_size = dictionary.size();
for(int i = 0; i < dict_size; i++)
cout << "dictionary[" << i << "] is " << dictionary[i] << endl;
}

Related

why pointer to a string is is giving me blank output

i am running this in vs code.
its just taking input and then it terminates.
the output is blank.
this is the output
///
PS D:\c++\string> cd "d:\c++\string" ; if ($?) { g++ chararray.cpp -o chararray } ; if ($?) { .\chararray }
uu uugg gg
///
heres the code.
#include <iostream>
using namespace std;
int main()
{
char *u;
cin.getline(u, 19);
cout << "well " << u;
}
The local buffer char *u; hasn't been initialized, it may cause a SEGV crash, since calling getline will lead to writing into the address stored in u, and it's a random value now.
It would be better to use the alternative std::getline and std::string as the target string type, then we read an arbitrary length of the string (We void buffer overflow and other kinds of memory issues):
#include <iostream>
int main() {
std::string line;
std::getline(std::cin, line);
std::cout << "well " << line;
return 0;
}
A better way would be to do some allocation of mem before you store some data there.
#include <iostream>
using namespace std;
int main()
{
char *u = new char[20];
// char u[20] = { "\0" }; // with this you do not need to delete the mem
cin.getline(u, 19);
cout << "well " << u;
delete [] u; // do not forget to free your heap memory
}

a "?" before the string

I want to use strings to input the path of files:
char** argv;
char* mytarget[2]={ (char*)"‪D:\\testlas\\BigOne.pcd",(char*)"‪‪D:\\testlas\\SmallOne.pcd" };
argv = mytarget;
for(int i=0;i<2;i++)
{
std::cout << "m.name: " << argv[i] <<std::endl;
}
However, cout outputs:
m.name: ?‪D:\\testlas\\BigOne.pcd
m.name: ?‪D:\\testlas\\SmallOne.pcd
Why is there a ? before the strings?
I use VS2017 C++11.
I created a new program and used the code:
#include <iostream>
#include <string>
#include <cstring>
using namespace std;
int main()
{
std::string test = "‪abc789";
cout << test << endl;
return 0;
}
It also outputs "?abc789". Why?
std::string test = "‪abc789";
There is a hidden LEFT-TO-RIGHT EMBEDDING character between the opening quote " and the first letter a (Unicode character U+202A, or UTF-8 E2 80 AA). Remove it, for example by deleting and retyping the line, then the ? will go away.

STL vector containing vector causing segfault

The following code causes a segfault when I try to issue my push_back call. What am I doing wrong?
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main() {
std::string * foo = new std::string("hello world");
cout << *foo << endl;
std::vector<std::vector<std::string *> > my_vecs;
my_vecs[0].push_back(foo); // segfaults
cout << "trying to print my_vecs size of " << my_vecs.size() << " but we never reach that point due to segfault " << endl;
return 0;
}
I'm pretty sure I'm violating one of the contracts for using vector, as the problem is surely not with the STL implementation.
When you create my_vecs it has 0 elements, hence my_vecs[0] does not exists and gives segfault. You have to first reserve at least one element of my_vecs and then you can insert in the vector my_vecs[0] your pointer:
std::vector<std::vector<std::string *> > my_vecs(1);
my_vecs[0].push_back(&foo);
The outer vector must first be explicitly grown, before one can push to its elements.
This may be a little surprising since STL map's automatically insert their keys. But, it's certainly the way it is.
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main() {
const int DESIRED_VECTOR_SIZE = 1;
std::string * foo = new std::string("hello world");
cout << *foo << endl;
std::vector<std::vector<std::string *> > my_vecs;
for (int i = 0; i < DESIRED_VECTOR_SIZE; ++i) {
std::vector<std::string *> tmp;
my_vecs.push_back(tmp); // will invoke copy constructor, which seems unfortunate but meh
}
my_vecs[0].push_back(foo); // segfaults
cout << "now able to print my_vecs size of " << my_vecs.size() << endl;
return 0;
}

Assign a integer to char pointer using stringstream

I want to assign integer to a char pointer using stringstream. But I am getting error while running this program at line ss >> p. Please help me here i want integer to go into the buffer first and the it must be assigned to a char*.
#include <string> // std::string
#include <iostream> // std::cout
#include <sstream> // std::stringstream
using namespace std;
int main ()
{
stringstream ss;
int n=100;
char *p;
ss << n;
ss >> p; //not working
cout << ss;
return 0;
}
Use stringstream::str to get a C++ string, then use .c_str() on the string:
#include <string> // std::string
#include <iostream> // std::cout
#include <sstream> // std::stringstream
using namespace std;
int main ()
{
stringstream ss;
int n = 100;
char* p;
ss << n;
string tmp = ss.str();
p = const_cast<char*>(tmp.c_str());
cout << "p: " << p << '\n';
return 0;
}
Beware that the char pointer becomes invalid as soon as the string goes out of scope. If you need some kind of factory function behavior, return a string by value, use strlcpy or maybe new and shared_ptr.
#include <string> // std::string
#include <iostream> // std::cout
#include <sstream> // std::stringstream
using namespace std;
int main ()
{
stringstream ss;
int n=100;
char buffer[100];
char *p = buffer;
ss << n;
ss >> p;
cout << p;
return 0;
}
This is fixing only the problem you directly encountered - there's no storage behind p so it will crash. Stylistically there are many other things to improve / fix, but this should show you what part of this was actually wrong.

Access violation writing location 0x0120FA68

So i'm trying to make a program for c++ that will split up text by spaces and I keep getting the error Access violation writing location 0x0120FA68. Here's the code:
#include <string>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <list>
#include <vector>
int main(int argc, char* argv[])
{
std::vector<char*> testVector;
char* string1 = "test f";
char seperators[] = " ";
char* token1;
char *next_token1;
int counter = 0;
token1 = strtok_s(string1, seperators, &next_token1);
while (token1 != NULL)
{
if (token1 != NULL)
{
std::cout << "\n" << token1 << std::endl;
testVector.push_back(token1);
token1 = strtok_s(NULL, seperators, &next_token1);
counter++;
}
}
std::cout << testVector.at(0);
system("pause");
return 0;
}
The strtok() family of functions modify their input strings. You are calling it on a string literal, which some compilers store in memory that is not user writeable. You can fix this by using strcpy() to copy the string literal into a buffer that you are then free to modify.