String assignment error - c++

I am writing an ns3 application, for which I need to write a vector to a file, read the file to construct the vector back again and pick random elements from the vector. This is the code:
#include <iostream>
#include <fstream>
#include <string>
#include <cassert>
#include "ns3/core-module.h"
#include "ns3/network-module.h"
#include "ns3/internet-module.h"
#include "ns3/point-to-point-module.h"
#include "ns3/applications-module.h"
#include "ns3/mf-helper.h"
#include "ns3/ipv4-static-routing-helper.h"
#include "ns3/ipv4-list-routing-helper.h"
#include "ns3/data-rate.h"
#include "ns3/mobility-module.h"
#include "ns3/wifi-module.h"
#include "ns3/ideal-wifi-manager.h"
#include "ns3/wifi-remote-station-manager.h"
#include "ns3/wifi-mode.h"
using namespace ns3;
using namespace std;
void writeFile(string, vector<string>);
void readFile(string, vector<string> &);
unsigned int Random(int,int);
bool Find(vector<string> , string);
void selectNodes(vector<string>);
vector<string> senders;
int main(int argc, char **argv)
{
vector<string> vect;
vect.push_back("10.1.1.1");
vect.push_back("10.1.1.2");
vect.push_back("10.1.1.3");
vect.push_back("10.1.1.4");
vect.push_back("10.1.1.5");
vect.push_back("10.1.1.6");
vect.push_back("10.1.1.7");
writeFile("data.txt", vect);
vector<string> ret;
readFile("data.txt",ret);
selectNodes(ret);
}
void writeFile(string name, vector<string> vs)
{
ofstream outfile(name.c_str(), ios::out);
ostream_iterator<string> oi(outfile, "\n");
copy(vs.begin(), vs.end(), oi);
}
void readFile(string name, vector<string> &vect)
{
ifstream file(name.c_str());
copy(istream_iterator<string> (file), istream_iterator<string>(), back_inserter(vect));
}
void selectNodes(vector<string> ret)
{
srand(time(NULL));
string src;
string dest;
unsigned int s= ret.size();
src = ret[Random(1,s)];
dest = ret[Random(1,s)];
while(Find(senders, src))
{
src = ret[Random(1,s)];
}
while (src == dest)
{
src = ret[Random(1,s)];
if (dest != src)
break;
}
cout << "##Source: " << src << std::endl;
cout << "##Destination: " << dest << std::endl;
senders.push_back(src);
}
unsigned int Random(int nLow, int nHigh)
{
return (rand() % (nHigh - nLow + 1)) + nLow;
}
bool Find(vector<string> senders, string addr)
{
for(unsigned int i=0;i<senders.size();i++)
if(senders[i] == addr)
return 1;
return 0;
}
This code crashes randomly. This is what gdb says
Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0xfffffffffffffff8
0x00007fff8ad5a220 in std::string::_Rep::_M_grab ()
(gdb) bt
#0 0x00007fff8ad5a220 in std::string::_Rep::_M_grab ()
#1 0x00007fff8ad5a29b in std::string::assign ()
#2 0x0000000100002a31 in selectNodes (ret=#0x7fff5fbff7c0) at test_write.cc:74
#3 0x0000000100003cf5 in main (argc=1, argv=0x7fff5fbff998) at test_write.cc:49
Why is the string assignment failing? I found that some people had this porblem due to memory leaks. But that does not seem the case here. Am I missing something?

There is problem with these lines:
src = ret[Random(1,s)];
dest = ret[Random(1,s)];
because the value Random returns could be equal to s which is out of range. The maxim value of index to ret is s-1.
So the solution is, either you write this:
src = ret[Random(1,s-1)];
dest = ret[Random(1,s-1)];
Or, define Random as:
unsigned int Random(int nLow, int nHigh)
{
return (rand() % (nHigh - nLow + 1)) + nLow - 1;
}
I would suggest you to redine the Random as suggested above, because it is mathematically sound to say that Random generates a value which falls in the range [nLow, nHigh). Dikkstra has provided a sound argument for this. Read this:
Why numbering should start at zero
By the way, you should accept vector argument by reference.

I would say that the problem is you access your vector with illegal indexes. A vector has an index from 0 to size-1, just like any other C and C++ array. Change your Random calls to Random(0, s - 1).

Related

i am trying to use getline to read a csv file line by line and separate the data in the file and turn a string into int

