How to pass integer vector from shell? - c++

I want to pass an integer array/vector as shell argument? Below is my last attempt:
#include <iostream>
#include <vector>
#include <string>
//using namespace std;
int main(int argc, const char *argv[])
{
char dummy;
std::vector<int> argument(argc-1);
std::cout<<argc<<std::endl;
for (int i = 1; i <= argc; ++i)
{
dummy=*(*(argv+1)+i);
argument[i-1]=std::stoi(dummy);
}
std::cout<<argument.size()<<std::endl;
return 0;
}
I got error:
error: no matching function for call to ‘stoi(char&)’
Is there any simpler way to do it?
basically run program as:
./executable {1, 2, 3, 4, 5}
and intialize an array/vector in programme with those values?

Resolving the compiler error is a waste of time. OP had the right idea initially using std::string dummy;, so let's stick with that and figure out what went wrong.
First off lets assume 4 arguments: 1 12 123 1234 and examine the range of the 4 loop.
for (int i = 1; i <= argc; ++i)
Because OP starts the loop at 1, I assume they know that the first argument is the command executed. Great start.
But i <= argc will allow the i to range from 1 to 5. argv is valid from 0 to 4. That means undefined behaviour was invoked accessing argv[5] and Crom only knows what happens after that. Very likely dummy got loaded with garbage from argv[5] and std::stoi could not parse this garbage into an int. This is only speculation. Determining the behaviour of undefined behaviour is a waste of time. It might be different next time. It might even look like it worked next time.
So the first thing to do is get rid of the out of bounds read.
for (int i = 1; i < argc; ++i)
Now we have an i with a range of 1 to 4 and everything stays in bounds.
Next, we can clean up
dummy=*(*(argv+1)+i);
since we aren't tying to fit it into a char anymore. The simplest is
std::string dummy(argv[i]);
which declares string dummy and initializes it to contain one command line argument. Can this be done faster? Yeah, but this is stupidly easy to read. Start with easy and only go into the difficult if easy doesn't meet the program requirements. The only change I would make here until forced is change dummy to a more descriptive name.
Even simpler you could
argument[i-1]=std::stoi(argv[i]);
But I prefer the dummy approach at least for now. It has a major debugging advantage: You can print or use the debugger to inspect the value of dummy before std::stoi throws an exception because dummy can't be converted.
The resulting code:
int main(int argc, const char *argv[])
{
std::vector<int> argument(argc-1);
std::cout<<argc<<std::endl;
for (int i = 1; i < argc; ++i)
{
std::string dummy(argv[i]);
argument[i-1]=std::stoi(dummy);
}
std::cout<<argument.size()<<std::endl;
return 0;
}
called with ./executable 1 12 123 1234 the output will be
5
4
5 input arguments and 4 items in the vector because the command is discarded.
Figuring out how to handle the curly braces in
./executable {1, 2, 3, 4, 5}
I'm going to leave to OP to figure out.

No need to make complex simply use
argument[i-1]=std::stoi(argv[i]); in place of
dummy=*(*(argv+1)+i);
argument[i-1]=std::stoi(dummy);
we know that array of size n stores element from location 0 to location n-1.
argc is the number of strings when you run the program including your executable file name we know that argv is array of strings(character sequence) so at location zero in argv is a executable file name. that is why start for loop from location i=1, and we need to run for loop i=1 to i < argc( means till i<=argc-1)
try following program
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main(int argc, const char *argv[])
{
char dummy;
std::vector<int> argument(argc-1);
std::cout<<argc<<std::endl;
for (int i = 1; i < argc; ++i)
{
// dummy=*(*(argv+1)+i);
// argument[i-1]=std::stoi(dummy);
argument[i-1]=std::stoi(argv[i]);
}
std::cout<<argument.size()<<std::endl;
return 0;
}

Related

Can' t print position of element in an array after heapify-up C++

