C++ function with pointer argument - c++

I am writing a C++ program that outputs data to a file, generates a python script and calls pyplot to make the plotting.
However, when I pass the arguments in terms of the pointers, it can be compiled properly, but cannot run. It returns error. When I use Xcode debug mode and execute it step by step, it gives correct result by chance but not always. Sometimes it also returns an error.
I doubt that it might be caused by some memory allocation problem, but I cannot identify what is exactly the problem.
My codes are as following:
1) main
#include <iostream>
#include <stdlib.h>
#include <cmath>
#include "PyCPlot.h"
using namespace std;
double pi = 3.1415926;
int main(int argc, const char * argv[]) {
int nline = 100;
double * np_list = new double(nline);
double * pack_fraction_np = new double (nline);
for (int i=0; i<nline; i++){
np_list[i] = double(i)/double(nline)*2*pi;
pack_fraction_np[i] = cos(np_list[i]);
}
PyCPlot_data_fout("RandomPacking", nline, np_list, pack_fraction_np);
PyCPlot_pythonscript("RandomPacking", "Random Packing");
PyCPlot_pyplot("RandomPacking", "Random Packing");
return 0;
}
2) head file
#ifndef PyCPlot_h
#define PyCPlot_h
#include <iostream>
#include <cmath>
#include <fstream>
#include <string>
#include <stdlib.h>
using namespace std;
int PyCPlot_data_fout(string datafilename, int nline, double * x, double *y){
ofstream fout;
fout.open(datafilename+".txt");
fout << nline << endl;
for (int i=0; i<nline; i++){
fout << x[i] << " " << y[i] << endl;
}
fout.close();
return 0;
}
int PyCPlot_pythonscript(string datafilename, string plttitle){
string strhead = "import numpy as np\nimport matplotlib.pyplot as plt\n";
string strpltfig = "plt.figure()\n";
string strpltplt = "plt.plot(xlist, ylist)\n";
string strplttit = "plt.title('"+plttitle+"')\n";
string strpltshw = "plt.show()\n";
string strfileopen ="f = open('"+datafilename+".txt', 'r')\n";
string strreadline ="size = map(int, f.readline().split())\n";
string strpltlist ="xlist = np.zeros((size))\nylist = np.zeros((size))\n";
string strfor = "for i in range(size[0]):\n xlist[i], ylist[i] = map(float, f.readline().split())\n";
ofstream pyout;
pyout.open("PyCPlot_"+datafilename+".py");
pyout << strhead << strfileopen << strreadline << strpltlist << strfor;
pyout << strpltfig << strpltplt << strplttit << strpltshw;
pyout.close();
return 0;
}
int PyCPlot_pyplot(string datafilename, string plttitle){
string strsystemsh ="source ~/.bashrc; python PyCPlot_"+datafilename+".py";
system(strsystemsh.c_str());
return 0;
}
#endif /* PyCPlot_h */
When it is ran, I get below error message
malloc: *** error for object 0x1002002e8: incorrect checksum for freed object - object was probably modified after being freed.