I am a beginner and I just need a bit of help on why I getline is showing an error:
this is what I have so far
#include <iostream>
#include <iomanip>
#include <cmath>
#include <fstream>
using namespace std;
const double TAX_RATE = 0.0825;
const int MAX_ITEMS = 1000;
const int MAX_TRANSACTIONS = 100;
int main(int argc, char const *argv[]){
string fname = "";
int itemCnt = 0, start = 0, end = 0;
int ids[MAX_ITEMS], qtys[MAX_ITEMS];
double costs[MAX_ITEMS], subtotals[MAX_TRANSACTIONS],
taxes[MAX_TRANSACTIONS], totals[MAX_TRANSACTIONS];
string names[MAX_ITEMS], paymentTypes[MAX_ITEMS], payments[MAX_ITEMS];
ifstream iFile;
if ( argc != 2 ) {
cout<<"usage: "<< argv[0]<< " <file name>" <<endl;
return 0;
} else {
iFile.open(argv[1]);
}
if (!iFile) {
cout<<"Error: Invalid file name"<<endl;
cin.clear();
}
while (!iFile.eof())
{
getline(iFile,str); //this isn't working
int commaLoc = str.find(',');
ids[itemCnt]= str.substr(0,commaLoc);
str = str.substr(commaLoc +1, str.length());
//string to int I'm not sure how to do I know its something with stoi() but not sure how to format it
}
return 0;
}
I am able to get the file to open but I'm not sure why getline isn't working it keeps saying something like
no instance of overload function
My csv file looks like:
1,Laptop,799.99,1,cash,1100
I need it to read the first number and because Its a string i don't know how to save it as an int
Multiple errors. First there is nothing called 'str' in your program. I will guess its just a string used as a temp buffer
do not do this (!File.eof) it doesnt do what you think.
while (iFile)
{
string str; <<<<<==== added
getline(iFile,str); //this isn't working <<<===is now
int commaLoc = str.find(',');
Next this line doesnt work because ids are ints and substring returns a string.
// ids[itemCnt]= str.substr(0,commaLoc);
ids[itemCnt]= stoi(str.substr(0,commaLoc)); <<<<==== fixed
str = str.substr(commaLoc +1, str.length());
}
I strongly recommend you use std::vector instead of c-style fixed size arrays. Takes 5 minutes to learn how to use them and they have huge benefits. If you must use fixed size arrays use std::array instead of c-style
You can read a string and try to convert it to a number in different ways. For example, since C++17, you can use from_chars. One of its overloads:
Receives a pair of begin and end char pointers, and an int variable,
tries to parse an int number, and
and returns the parsed number, together with a pointer to the first character that wasn't part of the match.
int i{};
auto [ptr, ec] = std::from_chars(str.data(), str.data() + str.size(), i);
if (ec == std::errc{}) { /* do something with i */} else { /* error */ }
[Demo]
Full code (using a istrinstream instead of a ifstream):
#include <charconv> // from_chars
#include <iomanip>
#include <iostream>
#include <sstream> // istringstream
#include <system_error> // errc
constinit const int MAX_ITEMS = 10;
int main() {
std::istringstream iss{
"1,Laptop,799.99,1,cash,1100\n"
"2,PC,688.88,2,card,1101\n"
"blah,Keyboard,39.00,3,cash,1102"
};
size_t itemCnt{};
int ids[MAX_ITEMS]{};
std::string str{};
while (std::getline(iss, str)) {
// Parse counter
int i{};
auto [ptr, ec] = std::from_chars(str.data(), str.data() + str.size(), i);
if (ec == std::errc{}) {
ids[itemCnt] = i;
// Remaining string
std::string remaining_string{ str.substr(ptr - str.data() + 1) };
std::cout << ids[itemCnt] << ", " << remaining_string << "\n";
}
else {
std::cout << "Error: invalid counter.\n";
}
++itemCnt;
}
}
// Outputs:
//
// 1, Laptop,799.99,1,cash,1100
// 2, PC,688.88,2,card,1101
// Error: invalid counter.

C++ Array pointer-to-object error

I am having what seems to be a common issue however reading through the replies to the similar questions I can't find the solution to my issue at all as I have already done what they are suggesting such as making the variable an array. I have the following code:
#include "stdafx.h"
#include <cstring>
#include <fstream>
#include <iostream>
#include <string>
#include <algorithm>
#include <future>
using namespace std;
string eng2Str[4] = { "money", "politics", "RT", "#"};
int resArr[4];
int main()
{
engine2(eng2Str[4], resArr[4]);
system("Pause");
system("cls");
return 0;
}
void engine2(string &eng2Str, int &resArr)
{
ifstream fin;
fin.open("sampleTweets.csv");
int fcount = 0;
string line;
for (int i = 0; i < 4; i++) {
while (getline(fin, line)) {
if (line.find(eng2Str[i]) != string::npos) {
++fcount;
}
}
resArr[i] = fcount;
}
fin.close();
return;
}
Before you mark as duplicate I have made sure of the following:
The array and variable I am trying to assign are both int
Its an array
The error is:
expression must have pointer-to-object type
The error is occurring at the "resArr[i] = fcount;" line and am not sure why as resArr is an int array and I am trying to assign it a value from another int variable. I am quite new to C++ so any help would be great as I am really stuck!
Thanks!
The problem is that you've declared your function to take a reference to a single string and int, not arrays. It should be:
void engine2(string *eng2Str, int *resArr)
or:
void engine2(string eng2Str[], int resArr[])
Then when you call it, you can give the array names as arguments:
engine2(eng2Str, resArr);
Another problem is the while loop in the function. This will read the entire file during the first iteration of the for() loop. Other iterations will not have anything to read, since it will be at the end of the file already. You could seek back to the beginning of the file, but a better way would be to rearrange the two loops so you just need to read the file once.
while (getline(fin, line)) {
for (int i = 0; i < 4; i++) {
if (line.find(eng2Str[i]) != string::npos) {
resArr[i]++;
}
}
}
I would suggest to use std::vector instead of pure C array.
In your code, there are more issues.
You are passing the fourth element of both arrays to the engine2 function.
From your definition of void engine2(string &eng2Str, int &resArr) you expect reference to a string (not array / vector) and an address / reference of int - you need to pass an pointer to the first element of resArr.
#include <cstring>
#include <fstream>
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <future>
using namespace std;
vector<string> eng2Str = { "money", "politics", "RT", "#" };
int resArr[4] = {};
void engine2(const vector<string>& eng2Str, int* resArr)
{
ifstream fin;
fin.open("sampleTweets.csv");
int fcount = 0;
string line;
for (int i = 0; i < 4; i++)
{
while (getline(fin, line))
{
if (line.find(eng2Str[i]) != string::npos)
{
++fcount;
}
}
resArr[i] = fcount;
}
fin.close();
return;
}
int main()
{
engine2(eng2Str, resArr);
system("Pause");
system("cls");
return 0;
}

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;
}

