I'm very new to programming, I'm just in the 2nd sem of my first year in college so please go easy on the technical terms. We were asked to make a program that reads 10 integers from a file to comprise a list and asks the user to input an integer 'N'. If 'N' is in the list the program should display "FOUND" and "NOT FOUND" if otherwise. I'm getting an error in main about the arguments, it says that 'V', 'N', and 'F' in the function calls "was not declared in this scope".
#include<iostream>
#include<fstream>
using namespace std;
int fRead();
int iRead();
bool search(int, int);
void display(bool);
int main() {
fRead();
iRead();
search(V, N);
display(F);
return 0;
}
int fRead() {
int V[10], c;
ifstream fin;
fin.open("lab02.in");
for(c=0; c<10; c++)
fin >> V[10];
fin.close();
return V[10];
}
int iRead() {
int N;
cout << "Input an integer: ";
cin >> N;
return N;
}
bool search(int V[10], int N) {
bool F = false;
if(V[10] == N)
F = true;
return F;
}
void display(bool F) {
if(F == true)
cout << "\nFOUND" << endl;
else
cout << "\nNOT FOUND" << endl;
}
Local variable (those declared inside a function) are only visible to the block (those things delimited by { and }) where they are declared. If you want to use different functions for various operations you'll need to pass the variables as arguments to the corresponding functions.
As an aside, you should always verify that your read operation was successful before using the result, e.g.:
int N(-1);
if (!(std::cin >> N)) {
std::cout << "ERROR: failed to read integer\n";
}
the integers V N and F are basically described in other functions.
To solve this problem you should declare them in main
the program should go as follows
void f_read(v[]);
void i_read(int &);
bool bool(int,int);
void disp(bool);
void main()
{
int v[10],n;
bool f;
f_read(v);
i_read(n);
f=bool(v,n);
disp(f);
}
void fRead()
{
int c;
ifstream fin;
fin.open("lab02.in");
for(c=0; c<10; c++)
fin >> V[c];
fin.close();
}
void iRead(int &n)
{
cout << "Input an integer: ";
cin >> N;
}
bool search(int V[10], int N)
{
bool F = false;
int i;
for(i=0;i<=9;i++)
if(V[i] == N)
{
F = true;
return F;
}
}
void display(bool F)
{
if(F == true)
cout << "\nFOUND" << endl;
else
cout << "\nNOT FOUND" << endl;
}
so basically you need to pass n as a reference variable and arrays by default are passed as reference.
and also you were looking for v[10]=f ,which would have given you another array, i also corrected that
Related
I have been trying to get this to work for an hour now and I know it can't be that difficult a fix. Every time I enter the file.txt name it comes up as invalid file. I tried moving the files to the same directory as the .cpp file and everything but I just cant get it to read. Help would be appreciated.
#include<iostream>
#include<iomanip>
#include<fstream>
#include<string>
#include<assert.h>
using namespace std;
const int SIZE = 20;
void readIntFile(ifstream& x, int intArray[], int size, int &length);
void printValues(int intArray[], int& length);
char getSentinel();
int main()
{
ifstream inputStream;
const int size = SIZE;
string fileName;
int length = 0;
bool isEmpty = false;
int intArray[size];
char sentinel = 'y';
while (sentinel == 'y' || sentinel == 'Y')
{
cout << "Please enter the name of the file: ";
cin >> fileName;
inputStream.open(fileName);
if (inputStream.bad() || inputStream.fail())
{
cout << "Error, <" << fileName << "> is Invalid File Name.";
}
if (fileName.empty())
{
isEmpty = true;
}
if (isEmpty == true)
{
cout << "Error <" << fileName << "> has no data.";
}
if (inputStream.good() && isEmpty == false)
{
readIntFile(inputStream, intArray, size, length);
printValues(intArray, length);
inputStream.close();
}
sentinel = getSentinel();
}
return 0;
}
void readIntFile(ifstream& x, int intArray[], int size, int& length)
{
int count = 0;
int arrayLocation = -1;
int fileInputValue = 0;
x >> fileInputValue;
while (!x.eof())
{
count ++;
if (count > SIZE)
{
cout << "The file has more than <" << SIZE << "> values." << endl;
break;
}
else
{
arrayLocation ++;
intArray[count] = fileInputValue;
x >> fileInputValue;
}
}
}
void printValues(int intArray[], int& length)
{
assert(length > 0);
cout << "<" << length << "> values processed from the file. The values are: ";
for (int i=0; i <= length; i++)
{
cout << intArray[i] << ", ";
}
}
char getSentinel()
{
char userInput = 'n';
bool inputCheck = false;
cout << "Do you wish to process another file (y/n)?" << endl;
cin >> userInput;
do
{
if (userInput == 'y' || userInput == 'Y' || userInput == 'n' || userInput == 'N')
{
inputCheck = true;
}
else
{
cout << "Invalid response: <" << userInput << ">" << endl;
cout << "Do you wish to process another file (y/n)?" << endl;
cin >> userInput;
}
} while (!inputCheck);
return userInput;
}
Your basic problem is in function
void readIntFile(ifstream& x, int intArray[], int size, int& length)
You do not set the output variable length. And you use the wrong index value for your array. Please check.
Additionally there are many other problems in your code.
I will now paste your code, amended with my comments comments, where problems are or where things should be improved.
Please see:
#include<iostream>
#include<iomanip>
#include<fstream>
#include<string>
#include<assert.h>
using namespace std; // Should never be used. Always use fully qualified names
const int SIZE = 20; // Please use constexpr
// Do not use C-Style function prototypes. Put main at the bottom
// Do not use C-Style Arrays
// In C++ (C-Style-)Arrays are different. You actually do not pass an array to your function
// but a decyed pointer. You can pass an array by pointer or by reference, but this has a different syntax
void readIntFile(ifstream& x, int intArray[], int size, int &length);
void printValues(int intArray[], int& length);
char getSentinel();
int main()
{
// All variables shall be initialized at the point of defintion
ifstream inputStream; // You should define variables just before you need then
const int size = SIZE; // This is code duplication. And constexpr should be used
string fileName;
int length = 0;
bool isEmpty = false;
int intArray[size]; // C-Style Arrays should not be used. Use std::array or best, std::vector
char sentinel = 'y'; // You could use universal initializer syntax with braced initializer
while (sentinel == 'y' || sentinel == 'Y')
{
cout << "Please enter the name of the file: ";
cin >> fileName;
inputStream.open(fileName); // The constructor can open the file for you
if (inputStream.bad() || inputStream.fail()) // This is too complicated
{
cout << "Error, <" << fileName << "> is Invalid File Name.";
}
if (fileName.empty()) // Check is too late and not necessary
{
isEmpty = true;
}
if (isEmpty == true)
{
cout << "Error <" << fileName << "> has no data.";
}
if (inputStream.good() && isEmpty == false)
{
readIntFile(inputStream, intArray, size, length);
printValues(intArray, length);
inputStream.close(); // Destructor will clsoe the file for you
}
sentinel = getSentinel();
}
return 0;
}
// Not optimal function prototype
void readIntFile(ifstream& x, int intArray[], int size, int& length)
{
// the whole design / logic is very strange
int count = 0;
int arrayLocation = -1; // More then strange. Shows that this is a bad design
int fileInputValue = 0;
x >> fileInputValue;
while (!x.eof()) // Bad or even wrong design
{
count ++; // Wrong. See below. array will be filled with starting with index one
if (count > SIZE)
{
cout << "The file has more than <" << SIZE << "> values." << endl;
break;
}
else
{
arrayLocation ++; // This variable is not used
intArray[count] = fileInputValue;
x >> fileInputValue;
}
}
// Nobody will set the length variable
}
void printValues(int intArray[], int& length)
{
assert(length > 0); // Basically OK, but no necessary here. Cannoz happen
cout << "<" << length << "> values processed from the file. The values are: ";
for (int i=0; i <= length; i++)
{
cout << intArray[i] << ", ";
}
// There is now newline character used anywhere
}
// Very complicated
char getSentinel()
{
char userInput = 'n';
bool inputCheck = false;
cout << "Do you wish to process another file (y/n)?" << endl;
cin >> userInput;
do
{
if (userInput == 'y' || userInput == 'Y' || userInput == 'n' || userInput == 'N')
{
inputCheck = true;
}
else
{
cout << "Invalid response: <" << userInput << ">" << endl;
cout << "Do you wish to process another file (y/n)?" << endl;
cin >> userInput;
}
} while (!inputCheck);
return userInput;
}
Next, I will make your code working, by fixing the biggest problems. I will still follow your programming style.
#include<iostream>
#include<iomanip>
#include<fstream>
#include<string>
#include<assert.h>
constexpr int MaxArraySize = 20;
using IntArray = int[MaxArraySize];
void readIntFile(std::ifstream& x, int intArray[], int& length)
{
length = 0;
int value{};
while (x >> value)
{
if (length >= MaxArraySize)
{
std::cout << "The file has more than <" << MaxArraySize << "> values.\n";
break;
}
else
{
intArray[length++] = value;
}
}
}
void printValues(int intArray[], int& length)
{
std::cout << "\n<" << length << "> values processed from the file. The values are: ";
for (int i=0; i < length; i++)
{
std::cout << intArray[i] << ", ";
}
std::cout << "\n\n";
}
bool getSentinel()
{
char userInput{'n'};
bool valid = false;
while (not valid)
{
std::cout << "\n\nDo you wish to process another file (y/n)?\n";
std::cin >> userInput;
if (userInput != 'y' && userInput != 'Y' && userInput != 'n' && userInput != 'N')
{
std::cout << "Invalid response: <" << userInput << ">\n\n";
}
else {
valid = true;
}
}
return ( userInput=='y' || userInput=='Y');
}
int main()
{
int intArray[MaxArraySize];
bool sentinel = true;
while (sentinel)
{
std::cout << "Please enter the name of the file: ";
std::string fileName{};
std::cin >> fileName;
if (fileName.empty())
{
std::cout << "Error <" << fileName << "> has no data.\n\n";
}
else {
std::ifstream inputStream(fileName);
if (!inputStream)
{
std::cout << "Error, <" << fileName << "> is Invalid File Name.\n\n";
}
else
{
int length = 0;
readIntFile(inputStream, intArray, length);
printValues(intArray, length);
}
}
sentinel = getSentinel();
}
return 0;
}
and, in the end, because we are in a C++ site here, I will show (one of many possible) a more advanced C++ solution.
This is just for information and to grab some ideas for the future
#include<iostream>
#include<iomanip>
#include<fstream>
#include<string>
#include<vector>
#include<algorithm>
#include<iterator>
#include<initializer_list>
// Some aliases for easier reading and saving typing work
using DataType = int;
using Vector = std::vector<DataType>;
// Define an "in" operator
struct in {
in(const std::initializer_list<char>& il) : ref(il) {}
const std::initializer_list<char>& ref;
};
bool operator,(const char& lhs, const in& rhs) {
return std::find(rhs.ref.begin(), rhs.ref.end(), lhs) != rhs.ref.end();
}
int main() {
// As long as the user wants to read files
for (bool userWantsToContinue{true}; userWantsToContinue;) {
std::cout << "\nPlease enter a valid filename: ";
if (std::string filename{}; std::cin >> filename) {
// Open the file for reading and check, it it is open
if (std::ifstream inputStream{filename}; inputStream) {
// Read all data from the file
Vector data(std::istream_iterator<DataType>(inputStream), {});
// Now show result to user
std::cout << "\nRead values are:\n";
std::copy(data.begin(), data.end(), std::ostream_iterator<DataType>(std::cout, " "));
}
else std::cerr << "\nError: Could not open file '" << filename << "' for reading\n\n";
}
else std::cerr << "\nError: Problem with filename input\n\n";
// Ask, if the user wants to continue
bool validInput{false};
while (not validInput) {
std::cout << "\n\nDo you want to read more files? Please enter 'y' or 'n' ";
if (char selection{}; (std::cin >> selection) && (selection, in{'y','Y','n','N',}) ) {
validInput = true;
userWantsToContinue = (selection, in{'y','Y'});
}
else {
std::cout << "\n\nInvalid input, please retry\n\n";
}
}
}
return 0;
}
Try using an full absolute filename, not a relative one.
And replace cin >> fileName; with std::getline(std::cin, fileName); Otherwise, it will easily break. The getline version is much more robust.
If this was not enough, read the answer of: How do I get the directory that a program is running from? and do the checks suited for your system to find out your "working directory". This is the place where you input file must be, if you don't use absolute paths.
C++ beginner here. So I have several functions in which I am trying to pass an element of array of pointers (which contains structures (records)). I'm having trouble doing this and I'm pretty stuck and frustrated. I'm very new to pointers and memory so go easy on me. I keep getting errors when I try to pass the specific structure element into the function. (BTW: The functions are declared in a header file)
What can I do to fix/change this and make it work? Thank you for the help, it is very much appreciated.
The error I get:
'changeAssignmentGradeForStudent' was not declared in this scope
Code:
Structure student:
typedef struct
{
char firstName[50];
char lastName[50];
char studentNumber[10];
char NSID[10];
float assignments[10];
float midterm;
float final;
} Student;
void useFunctions(int recordNum)
{
// array of 10 student references
Student *students[recordNum];
// values received from the user
for (int i = 0; i < recordNum; i++)
{
cout << "Student " << i + 1 << ": " << endl;
students[i] = readStudentRecordFromConsole();
}
cout << "Would you like to make any changes to any student records? (N or Y)" << endl;
cin >> answer;
if (answer == 'N')
{
return;
}
else
{
cout << "Which student?" << endl;
cin >> student;
students[student - 1] = gradeChanges(*students[student - 1], recordNum, student);
}
}
Student *gradeChanges(Student *s, int recordNum, int student)
{
Student *changedStudent = s;
int gradeChange, aNum;
cout << "assignment number to change?" << endl;
cin >> aNum;
cout << "assignment to change?" << endl;
cin >> gradeChange;
changeAssignmentGradeForStudent(changedStudent, aNum, gradeChange); // where the errors are
return changedStudent;
}
void changeAssignmentGradeForStudent(Student *s, int a, int g)
{
if (s != NULL)
{
s->assignments[a] += g;
}
}
PS: Sorry if my code is not formatted correctly. If it isn't, feel free to edit it, thank you.
The function changeAssignmentGradeForStudent was not declared or defined before it was used, so the compiler doesn't know about it yet. You can either move the function definition up before useFunctions() or declare it at the top of the file like this:
void changeAssignmentGradeForStudent(Student*, int, int);
The compiler needs to see a declaration of your functions before these are referred to. You have to put that declaration before you call a function like this:
// This is the (forward) declaration:
void changeAssignmentGradeForStudent(Student* s, int a, int g);
Student * gradeChanges(Student* s, int recordNum, int student) {
Student *changedStudent = s;
int gradeChange, aNum;
cout << "assignment number to change?" << endl;
cin >> aNum;
cout << "assignment to change?" << endl;
cin >> gradeChange;
changeAssignmentGradeForStudent(changedStudent, aNum, gradeChange); // where the errors are
return changedStudent;
}
// This is the definition:
void changeAssignmentGradeForStudent(Student* s, int a, int g) {
if (s != NULL) {
s->assignments[a] += g;
}
}
I am designing a Logic Gate data structure in C++ called AND that has 3 functions:
a function that takes input either 1 or 0 from the user.
a function that shows output of AND Gate from the input.
a function that asks user if they want to edit their inputs and if yes, then allows them to edit the inputs they have entered.
Problem is that I cannot figure out how to call the function that edits input in the main. Following is my code.
#include<iostream>
using namespace std;
struct AND //structure called AND
{
int x, y;
AND() //constructor
{
x, y = 0; //declaring variables as inputs
}
void inputAND() //function that takes inputs from the user
{
cin >> x;
cin >> y;
}
void outputAND() //function that displays output
{
if (x == 0 || y == 0)
{
cout << "0" << endl;
}
else if (x == 1 && y == 1)
{
cout << "1" << endl;
}
}
void changeInputAND(AND change[]) //function for changing inputs
{
cout << "Do you wish change first input Yes/No:" << endl;
string t;
cin >> t;
int k;
if (t == "Yes" || "yes")
{
cout << "Enter New Input ";
cin >> k;
x = k;
}
else
{
k = x;
}
cout << "Do you wish to change the second input Yes/No:" << endl;
{
string s;
cin >> s;
int l;
if (t == "Yes" || "yes")
{
cout << "enter new input";
cin >> l;
y = l;
}
}
}
};
void main()
{
AND a1;
a1.input(); //calling the input function
a1.output(); //calling the output function
}
Suggestions for improvement and how to implement the task of editing an AND object.
Keep your class as simple as you can. Don't pollute it with code related input and output streams.
struct AND //structure called AND
{
int x, y;
AND() : x(0), y(0) //constructor
{
}
void setX(int newX)
{
x = newX;
}
void setY(int newY)
{
y = newY;
}
};
Initialize members of a class in the initializer list instead of assigning to them in the body of a constructor.
Prefer to use:
AND() : x(0), y(0) //constructor
{
}
over
AND() //constructor
{
x = y = 0;
}
Move the code to read and write from member functions to non-member functions. Don't assume whether the input/output streams are std::cin or std::cout. The driver code can choose to use std::cin/std::cout or it may choose a file, std::ifstream/std::ofstream.
// Write data to a stream
std::ostream& operator<<(std::ostream& out, AND const& a)
{
return out << a.x << " " << a.y;
}
// Read data from a stream
std::istream& operator>>(std::istream& in, AND& a)
{
in >> a.x >> a.y;
}
Also, it's better to make sure that write/read are such that what is written out can be read back.
Create a non-member function for reading user data and changing the object instead of putting it all in a member function.
// Non-member function for changing the object.
void changeInputAND(AND& a)
{
cout << "Do you wish change first input Yes/No:" << endl;
string ans;
cin >> ans;
if (ans == "Yes" || ans == "yes")
{
cout << "Enter New Input ";
int x;
cin >> x;
a.setX(x);
}
cout << "Do you wish to change the second input Yes/No:" << endl;
cin >> ans;
if (ans == "Yes" || ans == "yes")
{
cout << "enter new input";
int y;
cin >> y;
a.setY(y);
}
}
BTW, your attempt at comparing with "Yes" or "yes" is flawed.
if (ans == "Yes" || "yes")
is equivalent to
if ( (ans == "Yes") || "yes")
That will always evaluate to true. That's a very different topic :)
Put it all together in one or more functions to test the AND functionality, preferably different from main.
void testAND()
{
AND a1;
std::cin >> a1; // calling the input function
std::cout << a1 << std::endl; // calling the output function
changeInputAND(a1); // function for changing inputs
std::cout << a1 << std::endl; // calling the output function again
}
Call the test function from main.
void main()
{
testAND();
return 0;
}
//Benjamin McKinney
//CSCI 2010-10
//Spring 2015
//PASS 3
//Programmed on Windows 8.1 using Visual C++ 2010 Express
//This program plays the game MasterMind
#include <iostream>
#include <iomanip>
#include <string>
#include <fstream>
using namespace std;
struct Player
{
string Name;
int HighScores[6];
bool CheatOn;
};
struct Board
{
int NumHoles;
int Holes[6];
};
struct Guess
{
int Count;
int NumHoles;
int Holes;
};
void printHighScores(string);
void readHighScore(string);
void updateHighScore(string, int);
string getPlayer();
int getBoard();
void playGame(string);
void menu(string);
int main()
{
Player p;
srand((unsigned int)time(0));
cout << "!!! Benjamin McKinney's Master-MasterMind!!!\n";
cout << "--------------------------------------------\n";
getPlayer();
menu(p.Name);
cout << "Goodbye, " << p.Name << endl;
printHighScores(p.Name);
cout << "----------------------------------------------\n";
cout << "!!! Benjamin McKinney's Master-MasterMind!!!\n";
system("PAUSE");
return 0;
}
void printHighScores(string name)
{
return;
}
void readHighScore(string)
{
return;
}
void updateHighScore(string, int)
{
return;
}
string getPlayer()
{
Player p;
cout << "What is your name?\n";
cin >> p.Name;
cout << "Welcome, " << p.Name << endl;
p.CheatOn = false;
readHighScore(p.Name);
return p.Name;
}
int getBoard()
{
Board b;
cout << "Enter the number of holes you would like: ";
cin >> b.NumHoles;
if(b.NumHoles > 6 || b.NumHoles < 1)
{
cout << "Error! You must pick a number between 1 and 6! Try again!\n";
}
for(int i=0;i<b.NumHoles;i++)
{
b.Holes[i] = rand() % 2 + 1;
}
return b.NumHoles;
}
void playGame(string)
{
Player p;
Board b;
Guess g;
getBoard();
g.Count=0;
for(int i=0;i<b.NumHoles;i++)
{
cout << "Enter your guess for the row\n";
if(p.CheatOn == true)
{
for(int a=0;a<(sizeof(b.Holes)-1);a++)
{
cout << b.Holes[a];
}
}
cout << "Enter your guess for hole " << i << ": ";
cin >> g.Holes;
g.Count++;
}
return;
}
void menu(string)
{
Player p;
char choice;
cout << "Please choose an option below:\n";
cout << "\t P)lay\n\t Q)uit\n\tChoice: ";
cin >> choice;
if(choice == 'P')
playGame(p.Name);
else
if(choice == 'Q')
return;
else`enter code here`
if(choice == 'C')
{
p.CheatOn = true;
playGame(p.Name);
}
}
Ignore the three HighScore functions, but otherwise I can't get this to work... "Run-Time Check Failure #3 - The variable 'b' is being used without being initialized." is the main issue that I'm having. If anyone can help me I would really appreciate it. Thanks!
In the playGame function:
void playGame(string)
{
Player p;
Board b; // <----- uninitialized
// ...
for(int i=0;i<b.NumHoles;i++)
// ^^^^^^^^^^
you use b.NumHoles when you have never initialized b.
I guess you intended that getBoard() would magically have some effect on b but it doesn't. The getBoard function updates a local board but never does anything with it.
To fix this you could change getBoard to return the whole board:
Board getBoard()
{
Board b;
// set up b...
return b;
}
and then inside playGame:
Board b = getBoard();
There's another error just below:
for(int a=0;a<(sizeof(b.Holes)-1);a++)
The sizeof operator gives the size in bytes. You actually want the size in elements, so you need to divide by the element size:
a < (sizeof b.Holes / sizeof b.Holes[0])
I'm not sure what the -1 was meant to be doing either, this would just cause you to not output the last hole.
Apparently push_back() is not working for my custom data class T. On compilation I get the following error:
error: no matching function for call to ‘Vector::push_back(int&)’
Could someone explain to me why that is? Thank you.
#include <std_lib_facilities>
#include <numeric>
#include <vector>
#include <string>
// vector<int> userin;
// int total;
// bool success;
class T
{
public:
void computeSum(vector<T> userin, int sumamount, T& total, bool& success);
void getData(vector<T> userin);
};
template <class T>
void computeSum(vector<T> userin, int sumamount, T& total, bool& success)
{
if (sumamount < userin.size()){
success = true;
int i = 0;
while (i<sumamount){
total = total + userin[i];
++i;
}
} else {
success = false;
cerr << "You can not request to sum up more numbers than there are.\n";
}
}
template <class>
void getData(vector<T> userin)
{
cout << "Please insert the data:\n";
int n;
do{
cin >> n;
userin.push_back(n);
} while (n);
cout << "This vector has " << userin.size() << " numbers.\n";
}
int helper()
{
cout << "Do you want help? ";
string help;
cin >> help;
if (help == "n" || help == "no"){
return 0;
}else{
cout << "Enter your data. Negative numbers will be added as 0. Ctrl-D to finish inputing values.\n";
}
}
int main()
{
helper();
getData(userin);
cout << "How many numbers would you like to sum?";
int sumamount;
cin >> sumamount;
computeSum(userin, sumamount);
if (success = true) {
cout << "The sum is " << total << endl;
} else {
cerr << "Oops, an error has occured.\n";
}
cout << endl;
return 0;
}
Outside some flagrantly offensive issues (e.g. it should be template <class T>, not template<class>), the real problem is that vector expects you to push back objects of type T. It looks like you are reading in with type int and pushing. Try:
template <class>
void getData(vector<T> userin)
{
cout << "Please insert the data:\n";
T n;
do{
cin >> n;
userin.push_back(n);
} while (n);
cout << "This vector has " << userin.size() << " numbers.\n";
}
The problem is this line:
userin.push_back(n);
where n is an int. push_back is expecting something of type T.
I'm also not sure what the point of class T is in this case.