You want to pass an array, so pass an actual array which can be sized at runtime (std::vector), not some random pointer that hopefully will be pointing to the first element of an array (and in this case, it doesn't)
Your mistake is using new double(x) instead of new double[x]. The former allocates a single double with a value equal to x, and the latter allocates an array of double of size x and returns a pointer to the first element, but, as I've said, you wouldn't have that problem at all had you actually used std::vector and not dabbled with pointers like the early 90s style (not to mention, you wouldn't have a memory leak had you used std::vector).

You're doing a few things which are not right or seem strange.
The code new double(nline) will allocate a single double with the value of nline, which doesn't seem what you intend.
It looks like you intend to dynamically allocate an array of double. Actually from the code you've shown there's no reason you can't do a simple array as the size is known at compile time.
This code below:
double * np_list = new double(nline);
double * pack_fraction_np = new double (nline);
Could be replaced with:
double np_list[nline];
double pack_fraction_np[nline];

The following lines allocate a single double for np_list and pack_fraction_np:
double * np_list = new double(nline);
double * pack_fraction_np = new double (nline);
As a result, when you will enter your loop, you will write data to invalid memory blocks. You have to use square brackets to define an array (I do not get any error; using clang++).
Consider to use the std::vectorclass. Here is an example (your example) with std::pair of double nested in a std::vector:
PyCPlot.h
#ifndef PyCPlot_h
#define PyCPlot_h
#include <iostream>
#include <cmath>
#include <fstream>
#include <string>
#include <stdlib.h>
#include <vector>
#include <utility>
using namespace std;
int PyCPlot_data_fout(string datafilename, std::vector<std::pair<double, double>>& v){
ofstream fout;
fout.open(datafilename+".txt");
fout << v.size() << endl;
for (int i=0; i < v.size(); i++){
fout << v[i].first << " " << v[i].second << endl;
}
fout.close();
return 0;
}
int PyCPlot_pythonscript(string datafilename, string plttitle){
string strhead = "import numpy as np\nimport matplotlib.pyplot as plt\n";
string strpltfig = "plt.figure()\n";
string strpltplt = "plt.plot(xlist, ylist)\n";
string strplttit = "plt.title('"+plttitle+"')\n";
string strpltshw = "plt.show()\n";
string strfileopen ="f = open('"+datafilename+".txt', 'r')\n";
string strreadline ="size = map(int, f.readline().split())\n";
string strpltlist ="xlist = np.zeros((size))\nylist = np.zeros((size))\n";
string strfor = "for i in range(size[0]):\n xlist[i], ylist[i] = map(float, f.readline().split())\n";
ofstream pyout;
pyout.open("PyCPlot_"+datafilename+".py");
pyout << strhead << strfileopen << strreadline << strpltlist << strfor;
pyout << strpltfig << strpltplt << strplttit << strpltshw;
pyout.close();
return 0;
}
int PyCPlot_pyplot(string datafilename, string plttitle){
string strsystemsh ="source ~/.bashrc; python PyCPlot_"+datafilename+".py";
system(strsystemsh.c_str());
return 0;
}
#endif /* PyCPlot_h */
PyCPlot.cpp
#include <iostream>
#include <stdlib.h>
#include <cmath>
#include "PyCPlot.h"
using namespace std;
double pi = 3.1415926;
int main(int argc, const char * argv[]) {
int nline = 100;
std::vector<std::pair<double, double>> v;
v.reserve(nline);
double a;
for (int i=0; i < nline; i++){
a = double(i)/double(nline)*2*pi;
v.push_back(std::make_pair(a, cos(a)));
}
PyCPlot_data_fout("RandomPacking", v);
PyCPlot_pythonscript("RandomPacking", "Random Packing");
PyCPlot_pyplot("RandomPacking", "Random Packing");
return 0;
}

Related

Array print function

I am trying to create a function that prints the elements of an array. I set it up so it calculates the size of the array, but I cannot figure why it doesn't work. Can you give me some suggestions?
Thanks!
#include <iostream>
#include <string>
using namespace std;
void print_array(string s){
for(int i = 0; i < ( sizeof(s) / sizeof(s[0]) ); i++){
cout << s[i] << "\n";
}
}
int main()
{
string names[5] = {"Dante", "Greg", "Bob", "Victor", "Saber"};
print_array(names);
}
Welcome to Stack Overflow! Be aware that there are many questions similar to this that have received answers.
As mentioned in a comment, you would need to specify the size of the array if you plan on passing it into a function, because the compiler will look at it not as an array of strings (string s[]), but as a pointer to strings (string s*). Thus, you would need to modify it a little like so:
#include <iostream>
#include <string>
using namespace std;
void print_array(string s[], int size){
for(int i = 0; i < size; i++)
{
cout << s[i] << "\n";
}
}
int main()
{
string names[5] = {"Dante", "Greg", "Bob", "Victor", "Saber"};
print_array(names, sizeof(names) / sizeof(names[0]));
}
You are passing a string instead of an array of strings. You could modify your code by using vectors like this:
void print_array(const std::vector<std::string> &vector){
for (const auto &string : vector) {
std::cout << string << "\n";
}
}
int main()
{
std::vector<std::string> names = {"Dante", "Greg", "Bob", "Victor", "Saber"};
print_array(names);
}
Using vectors allows you to use auto generated for loops, wich are easy to read and use.

c++ : char* invariably stores the word vector

This is although a code specific question but the output is quite bizarre.
I am aware of STL string etc. I was fooling around when I noticed something strange, and could not find a reason for it. :(
See the Two Codes below and the output.
[Code #1] (https://ideone.com/ydB8sQ)
#include <iostream>
#include <vector>
#include <cstdlib>
#include <cstdio>
using namespace std;
class str
{
private:
vector<char> A;
public:
str(const char *S) {
int sz = sizeof(S);
cerr << sz << endl;
for (int i = 0; i < sz; ++i) {
cout << S[i];
//A.push_back(S[i]); //!-- Comment --!//
}
}
};
int main(int argc, char const *argv[])
{
str A("");
return 0;
}
In this, An Empty String is passed and is printed. The Vector A does nothing but is relevant to this problem. In the first version, A is untouched, and the code prints garbage value. (see ideone O/P)
In this second version ( see A.push_back is now uncommented )
[Code #2] (https://ideone.com/PPHGZy)
#include <iostream>
#include <vector>
#include <cstdlib>
#include <cstdio>
using namespace std;
class str
{
private:
vector<char> A;
public:
str(const char *S) {
int sz = sizeof(S);
cerr << sz << endl;
for (int i = 0; i < sz; ++i) {
cout << S[i];
A.push_back(S[i]);
}
}
};
int main(int argc, char const *argv[])
{
str A("G");
return 0;
}
The Output is :
Gvector
This is across GCC / MinGW x64. This one never prints garbage value but always contains the word 'vector'.
Where is the char* in the function pointing to?
Why would 'vector' be there anyways?
Also, the size of char * is 8.
EDIT : This does not happen if it isn't wrapped around a 'class'.
The word 'vector' appears always. I supposed it was random garbage value but then how come ideone still has the same word in its memory?
The main problem in your code is in line int sz = sizeof(S);. sizeof(S) is always equal to sizeof(char *) which seems to be 8 on your system. sizeof gives you number of bytes for variable itself. If you want to know number of bytes in string to which your char pointer points, you should use strlen function instead.
You get that vector string in output randomly, as you are accessing memory which is not in allocated space. Accessing such memory is undefined behavior, so you get your undefined result.

Failed to generate disassembly for stack frame because the URL cannot be translated & Segmentation fault: 11

I am still a newbie in programming. I am writing a program of 2D Snell's Law. I know the problem may due to wrong localisations in Xcode, but I am writing in C++ only and g++ even gives me segmentation fault error after compiling successfully.
Here are my code for main function:
#include <string>
#include "Snell.hpp"
int main(int argc, const char * argv[]){//thread 1 exc_bad_access (code=2 address=0x7fff5f238304)
string filename;
double time;
Snell S[3600];
for (int i=1; i<=1; i++) {
while (S[i].angle_tr>0) {
filename="VPVSMOD"+to_string(i)+".txt";
S[i].Open(filename);
time=S[i].Locate(i);
cout<<"The "<<i<<"th event takes "<<time<<" seconds to reach the destination"<<endl;
S[i].angle_tr-=0.01;
}
}
return 0;
}
Here is the code for Snell.hpp
#ifndef Snell_hpp
#define Snell_hpp
#include <iostream>
#include <fstream>
#include <sstream>
#include <iomanip>
#include <string>
#include <algorithm>
#include <cmath>
using namespace std;
class Snell{
private:
double GetV(double lat,double dep);
int ny,nz,time;
double la[30],h[20],v[10][30];
double lat,alt,step;
public:
Snell();
void Open(string filename);
double Locate(int i);
double angle_tr;
};
#endif /* Snell_hpp */
and Snell.cpp:
#include "Snell.hpp"
Snell::Snell(){
ny=1,nz=3,time=0;
lat=0,alt=0,step=1;
angle_tr=M_PI/2;
}
void Snell::Open(string filename){
ifstream fin(filename);
stringstream ss;
string str,tok;
for (int i=0; i<nz; i++) {
(getline(fin, str));
ss.str(str);
for (int j=0; j<ny; j++) {
getline(ss, tok, ',');
v[i][j]=stod(tok);
cout<<v[i][j]<<",i="<<i<<",j="<<j<<endl;
}
ss.clear();
}
fin.close();
angle_tr=v[1][0]/v[0][0];
}
double Snell::GetV(double lat, double dep){
int index_la = 0,index_dep = 0;
index_dep=round(dep);
return (v[index_dep][index_la]+v[index_dep+1][index_la])/2;
}
double Snell::Locate(int i){
string filename;
double count_t=0;
double latt=lat,altt=alt,step_altt_all=0,angle=0,angle_p=0;
double vsy,vsz;
double vs,vs_n;
ofstream fout;
angle=M_PI/2-atan(angle_tr);
vs=GetV(lat, alt);
filename="Test"+to_string(i)+"_"+to_string(time)+".txt";
fout.open(filename,ios::out);
fout<<lat<<","<<alt<<endl;
while (altt!=2) {
//cout<<"Compute Velocity in each dimension"<<endl;
angle_p=angle;
vsy=vs*cos(angle);
vsz=vs*sin(angle);
//cout<<"Check Velocity"<<endl;
if (vsy==0||vsz==0) {
break;
}
//cout<<"Compute reflection point"<<endl;
step_altt_all=step/vsz;
count_t=count_t+step/vsz;//time plus one
latt=latt+vsy*(step_altt_all);
step_altt_all=0;
altt=altt+step;
//cout<<"Compute New Velocity"<<endl;
vs_n=GetV(latt,altt);
if ((vs_n*cos(angle)/vs)>1) {
break;
}
else{
angle=M_PI/2-asin(vs_n*cos(angle)/vs);
vs=vs_n;
if (angle!=angle_p)
fout<</*"position:"<<*/latt<<","<<altt<<endl;
}
}
fout.close();
filename="Result"+to_string(i)+"_"+to_string(time)+".txt";
fout.open(filename);
fout<<0<<" "<<latt<<" "<<altt<<" "<<step<<endl;
fout.close();
return count_t;
}
My immediate guess is: You must have blown your stack. Please see why is stack memory size so limited?
....And yes, On my platform, my guess was correct...
Reproducing your program, but modifying your main.cpp ...
int main(int argc, const char * argv[]){//thread 1 exc_bad_access (code=2 address=0x7fff5f238304)
string filename;
double time;
//Snell S[3600];
std::cout << sizeof(Snell) << " bytes" << std::endl;
return 0;
}
It gives an output of
2848 bytes
....And You are trying to allocate 3600 of them... ~10MB!!
The solution to that is to allocate it on the heap using a std::unique_ptr or better still, your good friend, std::vector.
Modify your main to this
#include <string>
#include <memory>
//or #include <vector>
#include "Snell.hpp"
int main(int argc, const char * argv[]){//thread 1 exc_bad_access (code=2 address=0x7fff5f238304)
string filename;
double time;
std::unique_ptr<S[]> p(new Snell[3600]);
//or std::vector<Snell> S(3600);
for (int i=1; i<=1; i++) {
while (S[i].angle_tr>0) {
filename="VPVSMOD"+to_string(i)+".txt";
S[i].Open(filename);
time=S[i].Locate(i);
cout<<"The "<<i<<"th event takes "<<time<<" seconds to reach the destination"<<endl;
S[i].angle_tr-=0.01;
}
}
return 0;
}

Putting String array in parameter, then comparing the elements to literal strings error?

Let's say I have an array
string test = {"test1, "test2"}
I have my function
void testing(string test){
for(int i = 0; i < 2; i++){
if(test[i] == "test1"){
cout << "success" << endl;
}
}
}
But when I compile this, I get an error...why is that?
Is there a different approach?
Your test variable should be declared as an array type
string test[] = {"test1", "test2"};
You also need to change the function signature from
void testing(string test)
to
void testing(string* test){
the code you wrote is not going to compile because of wrong declaration of string array.
replace
string test = {"test1, "test2"};
with
string test[]={"test1, "test2"};
The following code uses the array in place without function
#include <iostream>
#include <string>
using namespace std;
string test[]={"test1, "test2"};
for(auto& item:test)
{
cout<<item<<endl;
}
I think the best way to get this working with function is to use vector
#include <iostream>
#include <string>
#include <vector>
using namespace std;
void testing(const vector<string>& strings)
{
for (auto& item : strings)
{
cout << item << endl;
}
}
int _tmain(int argc, _TCHAR* argv[])
{
vector<string> strings = { "str1", "str2", "str3" };
testing(strings);
cin.get();
return 0;
}

vector vs. arrays in c++

I am having trouble with my method. I want it to accept an array of strings as its first argument instead of a vector string. However when I try to use an Array of strings and make one in the main function I get all kinds of errors. I don't know if I should user a pointer to an array of strings for my argument or just a string. Any help?
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <sstream>
#include<iostream>
using namespace std;
class UserName
{
public:
string newMember(string* exist, string newname) {
bool found = false;
bool match = false;
stringstream ss;
string result;
string othername;
for(int i = 0; i < exist.size(); i++){
if(exist[i] == newname){
found = true;
break;
}
}
if(found){
for(int x = 1; ; x++){
match = false;
ss.str("");
ss << newname << x;
for(int i = 0; i < exist.size();i++){
//cout << ss.str() << endl;
othername = ss.str();
if(exist[i] == othername){
match = true;
break;
}
}
if(!match){
result = ss.str();
break;
}
}
return result;
}
else return newname;
}
};
int main(){
UserName u;
string Database [4];
Database[0] == "Justin";
Database[1] == "Justin1";
Database[2] == "Justin2";
Database[3] == "Justin3";
cout << u.newMember(Database, "Justin") << endl;
return 0;
}
Arrays in C++ are unfortunately a special case, and in many ways do not behave like proper values. A few examples:
void foo(int c[10]); // looks like we're taking an array by value.
// Wrong, the parameter type is 'adjusted' to be int*
int bar[3] = {1,2};
foo(bar); // compile error due to wrong types (int[3] vs. int[10])?
// No, compiles fine but you'll probably get undefined behavior at runtime
// if you want type checking, you can pass arrays by reference (or just use std::array):
void foo2(int (&c)[10]); // paramater type isn't 'adjusted'
foo2(bar); // compiler error, cannot convert int[3] to int (&)[10]
int baz()[10]; // returning an array by value?
// No, return types are prohibited from being an array.
int g[2] = {1,2};
int h[2] = g; // initializing the array? No, initializing an array requires {} syntax
h = g; // copying an array? No, assigning to arrays is prohibited
(taken from here)
If you want an array that behaves like a proper value use std::array.
#include <array>
#include <string>
void foo(std::array<std::string, 10> arr) { /* ... */ }
int main() {
std::array<std::string, 10> arr = {"Justin", "Justin1", "Justin2", "Justin3"};
foo(arr);
}
Use like following:
std::string Database[] ={ "Justin", "Justin1", "Justin2","Justin3" };
newmember as
string newMember(std::string exist[], std::size_t n, string newname)
replace exist.size() with n
In main :
cout << u.newMember(Database, 4,"Justin") << endl;
Also as per your edited post
The operator = is not the same as the operator ==, the first one is an assignment operator (assigns the value at its right to the variable at its left) and the other one == is the equality operator
So you need to use as:
Database[0] = "Justin";
Database[1] = "Justin1";
Database[2] = "Justin2";
Database[3] = "Justin3";