C++ code malfunctioning - c++

I wrote a basic linear search C++ code. Whenever I run this, the result I get is always the opposite of the expected result.
For instance, I want to search 4. In an array where it is present, it will say the number is not found, but upon searching an absent element, it will say the element is found at position 0.
Even after an hour or so of constantly looking at the code I have not found any solution.
#include <iostream>
using namespace std;
//scanning program
int linearsearch (int A[] , int z, int n, int srchElement) {
for (int z = 0; z < n; z++) {
if (A[z] == srchElement) {
return z;
}
}
return -1;
}
//main program
int main () {
int i, n, A[1000], z;
//asking for size of array
cout << "give size of the array needed to be scanned: ";
cin >> n;
cout << endl;
if (n > 999) {
cout << "invalid value";
return -1;
}
//making sure of the size of the array
cout << "enter " << n << " integers: ";
//asking for the array
for (i = 0; i < n; i++) {
cin >> A[i];
}
int srchElement, index;
do {
cout << endl << "enter element to search (-1 to exit ): ";
//srchElement is defined here
cin >> srchElement;
if (srchElement == -1) break;
index = linearsearch(A, n, srchElement, z);
//calling thscanning function
if (index == -1) {
cout << srchElement << " not present" << endl;
}
//outputting the results of the scan
else {
cout << srchElement << " present " << index << endl;
}
} while (true);
return 0;
}

Your parameters to linearsearch are not in the correct order - you are passing n into the unused z parameter. With your current function you should call it like:
index=linearsearch(A, 8675309, n, srchElement);
I recommend you get rid of z as a parameter, then you won't need to pass a value to it.
Also please note: Spaces and indentation do not make your program run slower, but they do make it a lot easier to read.

The order of arguments in the function definition is not the same as in the function call.
It should be like (Line no 4):
int linearsearch (int A[] , int n, int srchElement, int z)

This is your search function correctly formatted:
int linearsearch (int A[] , int z, int n, int srchElement)
{
for (int z = 0; z < n; z++)
{
if(A[z] == srchElement)
{return z;}
}
return -1;
}
and here is how you call it:
index=linearsearch(A, n, srchElement, z);
You pass a value z in with the call. It is unitialised and does nothing, in main() or in the function.
You pass the arguments into the function in the wrong order. You are:
passing n (from main()) into the unused z value
searching for the uninitialised z (from main())
passing in the element you are looking for as n (array size). (This will quite likely result in out of bounds error, e.g. if searching for -1)
Try this:
int linearsearch (int A[], int n, int srchElement)
{
for (int z = 0; z < n; z++)
{
if(A[z] == srchElement)
{return z;}
}
return -1;
}
and here is how you call it:
index=linearsearch(A, n, srchElement);

You immediate problem: as The Dark spotted, this call:
index=linearsearch(A, n, srchElement, z);
doesn't match the declaration
int linearsearch (int A[] , int z, int n, int srchElement)
Function arguments in C++ are positional: just because the last call argument and the second declaration parameter are both called z doesn't mean anything.
Now, there are several local issues of style:
this kind of function is risky in the first place
int linearsearch (int[],int,int,int)
because it relies on you remembering the correct order for the last three integer parameters. If you must do this, you should be extra careful to give them all distinctive names, be very clear about which is which, and keep the order consistent across families of functions.
It's better, where possible, to help the compiler help you out, by either giving the arguments distinct types (or enumerations, or whatever), or grouping them into a structure.
For example, using a std::vector<int> instead of your array effectively groups int A[] and int n together in an object, so they can't get out of sync and n can't get confused with the other integers floating around
You shouldn't be passing z in the first place. You immediately hide it with a local int z in the loop, so it can't be doing anything. Remove it from both the declaration and the call. This simplification is sufficient to fix your bug.
Your secondary problem is that the code is ugly. It's poorly formatted and hard to read, and and that makes it more difficult to spot mistakes. Try to make your code simple and readable: there's less opportunity for things to go wrong, and its easier to see the problems when they occur.
Your tertiary problem is that the code is bad. Most of this can be done using standard library facilities (making your code simpler), which are themselves well-tested and generally have carefully-designed interfaces. Use them first, and replace if necessary.

Related

Convert userInput (string) to UserInput(int) mid for loop

