I am using for loops combined with if statements to read integers from a text file into a two-dimensional array.
This is my code:
for (int i = 0; i < MAX_ROWS;i++) {
for (int j = 0; j < MAX_COLUMNS; j++) {
inFile >> ArrB[i][j];
if (ArrB[i][j] == -1) {
bad = true;
cout << "The array does not have enough integers" << endl;
break;
}
else {
if (ArrB[i][j] < 1) {
invalidnum = true;
}
}
if (invalidnum = true) {
cout << *(*(ArrB + i) + j) << " ";
cout << "There is/are negative number(s) or zero(s) in the array imported from your text file." << endl;
}
}
}
This code will read in the first 6 integers (max_row * max_column) from a text file into ArrB.
If -1 exists in the first 6 integers, it will exit the loop and print out "The array does not have enough integers".
If there is no -1 in the first 6 integers, then it will check all 6 integers to see if there are any other negative numbers or zero.
If there are negative numbers or zero, I want it to still print out the array, then print out the error message (There is/are negative number(s) or zero(s) in the array imported from your text file) ONLY ONCE.
For example, this is my text file. As you can see, there is no -1 in the first 6 numbers, but there is a -7.
So, ideally, the result should be something like:
2 4 5 6 9 -7
There is/are negative number(s) or zero(s) in the array imported from your text file
But this is what I am getting if I run my code above:
-------------------------------------UPDATE--------------------------------------
Figured it out based on #ZedLepplin 's comment
Here is the code:
for (int i = 0; i < MAX_ROWS;i++) {
for (int j = 0; j < MAX_COLUMNS; j++) {
inFile >> ArrB[i][j];
if (ArrB[i][j] == -1) {
bad = true;
cout << "The array does not have enough integers" << endl;
break;
}
else {
if (ArrB[i][j] < 1) {
invalidnum = true;
}
}
cout << *(*(ArrB + i) + j) << " ";
}
}
if (invalidnum == true) {
cout << "There is/are negative number(s) or zero(s) in the array imported from your text file." << endl;
}
You could just set a counter, and put the message outside of the loop.
Something like :
int counter = 0;
for(int i = 0; i < MAX_ROWS ; i++) {
if(myVector[i] == -1) {
counter++;
}
else {
// Do normal stuff
}
}
if(counter > 0) {
cout << "The array contained " << counter << "negative values" << endl;
}
Ho, and I'd advise to avoid comparisons to "true". If myVar is a boolean alrady, I can just do if(myVar). No need to do if(myVar == true).
And doing if(myVar = true) is worse, as it sets myVar to true, regardless of its initial value. That's a common typo that can be hard to detect when proofreading code.
Edited version (to adapt to comments) :
bool earlyNegativeOneFound = false;
int otherNegativeCounter;
for(int i = 0; i < MAX_ROWS ; i++) {
if(i < 6 && myVector[i] == -1) {
earlyNegativeOneFound = true;
break;
}
else if(myVector[i] < 0) {
cout << myVector[i] << endl;
otherNegativeCounter++;
}
else {
// Do normal stuff
}
}
if(!earlyNegativeOneFound && otherNegativeCounter> 0) {
cout << "The array contained " << otherNegativeCounter << "negative values" << endl;
}
Put the conditional error message print after your for loop. Leave the cout for displaying the array number inside the for loop so it is output for every iteration of the loop.
for (int i = 0; i<MAX_ROWS;i++) {
for (int j = 0; j<MAX_COLUMNS; j++) {
inFile >> ArrB[i][j];
if (ArrB[i][j] == -1) {
bad = true;
cout << "The array does not have enough integers" << endl;
break;
}
else {
if (ArrB[i][j] < 1) {
invalidnum = true;
}
}
cout << * (*(ArrB + i) + j) << " ";
}
}
if (invalidnum = true) {
cout << "There is/are negative number(s) or zero(s) in the array imported from your text file." << endl;
}
I am not sure if this is what you meant
for (int i = 0; i < MAX_ROWS;i++) {
for (int j = 0; j < MAX_COLUMNS; j++) {
flag log = false;
inFile >> ArrB[i][j];
if (ArrB[i][j] == -1) {
bad = true;
cout << "The array does not have enough integers" << endl;
break;
}
else {
if (ArrB[i][j] < 1) {
invalidnum = true;
}
}
if (invalidnum = true) {
cout << *(*(ArrB + i) + j) << " ";
if(!flag)
{
cout << "There is/are negative number(s) or zero(s) in the array
imported from your text file." << endl;
flag = true;
}
}
}
}
Adding the flag boolean variable would allow the statement "there are negative numbers.." to be printed once.
Just store the message and print it where and when you want. Some psuedo-code:
std::string message;
for (int i = 0; i < N; ++i)
{
for (int j = 0; j< M; ++j)
{
if (smth)
{
message {"Your message"};
break; // note that after break,
// you are still in the outer loop
}
else if (smth else)
{
message {"Your message"};
}
}
// print it here
}
// or here, or wherever you want to
Related
I have a function that receives a character "x" from a user. If the "x" exists in a hard-coded array, "x" is pushed into another array filled with lowdashes in the same position as in the first array. Fo example:
firstArray = ["h", "e", "l", "l","o"]
//user provided character that exist in first array. "e"
lowDashesArray= ["_", "e", "l", "l", "o"]
Then, I want to check if both arrays are equal, my problem is that when the user guesses the firts element in the array (in the above example "h"), the for loop stops iteraring without checking if the other elements are equal. As a result, the block of code that expects both arrays to be equal is executed.
The function looks like so:
bool checkIfLetterExistOnWord(string word, char letter, char* lettersArray, char* lowDashesArray, bool hasWon, bool hasLost, int lives){
bool isCorrectLetter = false;
for(int i = 0; i<word.length(); i++ ){
if(letter == lettersArray[i]){
int position = i;
lowDashesArray[position] = letter;
cout << lowDashesArray;
cout << endl;
isCorrectLetter = true;
}
}
if(isCorrectLetter){
for(int j = 0; j < word.length(); j++){
if(lettersArray[j] == lowDashesArray[j]){
hasWon = true;
//here is the problem. But only when user guesses the first element of the array
}
else{
break;
}
}
if(hasWon){
cout << "You have won";
cout << endl;
cout << hasWon;
cout << endl;
cout << lowDashesArray;
cout << endl;
cout << word;
cout << endl;
return hasWon;
}
else{
cout << "good job. Guess the next letter";
cout << endl;
return hasWon;
}
}
else{
cout << "wrong";
cout << endl;
lives--;
if(lives == 0){
hasLost = true;
cout << "You lost";
return hasLost;
}
else {
cout << "You still have this lives :";
cout << endl;
cout << lives;
cout << endl;
return hasLost;
}
}
}
Both your loop logic is incorrect.
bool isCorrectLetter = false;
for(int i = 0; i<word.length(); i++ ){
if(letter == lettersArray[i]){
int position = i;
lowDashesArray[position] = letter;
cout << lowDashesArray;
cout << endl;
isCorrectLetter = true;
}
}
Here you print the array once for every occurance of the guess character. FUrthermore you do not check, if the letter "was already uncovered". You need to do the printing after the loop and depending on whether you want guessing uncovered chars to be an error, you may need to ajust the check.
for(int j = 0; j < word.length(); j++){
if(lettersArray[j] == lowDashesArray[j]){
hasWon = true;
//here is the problem. But only when user guesses the first element of the array
}
else{
break;
}
}
You're trying to check here, if every char meets a certain criterion (being a non placeholder char). In this case you cannot break early. In general the loop for this kind of check needs to look like this:
bool checkSuccess = true;
for (size_t i = 0; checkSuccess && i != length; ++i)
{
if (!Check(elements[i]))
{
checkSuccess = false;
}
}
Or in your case (using break instead):
hasWon = true;
for(int j = 0; j < word.length(); j++)
{
if(lettersArray[j] != lowDashesArray[j])
{
hasWon = false;
break;
}
}
Imho it's preferrable to separate the replacement logic from io logic. You could e.g. rewrite the logic similar to this:
constexpr char MaskChar = '_';
/**
* Replaces placeholders in \p maskedText, if they the corresponding char in \p clearText
* matches \p guess.
*
* \param[in,out] maskedText the text with some chars replaced with '_'
*
* \return true, if at least one char was replaced, false otherwise
*/
bool GuessChar(std::string const& clearText, std::string& maskedText, char const guess)
{
assert(clearText.length() == maskedText.length());
bool guessCorrect = false;
for (size_t i = 0; i != clearText.length(); ++i)
{
if (maskedText[i] == MaskChar && clearText[i] == guess)
{
guessCorrect = true;
maskedText[i] = guess;
}
}
return guessCorrect;
}
int main()
{
std::string const clearText = "hello";
std::string maskedText(clearText.length(), MaskChar);
size_t lives = 3;
while (lives > 0 && maskedText.find(MaskChar) != std::string::npos)
{
std::cout << "Word: " << maskedText
<< "\nMake your guess!\n";
char c;
std::cin >> c;
if (GuessChar(clearText, maskedText, c))
{
std::cout << "Guess correct!\n";
}
else
{
--lives;
std::cout << "Guess incorrect\n"
<< lives << " lives left\n";
}
}
if (lives > 0)
{
std::cout << "You win!\n";
}
else
{
std::cout << "You loose!\n";
}
}
I am trying to compare two arrays.where if it is true it needs to print the string.since it need to print only one time but the string is printing three times .where i have stored three values in both arrays.can you guys spot and tell me what is wrong.
for (int i = 0; i < n; i++)
{
if (l[i] == g[i])
{
cout << "equal" << endl;
}
else if (l[i] < g[i])
{
cout << "lesser" << endl;
}
else if (l[i] > g[i])
{
cout << "greater" << endl;
}
}
I'm guessing that you're trying to do a lexicographic comparison.
It should be obvious that if you want to print the message only once then you shouldn't put the print statements inside the loop.
The following code works how I think you want your code to work. The result of the comparison is stored in a variable result and that variable is examined only after the loop has finished. I use break because once you have found an item that is not equal there is no need to carry on the comparison.
int result = 0;
for (int i = 0; i < n; i++)
{
if (l[i] < g[i])
{
result = -1;
break;
}
else if (l[i] > g[i])
{
result = +1;
break;
}
}
if (result == 0)
cout << "equal" << endl;
else if (result < 0)
cout << "lesser" << endl;
else
cout << "greater" << endl;
You could simplify:
for (int i = 0; i < n; ++i)
{
const int l_value = l[i];
const int g_value = g[i];
if (l_value == g_value)
{
cout << "slot[" << i << "] is equal\n";
}
else
{
if (l_value < g_value)
{
cout << "slot[" << i << "] is less than\n";
}
else
{
cout << "slot[" << i << "] is greater than\n";
}
}
}
In order compare the entire array, you'll need to sort it first. The "less than" and "greater than" apply to a sorted array.
Okay so I keep getting this error when I try to run my code and can't figure out how to fix it.
(Unhandled exception at 0x75195608 in hw6.exe: Microsoft C++ exception: std::out_of_range at memory location 0x0101F850.)\
I have included my source code below. Also the file that I am reading from is not long at all so I don’t think that’s the problem.
int main() {
//Initializes all of the variables, strings,boolean, and vectors
ifstream inFS;
int count = 1;
int i = 0;
int j = 0;
int location = 0;
char ch;
bool marker = 0;
string filename = "hw6-Fall2017.txt";
string list = "ABCDEFGHIJKEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
vector<int> locations;
vector<int> find_Locations;
vector<char> notFound;
vector<char> Found;
//Iterates through the file searching for each of the characters
while (count <= 62) {
inFS.open(filename);
if (!inFS.is_open()) {
cout << "Could not open the file: " << filename << endl;
return 1;
}
while (inFS.get(ch) && marker == 0) {
location++;
if (ch == list[i]) {
marker = 1;
}
}
inFS.close();
//Sets characters not found to have a location of 0
if (marker == 0) {
location = 0;
}
locations.push_back(location);
marker = 0;
location = 0;
i++;
count++;
}
//Creates a table printing out the characters and their susequent locations
for (i = 0;i < list.size();i++) {
if (locations.at(i) == 0) {
cout << list[i] << " " << setw(6) << "NotFnd"<< " ";
notFound.push_back(list[i]);
}
else {
cout << list[i] << " " << setw(6) << locations.at(i) << " ";
find_Locations.push_back(locations.at(i));
}
j++;
if (j == 5) {
cout << endl;
j = 0;
}
}
cout << endl << endl << endl;
//Sorts the characters in the order that they were found
sort(find_Locations.begin(), find_Locations.end());
for (i = 0;i < find_Locations.size();i++) {
for (j = 0;j < locations.size();j++) {
if (find_Locations.at(i) == locations.at(j) && marker == 0) {
Found.push_back(list[j]);
j = locations.size();
}
}
}
count = 0;
j = 0;
//Creates a table printing out the characters in the oreder they were found
//in the text file along with their locations. Characters not found are
//displayed first with a location of "NotFnd".
for (i = 0;i < (Found.size() + notFound.size());i++) {
if (i < Found.size()) {
cout << Found.at(i) << " " << setw(6) << find_Locations.at(i)<< " ";
}
else {
cout << notFound.at(j) << " " << setw(6) << "NotFnd" << " ";
j++;
}
count++;
if (count == 5) {
cout << endl;
count = 0;
}
}
system("pause");
return 0;
}
The answer is not easy to find with code review.
But this line looks nice in itself
string list = "ABCDEFGHIJKEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
but together with this
while (count <= 62) {
It looks suspicious, I think it should have been
while (count < list.size()) { // 2*26+10==62
An "Off by one error" which could cause a problem here
for (i = 0;i < find_Locations.size();i++) {
for (j = 0;j < locations.size();j++) {
if (find_Locations.at(i) == locations.at(j) && marker == 0) {
Found.push_back(list[j]); // <--- if J>=list.size()
j = locations.size();
}
}
}
And a potential crash at the marked line.
But the real error is here
Found.push_back(list[j]); // j should have been i
Which should cause a crash at
cout << Found.at(i) << " " << setw(6) << find_Locations.at(i)<< " ";
List.cpp (class definitions)
I have been working on code that is suppose to help familiarize with classes. My code currently has a function that displays a menu of options for the users. Option [1] is suppose to add a string, option [2] is suppose to remove a string from the list, option [3] prints the string list, option [4] exits. My option [1] seems to work okay as the user is able to input one string at a time but I am having a hard time with the removal of a string. The strings are currently stored in an array of 10 elements. I believe the function I wrote for the string removal is okay as I have debugged it and it seems successful, however, I am not seeing results on my console window.
My array is located in a private class in my class: string items[MAX_ITEMS]; along with another variable called: int totalItems;
The class is then called in my main function using a switch case:
//This code snippet below is located in a separate cpp file with main
cout << "Please enter the text you want to remove: " << endl;
cin >> userInput;
list1.remove(userInput);
////////////////////////////////////////////////////////////////////
//preprocessor directives
#include <iostream>
#include <string>
//header files
#include "list.h"
using namespace std;
List::List()
{
//clear array prior to starting (set everything to NULL)
for (int i = 0; i < MAX_ITEMS; i++)
{
items[i] = " ";
}
totalItems = 0;
}
//void List::init()
//{
// string items[MAX_ITEMS];
// totalItems = 0;
//}
bool List::insert(const string& data)
{
//verifies that string is not empty, not in the list, and not full
if (data.empty() == true || inList(data) == true || isFull() == true)
{
return false;
}
else
{
// items[isFull)] = data;
// totalItems++;
items[totalItems++] = data;
return true;
}
}
bool List::isEmpty() const
{
//runs through loop to verify array is empty
for (int i = 0; i < MAX_ITEMS; i++)
{
if (items[i].empty() != true)
{
return false;
}
}
return true;
}
//identifies whether the string is full or not
bool List::isFull() const
{
if (totalItems == MAX_ITEMS)
{
return true;
}
else
{
return false;
}
}
//identifies whether the string is already in the list or not
bool List::inList(const string& theList)
{
for (int i = 0; i < MAX_ITEMS; i++)
{
if (items[i] == theList)
{
return true;
}
}
return false;
}
bool List::remove(const string& data)
{
if (inList(data) == true || data.empty() == true)
{
return false;
}
for (int i = 0; i < MAX_ITEMS; i++)
{
if (items[i] == data)
{
items[i] == " ";
for (int j = i; j < MAX_ITEMS; j++)
{
items[j] = items[j + 1];
items[MAX_ITEMS - 1] == " ";
break;
}
}
}
totalItems--;
return true;
}
//prints list
void List::printList()
{
for (int i = 0; i < MAX_ITEMS; i++)
{
cout << i << items[i] << '\t';
}
}
list_test.cpp (main.cpp)
#include <iostream>
#include <string>
//header files
#include "list.h"
using namespace std;
//function prototypes
int showSelection();
int main()
{
List list1;
string userInput = "";
int userChoice;
// list1.init();
userChoice = showSelection();
while (userChoice != 4)
{
switch(userChoice)
{
case 1:
cout << "Please enter the text you want to add: " << endl;
cin >> userInput;
list1.insert(userInput);
/*if (list1.inList(userInput) == false)
{
cout << "Text is already entered in the list!" << endl;
}*/
if (list1.isFull() == true)
{
cout << "You have entered the MAXIMUM amount of elements!" << endl;
}
break;
case 2:
cout << "Please enter the text you want to remove: " << endl;
cin >> userInput;
list1.remove(userInput);
break;
case 3:
cout << "Printed list: " << endl;
list1.printList();
break;
}
userChoice = showSelection();
}
cout << "Goodbye. Please press enter to exit." << endl;
//TESTING PURPOSES FOR FUNCTIONS
cout << list1.insert(userInput) << endl;
cout << list1.isEmpty() << endl;
cout << list1.isFull() << endl;
cout << list1.inList(userInput) << endl;
return 0;
}
/* ===========================================
Name: showSelection
Desc: displays menu for user to choose options
for their inputted string(s).
Args: none
Retn: none
=========================================== */
int showSelection()
{
int userChoice;
bool exit = false;
while (exit == false)
{
cout << "\nTo select an option, please enter the corresponding number: " << endl;
cout << "[1] to add a string" << endl;
cout << "[2] to remove a string" << endl;
cout << "[3] to print a string" << endl;
cout << "[4] to exit" << endl << endl;
cin >> userChoice;
cout << "You entered option: " << userChoice << endl;
cout << '\n';
if (userChoice == 1 || userChoice == 2 || userChoice == 3 || userChoice == 4)
{
exit = true;
}
else
{
cout << "Invalid selection" << endl;
}
}`enter code here`
return userChoice;
}
Here is how you code should probably look:
bool List::remove(const string& data) {
// only check if the list is empty so you don't nececarily go through it
// you shoudn't ask here if the given string is in the list
// because you will search for it anyway just below
if (data.empty())
return false;
for (int i = 0; i < MAX_ITEMS; ++i) {
if (items[i] == data) { // now if it was found
items[i] = " "; // set it to your empty value
--totalItems; // prefix -- is faster then postfix one (no copy is created)
for (int j = i; j < MAX_ITEMS - 1; ++j) {
// stop at j < MAX_ITEMS - 1 because you wouldn't want
// to swap last element with the next because there
// is none behind it
if (items[j + 1] == " ")
// if the next item is already empty you don't need to shift any more
return true;
// swap the next item with much more
// efficient std::swap function
std::swap(items[j], items[j + 1]);
}
return true; // value is removed and items shifted so you can now return
}
}
// if function gets to this point that means the value wasn't found
return false;
}
If you would like to make your code more efficient, I can give you more suggestions on how to do it. This above should answer your question.
Also using an array for a struct like this isn't optimal at all. Using linked listed would mean no shifting would be required.
Edit: replaced long text with a code example
Edit2: added return statement if shifting is no longer necessary
FOR me it's unclear what you want to do as unavailability of full code to run.
But I think this should work as of what I think yo want to do
bool List::remove(const string& data){
for (int i = 0; i < totalItems; i++)
{
if (items[i] == data)
{
for (int j = i; j < totalItems-1; j++)
{
items[j] = items[j+1];
}
totalItems--;
return true;
}
}
return false;
if (inList(data) == true || data.empty() == true)
{
return false;
}
If the data parameter is in your list object, you return without removing anything? this should be !inList(data)
Additionally, when you make it into the loop below this code this loop:
for (int j = i; j < MAX_ITEMS; j++)
{
items[j] = items[j + 1];
items[MAX_ITEMS - 1] == " ";
break;
}
will only execute for j=i, the "break" statement will stop execution of this inner loop, and go back to the outer loop.
EDIT: this is how I personally would go about this problem.
bool List::remove(const string& data)
{
bool retVal;
if (!inList(data) || data.empty())
{
retVal = false;
}
else{
for (int i = 0; i < MAX_ITEMS; i++)
{
if (items[i] == data)
{
items[i] = " ";
for (int j = i; j < (MAX_ITEMS - 1); j++)
{
items[j] = items[j + 1];
}
items[MAX_ITEMS-1] = " ";
}
}
totalItems--;
retVal = true;
}
return retVal;
}
I am having a bug that I cannot find a fix for through google searching. I am attempting to make a text based version of the game Mastermind. I am using a string the is set from an array of chars as the criteria for a while loop. When the string is equal to "****" the game is supposed to tell the player that they won and exit, but for some reason a ^A is being added on to the end of the string that is being checked, even though it is not in the char array.
Here is the function that sets the char array and returns a string from that array:
string check(int guess[4], int num[4]) {
char hints[4];
cout << " ";
for (int i = 0; i < 4; i++) {
if (guess[i] == num[i]) {
hints[i] = '*';
cout << "*";
}
else {
for (int x = 0; x < 4; x++) {
if (guess[i] == num[x]) {
cout << "+";
}
}
}
if (guess[i] != num[i]) {
hints[i] = ' ';
}
}
string hint(hints);
cout << endl;
cout << hint << endl;
return hint;
}
And here is the function checking the value of the string:
while (hints.compare("****") != 0) {
if (guessCount == 5) {
break;
}
cout << "Guess?: ";
cin >> guess;
intToArray(guess, guessArr);
hints = check(guessArr, nums);
cout << hints << endl;
guessCount++;
}
if (hints.compare("****") == 0) {
cout << "You win! The number was: ";
for (int i = 0; i < 4; i++) {
cout << nums[i];
}
}
You haven't null-terminated the hints array, so you are getting extra garbage that is lying around on the stack in your string.
You could let the hint string know how long it is when you are constructing it.
string hint(hints, 4);
cout << endl;
cout << hint << endl;