Can someone help me with the code in c++ below?
#include <iostream>
#include <fstream>
using namespace std;
int PARENT(int i)
{
return (i/2);
}
int Heapify_up(int arra[], int i)
{
int j,k;
if (i>1){
j = PARENT(i);
if (arra[i]<arra[j]){
k=arra[i];
arra[i]=arra[j];
arra[j]=k;
Heapify_up(arra, j);
}
}
return j;
}
int main()
{
int array3[15];
int i,p,array_length;
ifstream inputFile1("Heapfile.txt");
if (inputFile1.good()){
int current_number = 0;
i=1;
while (inputFile1>> current_number)
array3[i++] = current_number;
inputFile1.close();
}
array_length = i;
cout<<"Please, enter an integer: ";
cin>>p;
array3[array_length+1]=p;
int pos=Heapify_up(array3, array_length+1);
for (i=1; i<15; i++){
cout<<array3[i]<<" ";
}
cout<<"The position is "<<pos;
}
Let me explain you that have an array in a txt file. After i insert a random integer and with the heapify-up algorith I'm sorting this random number to the array. I want to print the new sorted array(I' have done that) and the new position of the random element that i have entered. Any idea?
thanks in advance!
P.S. I am new here and i find it somehow difficult to post my code correctly... still learning! XD
Okay, there are multiple problems with your code.
You make no effort to ensure you don't blow past the size of your
static array.
You skip a spot in the array when appending your manually-added
value
Your array length is wrong
You aren't initializing your variables
Let's start with the last one. Please do something like this:
int i{0}, p, array_length;
This ensures the i variable is properly initialized to zero.
Next, your code does this:
array3[i++] = current_number;
This means that at any given time, i is the length of the array.
But later you do this:
array_length = i;
array3[array_length+1]=p;
Frankly, I would drop variable i entirely and use array_length instead. There is no need for both.
But even without that, you're setting array_length correctly, but then you're inserting to a point AFTER that, so you might start with:
[ 1, 2, 3, 4, 5 ]
At this point, i == 5. Input a 6 and have:
[ 1, 2, 3, 4, 5, 0, 6 ]
Because you put it at index i+1 not at index i.
At this point, array_length is no longer an accurate length. But you do this:
int pos=Heapify_up(array3, array_length+1);
So it kind of works.
I don't know why Heapify_up is returning j -- it's just the midpoint of the array. That's not a useful value.
Furthermore, I don't really know what your heapify thing is trying to accomplish.. It certainly isn't a heap-sort. If the middle and end numbers are in sorted order, it doesn't actually do a thing.
This URL might help you with some code:
Heap sort at Geeks for Geeks
As for using a fix-length array -- that's problematic, too, but using std::vector is probably a bit much for you. I'd make sure that your input loop doesn't run into issues or start with a much longer beginning array.

Is there a way to randomly add or subtract two specific numbers or more to an array of values?