I am working on a program that has to do with arrays. I decided that the input the user provides to be a string to later being converted to an integer once it is determined it is one. This way the program wouldn't run into an error when words/letters are entered. The issue I am having is the conversion from string to int. I want to change that because later in the program I am going to search the array for a given value and display it and its placement in the array. This is the code I have thus far:
#include <stdio.h>
#include <iostream>
using namespace std;
//check if number or string
bool check_number(string str) {
for (int i = 0; i < str.length(); i++)
if (isdigit(str[i]) == false)
return false;
return true;
}
int main()
{
const int size = 9 ;
int x, UserInput[size], findMe;
string userInput[size];
cout << "Enter "<< size <<" numbers: ";
for (int x =0; x < size; x++)
{
cin >> userInput[x];
if (check_number(userInput[x]))
{//the string is an int
}
else
{//the string is not an int
cout<<userInput[x]<< " is a string." << "Please enter a number: ";
cin >> userInput[x];}
}
int i;
for (int i =0; i < size; i++)
{
int UserInput[x] = std::stoi(userInput[x]); // error occurs here
}
for (int x= 0; x< size; x++)
{
if (UserInput = findMe)
{
cout <<"The number "<< UserInput[x] << "was found at " << x << "\n";
}
else
{
//want code to continue if the number the user is looking for isn't what is found
}
}
return 0;
}
Made comments here and there to kinda layout what I want the code to do and whatnot. I apperciate any help you can give, thank you.
This code:
int UserInput[x] = std::stoi(userInput[x]);
declares an int array of size x, to which you are assigning a single int (the result of std::stoi), which obviously doesn't work.
You need to assign an int to a particular index of the existing array, like this:
UserInput[x] = std::stoi(userInput[x]);
Given this comparison if (UserInput = findMe), which should actually be if (UserInput == findMe), it seems you want to declare a single int which stores the result of std::stoi. In that case, you should use a different name than the array, and write something like this:
int SingleUserInput = std::stoi(userInput[x]);
Also, please indent your code consistently, and compile with all your warnings turned on. Your code will be easier to read, and the compiler will point out additional problems with your code. And please don't use using namespace std;, it's a bad habit.
I don't understand why do u even need to use another loop to convert the string value to int. stdio.h header file does provides with preinstalled functions to make your work easier...
for (int x =0; x < size; x++)
{
getline(cin,userInput1[x]);
UserInput[x]=stoi(userInput1[x]);
}
stoi() function converts the string input to int, and you can call it dynamically as soon as you enter your string input,It will make you work easier and reduce the time complexity

Initialize all elements in matrix with variable dimensions to zero

I'm trying to initialize an int matrix in C++, with user-inputted dimensions, with every element set to zero. I know there are some elegant ways to do that with a one-dimensional array so I was wondering if there are any similar ways to do it with a two-dimensional array without using for loops and iterating through every element.
I found a source that gave several different ways, including std::fill (I've modified the code so that the dimensions are read with cin):
#include <iostream>
using namespace std;
int main() {
int x;
cin >> x;
int matrix[x][x];
fill(*matrix, *matrix + x * 3, 0);
for (int i = 0; i < x; i++) {
for (int j = 0; j < 3; j++) {
cout << matrix[i][j] << " ";
}
cout << endl;
}
}
But why does this work, and why would the pointer to the matrix in the arguments for fill be necessary if it's not necessary for a one-dimensional array? That source said it was because matrixes in C++ are treated like one-dimensional arrays, which would make sense, but that is why I don't understand why the pointer is needed.
I don't know if this is relevant, but in case it can help, I've described my previous attempts below.
At first I thought I could initialize all elements to zero like in a one-dimensional array. For the matrix, this worked fine when the side lengths were not read with cin (i.e. when I declared the matrix as int matrix[3][3] = {{}}; as answered here) but when I tried getting the side lengths from cin I started getting errors.
This was my code:
#include <iostream>
using namespace std;
int main() {
int x;
cin >> x;
int matrix[x][x] = {{}};
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
cout << matrix[i][j] << " ";
}
cout << endl;
}
}
And when I tried to compile it, it threw this error:
matrix_test.cpp:7:14: error: variable-sized object may not be initialized
int matrix[x][x] = {{}};
^
1 error generated.
Why you're getting the error
c-style arrays (such as int matrix[3][3]) must have size specified at the point you declare it. They can't vary in size in C++.
What you could do instead.
If you use std::vector, there's a really elegant way to do it:
#include <vector>
#include <iostream>
int main() {
using namespace std;
int x;
cin >> x;
auto matrix = vector<vector<int>>(x, vector<int>(x, 0));
// This is how we can print it
for(auto& row : matrix) {
for(auto& elem : row) {
cout << elem << ' ';
}
cout << '\n';
}
}
In C++17, you can shorten this even further:
auto matrix = vector(x, vector(x, 0));
What vector(number, thing) means is "Create a vector of number, where each element is thing".
The second dimension of two-dimension array must be a compile time constant, but in your code x is not.
Actually if you write a function with a two-dimension parameter, the second dimension must also be a compile time constant. That's because the array is stored linearly in the memory and the compiler must know the second dimension to calculate the offset correctly.