Segmentation Fault while Reading from File

I am trying to print last 10 lines of a file. Following is my code, but it is giving a segmentation fault due to fscanf. While running with gdb the fault reads : vfscanf.c: No such file or directory.
#include <iostream>
#include <stdio.h>
#include <string>
using namespace std;
int main()
{
FILE *fp = fopen("microfile.txt","r");
char *c[10];
int idx = 0;
cout<<fp<<"\n";
while(!feof(fp))
{
if(idx<10)
{
fscanf(fp,"%s",c[idx]);
idx++;
}
else if(idx==10)
{
for(int i=0;i<idx-1;i++)
{
c[i] = c[i+1];
}
fscanf(fp,"%s",c[idx-1]);
}
}
int i=0;
while(i<10)
{
cout<<c[i]<<"\n";
i++;
}
}
The source of the problem comes from the fact you have an array of pointers on this line:
char* c[10];
And later on in the program you attempt to assign character values to these pointers. Maybe you meant for just an array of characters instead:
char c[10];
Moreover, use of the Standard library is recommended. Try using std::string and standard streams and your program can be made more maintainable:
#include <iostream>
#include <fstream>
#include <string>
int main()
{
std::string s;
s.assign(
std::istreambuf_iterator<char>(std::ifsteam("microfile.txt").rdbuf()),
std::istreambuf_iterator<char>());
for (char c : s)
std::cout << c << std::endl;
}

How do you use string.erase and string.find?

Why cant i call string.find in string.erase like so: str.erase(str.find(a[1]),str.size())?
edit:code added
#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
// html tags
string tags[5]={"<!--...-->","<!DOCTYPE>","<a>","<abbr>","<acronym>"};
//
//check if string exists
int boolStringExists(string a, string b)
{
if(a.find(b)>0)
{
return 1;
}
if(a.find(b)<=0)
{
return 0;
}
}
//erase tag from string a
void eraseTags(string a,string b[])
{
for(int i=0; i<5;i++)
{
int x=(boolStringExists(a,b[i]));
while (x>0)
{
a.erase(a.find(b[i]),b[i].size());
x=(boolStringExists(a,b[i]));
}
}
}
int _tmain(int argc, _TCHAR* argv[])
{
fstream file;
file.open("h:\\a.htm");
string k,m;
while(getline(file, k))
m += k ;
eraseTags(m,tags);
return 0;
}
Gives this message: "this application has requested the runtime to terminate it in an unusual way.Please contact the application's support team for more information."
If the string is not found, find returns string::npos, and then your code wouldn't work and will give runtime error. See this gives error : https://ideone.com/NEhqn
So better write this:
size_t pos = str.find(a[1]);
if ( pos != std::string::npos)
str.erase(pos); //str.size() is not needed!
Now this doesn't give error : https://ideone.com/IF2Hy
There's nothing wrong with that call (assuming a[1] exists and is found in str at least once)
#include <iostream>
#include <string>
int main()
{
std::string str = "Hello, world!";
std::string a = "wwwwww";
str.erase(str.find(a[1]), str.size());
std::cout << str << '\n';
}
test run: https://ideone.com/8wibR
EDIT: Your full source code fails to check if b[1] is actually found in str. The function boolStringExists() returns 1 if a.find(b) is greater than zero, and the value of std::string::npos which it returns when b is not found in a IS greater than zero.
To fix this while keeping the rest of your logic intact, change that function to
//check if string exists
bool boolStringExists(string a, string b)
{
return a.find(b) != string::npos;
}
It seems you want to erase everything that comes after str.find(a[1]). In that case you can omit the second argument.
#include <iostream>
#include <string>
int main(int argc, char *argv[]) {
std::string str = "Hello, world!";
std::string needle = "o,";
str.erase(str.find(needle));
std::cout << str << "\n";
}
In this example I used needle instead of a[1], but the principle is the same.