I am supposed to make a function that accepts an integer array as an input, and then randomly modify each value within the array by either -38 or 55, specifically. However, I'm not sure how to randomly choose whether a number will get deducted by -38 or added by 55, and how to go about this process.
I tried making an if statement within my function, stating that if a function is even (array[i] % 2), then deduct by -38, and if the number is odd (else statement), add by 55. While this may work, it's not the right way to answer this question, because what if I wanted to add an even number by 55? Or vice versa with an odd number with subtracting 38?
#include <iostream>
using namespace std;
#include <time.h>
#include <cstdlib>
int output(int array[]){
for(int i = 0; i<5; i++){
cout << array[i] << " ";
}
}
int offset(int array[]){
for (int j = 0; j < 5; j++) {
int myrand = rand();
if (myrand % 2 == 0){
array[j] = array[j] - 38;
}
else{
array[j] = array[j] + 55;
}
}
}
int main()
{
srand(time(NULL));
int array[5] = {1, 2, 3, 4, 5};
cout << "Original: ";
output(array);
offset(array);
return 0;
}
If the value within an array is 5, it should have the possibility of being 10 or 0, and so forth with any numbers.
Let's get you started and then you can go from there. When beginning to learn any programming language, (or any language for that matter), you start with a large amount of what makes up the language, what are the words and what are the rules for putting them together. For a programming language that is its "syntax". Every language has its own. You begin learning the syntax with minimal examples that make use of the basic types and progress from there.
With a compiled language, you add to that, how you translate the collection of proper syntax in a file into a machine readable executable. How you compile the source code into an executable.
At this point, the most important thing you can do is make friends with your compiler and listen to what it is telling you. You do this most effectively by enabling compiler warnings so your compiler will point out for you the line (and in many cases the character in the line) that it finds troubling. The rule is
"Always compile with warnings enabled, and do not accept code
until it compiles cleanly without warning."
To enable warnings add -Wall -Wextra -pedantic to your gcc/clang compile string. For VS (cl.exe on windows), use /W3. There are always additional warnings you can add, but this will provide a thorough set that if you follow the rule will save you hours of time debugging.
With that as background, let's look at what you are trying to do. First, you have tagged your Question as C++. I provided you in the comment above a place to start to determine what basic header files were needed in your proposed code. C++ Standard Library headers. Checking you will find that C++ provides an implementation of time.h as the header ctime (all of the standard C headers are generally named c......). So here, based on what you included in your code, you would need, at minimum,
#include <iostream>
#include <cstdlib>
#include <ctime>
While you can use 5 in your code, you want to avoid hard-coding numbers (unless required by the standard library function being used, such as the C scanf field-width modifier, which does not allow a named constant or variable in that case). Hard-coding numbers is called using magic-numbers and is best avoided.
When you declare and initialize an array, you can declared the array with an empty [] (which would normally be an incomplete type), but by virtue of providing a braced-initializer, the compiler uses the number of elements provided to size the array at compile time. You can then determine the number of elements with the array by dividing the sizeof array by the sizeof (an_element). You can simply derefernce the array to obtain the first element, so you will see it written as follows:
int main (void) {
int array[] = {1, 2, 3, 4, 5};
int nelem = sizeof array / sizeof *array; /* number of elements */
...
Now when passing basic-type arrays to a function, you also need to pass the number of elements as well. Why? When an array is passed as a parameter (actually on any access, subject to limited exceptions), an array is converted to a pointer to the first element. If you tried to use the sizeof array / sizeof (an_element) within a function after passing the array as a parameter, you would end up with sizeof (a_pointer) / sizeof (an_element) which is certainly not going to work.
So for example, in your output() function, to pass the number of elements along with the array, you would need:
void output (int array[], int nelem)
{
for (int i = 0; i < nelem; i++) {
cout << array[i] << " ";
}
cout << '\n';
}
The same would apply equally to your offset() function:
void offset (int array[], int nelem)
{
for (int j = 0; j < nelem; j++) {
int myrand = rand();
if (myrand % 2 == 0) {
array[j] = array[j] - 38;
}
else{
array[j] = array[j] + 55;
}
}
}
(note: the return type for each function has been changed to void rather than int. Neither function need provide an indication of success/failure and neither is returning a value that is being used back in the calling function, main() here. In each case you are simply printing the elements of the array, or updating their values in-place.)
The remainder for your first attempt is simply to output the array before applying the offset, and then again afterwards. Your main() could be:
int main (void) {
int array[] = {1, 2, 3, 4, 5};
int nelem = sizeof array / sizeof *array; /* number of elements */
srand (time(NULL)); /* seed random number generator */
cout << "Original: "; /* output original array */
output (array, nelem);
offset (array, nelem); /* apply offset to array */
cout << "Updated : "; /* output original array */
output (array, nelem);
return 0;
}
If you put all the pieces together, and compile with warnings enabled, will find your code compiles without warning and produces a working executable.
Example Use/Output
$ ./bin/randaddtoarray
Original: 1 2 3 4 5
Updated : 56 57 58 -34 -33
If you run it multiple times you will probably see that you don't always have an even number of odd or even random numbers. That is the nature of random numbers.
As mentioned in the comments, there are many many ways to approach developing a random scheme for applying your -38 or +55. Take some time and research the different methods and try implementing them and see how your results change. You will probably want to add more than 5 values to your array to be able to draw any kind of distribution conclusion. Five values is really not enough to provide any type of clear comparison.
Let me know if you have further problem.

Inconsistency between int and bool

I just implemented breadth first search in c++ and instead of declaring a vector as bool, I declared it as an int. This lead to a very odd observation. When I used int, the code printed the following:
1
32763
-524268732
Throughout the entire code, I don't provide any such value to variable as the 2nd and 3rd node receive, so I assume that they are just garbage values, but why do garbage values even come up, when I'm initialising the vector to be full of zeroes ??? You may check the code to be that below:
#include <iostream>
#include <queue>
using namespace std;
queue<int> neigh;
vector< vector<int> > graph(3);
vector<int> flag(3, 0);
int main(void)
{
graph[0].push_back(1); graph[0].push_back(2);
graph[1].push_back(0); graph[1].push_back(2);
graph[2].push_back(0); graph[3].push_back(1);
neigh.push(0);
while(!neigh.empty())
{
int cur = neigh.front();
neigh.pop();
flag[cur] = 1;
for(int i = 0, l = graph[cur].size();i < l;i++)
{
if(!flag[graph[cur][i]])
neigh.push(graph[cur][i]);
}
}
for(int i = 0;i < 3;i++)
{
cout << flag[i] << endl;
}
}
Alright, then I changed just a single line of code, line number 7, the one where I declare and initialise the flag vector.
Before:
vector<int> flag(3, 0);
After:
vector<bool> flag(3, false);
And voila! The code started working:
1 //The new output
1
1
So, my question is, what is the problem with the code in the first place ? I believe it may be some kind of error I made, or possibly that its only by chance that my bfs implementation works at all... So, what is the truth, SO? What is my (possible) mistake ?
You are accessing your vector out of bounds here:
graph[3].push_back(1);
At this moment, graph only has three elements. This leads to undefined behaviour.

Im trying to make a program that just displays the tiles 2 players would start with in Scrabble, but it keeps crashing?

I have this program I am working on that is similar to scrabble. This program below is a "mini-program" however, it should just be able to print out the 7 starting tiles for the two players. This mini-program seems like it should be fully operational, but it just crashes. Do you guys have an ideas as to why it doesnt run. Thanks so much for your time! :D
#include <iostream>
#include <string>
#include <fstream>
#include <cstdlib>
#include <ctime>
#include <cctype>
using namespace std;
void selectTiles(char (*lettArray)[53], char (*playPieces)[8], char (*compPieces)[8])
{
int pP1, pP2, pP3, pP4, pP5, pP6, pP7;
int cP1, cP2, cP3, cP4, cP5, cP6, cP7;
//0000000
srand(time(NULL));
rand();
pP1=rand()%53;
(*playPieces)[0]=(*lettArray)[pP1];
strcpy((lettArray)[pP1],"*");
do{
pP2=rand()%53;
(*playPieces)[1]=(*lettArray)[pP2];
}while(strcmp((lettArray)[pP2],"*")==0);
do{
pP3=rand()%53;
(*playPieces)[2]=(*lettArray)[pP3];
}while(strcmp((lettArray)[pP3],"*")==0);
do{
pP4=rand()%53;(*playPieces)[3]=(*lettArray)[pP4];
}while(strcmp((lettArray)[pP4],"*")==0);
do{
pP5=rand()%53;(*playPieces)[4]=(*lettArray)[pP5];
}while(strcmp((lettArray)[pP5],"*")==0);
do{
pP6=rand()%53;(*playPieces)[5]=(*lettArray)[pP6];
}while(strcmp((lettArray)[pP6],"*")==0);
do{
pP7=rand()%53;(*playPieces)[6]=(*lettArray)[pP7];
}while(strcmp((lettArray)[pP7],"*")==0);
do{
cP1=rand()%53;(*compPieces)[0]=(*lettArray)[cP1];
}while(strcmp((lettArray)[cP1],"*")==0);
do{
cP2=rand()%53;(*compPieces)[1]=(*lettArray)[cP2];
}while(strcmp((lettArray)[cP2],"*")==0);
do{
cP3=rand()%53;(*compPieces)[2]=(*lettArray)[cP3];
}while(strcmp((lettArray)[cP3],"*")==0);
do{
cP4=rand()%53;(*compPieces)[3]=(*lettArray)[cP4];
}while(strcmp((lettArray)[cP4],"*")==0);
do{
cP5=rand()%53;(*compPieces)[4]=(*lettArray)[cP5];
}while(strcmp((lettArray)[cP5],"*")==0);
do{
cP6=rand()%53;(*compPieces)[5]=(*lettArray)[cP6];
}while(strcmp((lettArray)[cP6],"*")==0);
do{
cP7=rand()%53;(*compPieces)[6]=(*lettArray)[cP7];
}while(strcmp((lettArray) [cP7],"*")==0);
//0000000
}
int main()
{
char lettArray[53]="AABBCCDDEEFFGGHHIIJJKKLLMMNNOOPPQQRRSSTTUUVVWWXXYYZZ";
char (*pLetters)[53]=&lettArray;
char player[8];
char (*pPlayer)[8]=&player;
char computer[8];
char (*pComputer)[8]=&computer;
selectTiles(pLetters,pPlayer,pComputer);
for (int i=0;i<53;i++)
cout<<"|"<<lettArray[i]<<"|";
cout<<endl;
for (int i=0;i<8;i++)
cout<<"|"<<player[i]<<"|";
cout<<endl;
for (int i=0;i<8;i++)
cout<<"|"<<computer[i]<<"|";
cout<<endl;
system("pause");
}
I compiled this program on g++ version 4.5.3 under Cygwin and, after changing #include <string> to #include <cstring> it compiled and ran without apparent problem.
However, when I looked at the output, it was clear that the program was writing 8 letters instead of 7 for each player's Scrabble letters and the last letter in each set was from a previously unallocated piece of memory.
Thus, I'd suggest the lines like:
for (int i=0;i<8;i++)
... should be:
for (int i=0;i<7;i++)
There might well be other errors that I haven't spotted yet.
(EDIT)
The line:
for (int i=0;i<53;i++)
... also prints an extra character. It should be:
for (int i=0;i<52;i++)
Also, amplifying Beta's point on the use of strcpy, strcpy(dest,"*") will copy two characters to the address pointed to by dest, not one character. That is, it will copy "*" and the null that terminates the string. That will probably overwrite data that was not intended to be overwritten with the null.
I think the problem is here:
void selectTiles(char (*lettArray)[53], ...)
{
...
pP1=rand()%53;
strcpy((lettArray)[pP1],"*");
...
}
That strcpy is not doing what you think it's doing. It's (usually) writing out of bounds and causing undefined behavior. Use std:string instead of char [], references instead of pointers, and test your code as you develop it, and you won't have these problems.
EDIT:
All right, first let's tidy up the code so we can see what we're doing. All of those copy-and-pasted do-while loops in selectTiles(...) are painful to look at. Step 1, we introduce a new function for drawing a random character from lettArray:
char draw(char *lettArray)
{
int pp;
do{
pp=rand()%53;
}while(lettArray[pp]=='*');
return(lettArray[pp]);
}
void selectTiles(char (*lettArray)[53], char (*playPieces)[8],
char (*compPieces)[8])
{
int pP1;
//0000000
srand(time(NULL));
rand();
pP1=rand()%53;
(*playPieces)[0]=(*lettArray)[pP1];
strcpy((lettArray)[pP1],"*");
(*playPieces)[1]=draw(*lettArray);
(*playPieces)[2]=draw(*lettArray);
(*playPieces)[3]=draw(*lettArray);
(*playPieces)[4]=draw(*lettArray);
(*playPieces)[5]=draw(*lettArray);
(*playPieces)[6]=draw(*lettArray);
(*compPieces)[0]=draw(*lettArray);
(*compPieces)[1]=draw(*lettArray);
(*compPieces)[2]=draw(*lettArray);
(*compPieces)[3]=draw(*lettArray);
(*compPieces)[4]=draw(*lettArray);
(*compPieces)[5]=draw(*lettArray);
(*compPieces)[6]=draw(*lettArray);
//0000000
}
This alone reduces the length of the code by 30 lines and makes it much easier to read. It also underscores the silliness of passing pointers to arrays. In C an array is passed as a pointer to the first element, so no further indirection is necessary. And since (in selectTiles) lettArray is a pointer to a char[], this line:
strcpy((lettArray)[pP1],"*");
is deadly. If pP1 is, say, 12, you're not putting an asterisk at the twelfth (or thirteenth) position in the array, you're copying "*" into the twelfth char array past the real one. That is, you're writing out of bounds. Let's correct the line (and put in some for loops):
pP1=rand()%53;
(*playPieces)[0]=(*lettArray)[pP1];
(*lettArray)[pP1]= '*';
for(int k=1 ; k<7 ; ++k)
(*playPieces)[k]=draw(*lettArray);
for(int k=0 ; k<7 ; ++k)
(*compPieces)[k]=draw(*lettArray);
And the code stops crashing. There's still a lot of improvement possible, but now it works.

Segmentation Fault reason unknown Opencv

I have the following code compiled in linux terminal (c++ in linux) and am using OpenCv 2.4.3.
However, am getting a segmentation fault in run time and I really have no clue as to why. I have placed differnt cout statements to know if the program processed to the particular stage but in vain. Could you please help me? Please explain me what exactly is this segmentation fault. Am stuck here for a long time.
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <iostream>
#include <stdlib.h>
using namespace cv;
using namespace std;
int main()
{
cout<<"check"<<flush;
Mat src,src_gray,dst;
int kernel_size = 3;
int scale = 1;
int delta = 0;
int ddepth = CV_16S;
char* window_name = "sharpness estimate";
int freq,rows,cols =0;
double *estimate,*min = 0;
Point *minLoc,*maxLoc = 0;
src = imread("/home/siddarth/examplescv/erez images/image53.jpg");
if( !src.data )
{
return -1;
}
namedWindow(window_name,CV_WINDOW_AUTOSIZE);
Mat abs_dst;
cvtColor(src,src_gray,CV_RGB2GRAY);
Laplacian(src_gray,dst,ddepth,kernel_size,scale,delta,BORDER_DEFAULT);
convertScaleAbs(dst, abs_dst);
minMaxLoc(dst,min,estimate,minLoc,maxLoc,noArray());
Size s = dst.size();
rows = s.height;
cols = s.width;
cout<<rows<<endl<<cols<<endl;
for(int i=0;i<=rows;i++)
{
for(int j=0;j<=cols;j++)
{
if(dst.at<double>(i,j) >= *estimate-100
&& dst.at<double>(i,j) <= *estimate+100)
{
cout<<freq++;
}
}
}
cout<<"estimate :"<<*estimate<<endl;
cout<<"frequency :"<<freq<<endl;
imshow(window_name,abs_dst);
waitKey(1000);
return 0;
}
The code doesn't cross the first "check" print statement just after the main function declaration. That is the confusing issue. But once I flushed the first print statement, it got executed. I am still facing issues.
Make sure you insert std::endl into cout so that the buffer is flushed. This will probably be why you're not seeing any output.
One immediate issue is that your for loops check the condition with <=, meaning that you're probably going one past the end. But since you're using at, you should have an exception thrown (assuming this Mat type acts like a standard container).
Also, you're creating lots of pointers to pass as some function arguments (for example, double* estimate). This doesn't actually give you a double object though, just a pointer. Unless the function you're passing them to is allocating a double for you (which I hope it's not), you're doing it wrong. You should be doing:
double estimate;
minMaxLoc(/* ... */, &estimate, /* ... */);
You'll need to do that with all of the values you're getting through output parameters.
Another thing to note: Doing int i, j = 0; only initialises j to 0, but not i. You need to do int i = 0, j = 0;.
Okay, I'm going to explain why fixing the initialisers works. I had to look up the definition of minMaxLoc to see what happens. Basically, the function is something like the following:
void setToFive(int* x)
{
if (x) {
*x = 5;
}
}
This function will take a pointer to an int, and then set that int to the value 5. However, if the pointer passed is a null pointer, the value will not be set (otherwise there'll be undefined behaviour because you're derefencing a null pointer). Basically, passing a null pointer says "I don't care about this value so don't give it to me".
Now when you were initialising your pointers, you were doing:
double *estimate, *min = 0;
This only sets min to the null pointer. Since estimate is left uninitialized, you can't rely on its value being null. You need to provide an initialiser for each declarator:
double *estimate = 0, *min = 0;
Thanks to #sftrabbit. The problem was the initialization. instead of
int freq,rows,cols=0;
The change was
int freq=0,rows=0,cols=0;
this removed the segmentation fault. Thanks a lot for your help :).
Since you are in a Linux environment, you can use valgrind to find out exactly where the segmentation fault is happening. Just type valgrind before the name of the program, or the way you execute your program. For example, if you execute your program with the following command:
hello -print
issue the following command instead:
valgrind hello -print
I see you already solved this one, but this may be helpful in the future!