Words of length k generation from a DFA

Good day,
I'm having a serious problem into generating a list with all the words of length k (the generate function is the function intended to generate all the words of length k, the other function is used to find out if a word is accepted or not) from a DFA just by using the DFS algorithm, here's my attempt:
#include<vector>
#include<iostream>
#include<fstream>
#include<string.h>
using namespace std;
vector < pair <int,char> > a[100];
int viz[100], v[100];
char s1[100];
void accepted (int q, char c, char s[100], int x) {
c = s[x];
viz[q] = 1;
cout << q;
for (int i = 0; i < a[q].size(); i++)
if (a[q][i].second == c) {
x++;
accepted (a[q][i].first, a[q][i+1].second, s, x);
}
}
void generate (int q, int k) {
int x = 0;
v[q] = 1;
while (x < k) {
cout << a[q][0].second;
for (int i = 0; i < a[q].size(); i++)
if (v[a[q][i].first] == 0)
{
cout << a[q][i].second;
generate(a[q][i].first, k);
}
x++;
}
}
int main() {
ifstream f ("input.txt");
int n, m, x, y, i, j, k;
char c;
char s[100];
f >> n >> m;
for (i = 0; i < m; i++) {
f >> x >> y;
f >> c;
a[x].push_back (make_pair(y,c));
}
for (i = 0; i < n; i++) {
cout << i << ": ";
for (j = 0; j < a[i].size(); j++)
cout << a[i][j].first << a[i][j].second << " ";
cout << endl;
}
cout << endl << "Fiite states: 2, 3" << endl << endl;
cin.get (s,100);
accepted(0, s[0], s, 0);
if (viz[2] == 1) cout << endl << "Accepted";
cout << endl;
cin >> k;
generate (0, k);
cout << endl;
return 0;
}
Also here's how my input looks like:
4 6
0 0 a
0 1 b
1 2 c
2 2 a
2 3 c
3 3 c
Here's how the DFA and the output would look like:
The serious problem I'm facing is that I can't find a way to ouput properly all the obtained words to the screen by calling the generate function.
I changed your generate function as below. Following that is an explanation as to what I thought and how I changed it.
void generate (int q, int k, string &s) {
if (k > 0) {
for (int i = 0; i < a[q].size(); i++)
{
s += a[q][i].second;
generate(a[q][i].first, k-1, s);
s.pop_back();
}
}
else {
cout << s << endl;
}
}
First and foremost, you were attempting a mixture of recursive and repetitive version of DFS, but you had no structure for keeping the stack if you were, and I doubt, going for a repetitive version using an explicit stack. Basically, your outer while loop was wrong, as the depth should increase as you recursively traverse the graph and not repetitively at a single level of recursion using a while loop as you did. You could also, as I mentioned, have a repetitive approach and use an explicitly defined stack other than the one implicitly used by memory when you implement DFS recursively. But it was easier and more intuitive to get a grasp of DFS with its recursive implementation, so I left out the outer loop.
Secondly, keeping a list of visited nodes is not a good idea as you want to list all k-length strings and your DFA is not a simple graph. (i.e. there may exist edges from node u to node u) So I removed the if statement inside the for loop as you could visit the sane node multiple times. Your approach is exponential based on the branching factor of the DFA, but if your k is small enough, it should work regardless of that. And the approach being exponential is not the problem to the solution of which you are looking with this question.
Thirdly, probably due to your usage of while loop, there was a mixup with printing a single character at each level, which is incorrect. Remember, at every node of depth k, you have to print all the characters you encountered starting from the root of the tree. That is why I added a string as the third parameter to your function. Don't worry, though, it's passed by reference and it will only cause an addition of O(k) space complexity to your algorithm, which should be negligible.
If in your main function you start traversing using the call below, you will find that it works properly.
string S;
generate(0, k, S);

To write a program to remove duplicates from an array

I am working on program that remove duplicates from an array I am using three functions here: one to take the input such as the size and the number, second function to remove duplicates and return the number without duplicates and the third function just a report show the size and the new number but I am having problem I don't know in what step I think in report or phillip erreur:
In function ‘int main()’: invalid conversion from ‘int*’ to ‘int’,initializing argument 1 of ‘void report(int, int)’
#include <iostream>
using namespace std;
const int size = 100;
void phillip(int[], int & );
/* Preconditions: Array of base type in declared and int varuable declared
postconditions: the array is filled with values supllied by the user at
the keybord. the user is assked how many values they want - this value is
given to the second argument.
*/
int remdubs(int[], int noel);
/* Preconditions: An array of basetype int that has noel values.
postconditions: The number of unique elemts in the array is returned. The function removes all dubplicates inside the array.
*/
void report(int s, int d);
int main()
{
int ruby[size];
int numele, numuniq;
phillip(ruby, numele);
numuniq = remdubs(ruby, numele);
report(ruby, numuniq);
return 0;
}
void phillip(int[], int& )
{
int s;
cout << "\nHow many values you want? ";
cin >> s;
cout << "\nPlease input 10 integers, hitting return after each one \n";
for (int i = 0; i < s; i++)
{
int num;
cin >> num;
}
}
int rembups(int sapphire[], int noel)
{
for (int i = 0; i < noel; i++)
{
for (int j = i + 1; j < noel; j++)
{
if (sapphire[i] == sapphire[j])
{
for (int k = j; k < noel; k++)
sapphire[k] = sapphire[k + 1];
noel--;
j--;
}
}
}
return noel;
}
void report(int s, int d)
{
cout << "\nYou entered " << s << "distinct numbers: " << d;
}
Can't explain it better than your error:
void report (int s, int d);
this function asks for two integer values, you're passing an array to it which, with decayed functionalities, will behave like an integer pointer
int ruby[size];
report (ruby, numuniq);
I'm unsure on the behavior of your program but you should rather do something like
report(ruby[0], numuniq);
that is: access the element of the array and feed it to the function
The error is in the function report, it asks for two integer and you are passing an array and an integer instead
and again i don't think you need 2 parameters in the function report one would solve your purpose
void report(int d)
{
cout << "\nYou entered <<d<<" distinct numbers";
}
that would solve your error but i don't think you would get your desired output
Few problems with the code:
Report function should be expecting an array of integers rather than single integer
Try using human readable variable or function names
remdubs was renamed to rempubs in function definition
phillip function definition didn't have params defined properly
You have const int size but do not use it
remdups has a bug somewhere. I will leave that out as I am trying to fix other issues here.
There are better ways of finding duplicates than remdups. Please look at some other solutions.
I have fixed your code and provided it here on ideone

recursive algorithm to sum of every element in an array with a value lesser than x

I'm a beginner to c++ and I'm trying to write an recursive algorithm that returns the sum of every element in an array with a value less than x.
Here is my code:
#include <iostream>
using namespace std;
int sumOfElement(int xList[],int x, int lengthOfArray){
int sum = 0;
if (lengthOfArray == 0)
return sum;
else
for (int i=0; i <= lengthOfArray; i++) {
if(xList[i] < x)
return sum + xList[i];
else
sumOfElement(xList,x,lengthOfArray-1);
}
}
int main() {
cout << "Size of Array: ";
int size;
cin >> size;
int *xList = new int[size];
//Inputing array.
cout << "Enter elements of array followed by spaces: ";
for (int i = 0; i<size; i++)
cin >> xList[i];
cout << "Enter the integer value of x: " <<endl;
int limit;
cin >> limit;
cout << "Sum of every element in an array with a value less than x: " << sumOfElement(xList,limit,size) << endl;
return 0;
}
I'm using Visual Studio, while I was running the code, I got this warning: "warning C4715: 'sumOfElement' : not all control paths return a value. " And the program always stop executing when it asks me to enter the integer value for x.
What's wrong with my code?
Your approach here isn't really recursive. The idea with recursion is to consider a base case, and then consider how to reduce the problem at each step until you get to the base case.
For this problem:
The base case is when the length of the array is zero. In this case we return a sum of zero. (Intuitively: if the array is empty then we're adding nothing, giving a sum of zero.)
In order to reduce our array we look at the last element of the array (ie. at lengthOfArray - 1). We process this element: if it's less than x we add it, if it's not then we ignore it. We then get the result of processing the rest of the array by the same means (by calling the same function, but with a different array length), and add our result if applicable.
So, some example code:
int sumOfElement(int xList[], int x, int lengthOfArray){
if (lengthOfArray == 0) {
// base case
return 0;
} else {
int value = xList[lengthOfArray-1];
if (value < x) {
// process the rest of the array and add our result
return value + sumOfElement(xList, x, lengthOfArray - 1);
} else {
// process the rest of the array
return sumOfElement(xList, x, lengthOfArray - 1);
}
}
}
for (int i=0; i <= lengthOfArray; i++)
{
if(xList[i] < x)
return sum + xList[i];
else sumOfElement(xList,x,lengthOfArray-1);
}
You shouldn't have a for-loop, and recursive functions should "return" the deeper call, so
int retVal = 0;
if(xList[lengthOfArray-1] < x)
retval = xList[lengthOfArray-1]
return retVal + sumOfElement(xList,x,lengthOfArray-1);