C++:array functions - c++

How can I write a program that reads in, a collection of characters from the key board and outputs them to the console. Data is input at random, but output selectively. Only unique characters are displayed at the console. Therefore, every character should be displayed once, no matter how many times it appears in the array.
For example, if an array
Char letterArray[ ] = {B,C,C,X,Y,U,U,U};
The output should be:
B,C,X,Y,U
This is what I have done so far...
char myArray [500];
int count = 0;
int entered = 0;
char num;
while (entered < 8)
{
cout << "\nEnter a Character:";
cin >> num;
bool duplicate = false;
entered++;
for (int i = 0; i < 8; i++)
{
if (myArray[i] == num)
duplicate=true;
}
if (!duplicate)
{
myArray[count] = num;
count++;
} // end if
else
cout << num << " character has already been entered\n\n";
// prints the list of values
cout<<"The final Array Contains:\n";
for (int i = 0; i < count; i++)
{
cout << myArray[i] << " ";
}
}

I believe you could make use of std::set<>.
"Sets are a kind of associative container that stores unique elements <...> elements in a set are always sorted from lower to higher following a specific strict weak ordering criterion set"

Looking through your code...
char myArray [500];
Why 500? You never use more than 8.
char num;
Confusing naming. Most programmers would expect a variable named num to be a numeric type (e.g. int or float).
while (entered < 8)
Consider replacing 8 with a constant (e.g. const int kMaxEntered = 8;).
cin >> num;
cin might be line-buffered; i.e. it does nothing until a whole line is entered.
for (int i = 0; i < 8; i++)
{
if (myArray[i] == num)
duplicate=true;
}
You're accessing uninitialized elements of myArray. Hint: your loop size should not be 8.
Consider using continue; if you find a duplicate.
if (!duplicate)
{
myArray[count] = num;
count++;
} // end if
else
cout << num << " character has already been entered\n\n";
Your // end if comment is incorrect. The if isn't ended until the else is done.
You may want to add braces around the else clause, or remove the braces from the if clause by combining its two lines into the one-line myArray[count++] = num;.
// prints the list of values
cout<<"The final Array Contains:\n";
for (int i = 0; i < count; i++)
{
cout << myArray[i] << " ";
}
You're printing the list every time you get a single input?
Don't use \n in text to cout unless you specifically want to micromanage buffering. Instead, use endl. Also, always put spaces around binary operators like << and don't randomly capitalize words:
cout << "The final array contains:" << endl;
for (int i = 0; i < count; i++)
cout << myArray[i] << " ";
cout << endl;

It would be much more efficient to create an array of size 128 (assuming you are dealing with ASCII) that is initialized with false. Every time you get a character, check its ASCII value and if the array is true on that value you don't print it. After that, update the value of the array on the character value to true. Something like:
bool *seenArray = new bool[128]();
void onkey(char input) {
if(((int)input) < 0) return;
if (!seenArray[(int)input]) {
myArray[count] = input;
count++;
seenArray[(int)input] = true;
}
}

Related

How do i make my array compare and then display certain outputs based on users guess

Newer to coding and im stuck, Need to make a array thats stores 5 numbers (1-9), then i need to check that array for duplicates if there is duplicates i need to replace that number either with a whole new random line no duplicates (seems like the easier option) or just replace that one number,
after that wants me to get users 5 numbers guess store that in a array, display that array at the bottom along with these under each of the numbers
// The * = means the number is in the exact location
// The - = means the array does not contain that number
// The + = means the array contains the number but its not in the right location
All the arrays want the digits to be entered one at a time
repeat steps till user gets all the numbers to * then end game with completion msg.
My true problem lies with step 4 and step 7;
Below is the code ive been working on today but any help would be truly appreciated
#include <iostream>
#include <ctime>
#include <cstdlib>
using namespace std;
void game_instructions(int n);
bool search_array(int a[], int n, int t);
int main()
{
//Step 1: Declare your variables and constants
const int SIZE = 5; //this constant stores the length/size of the code
int randcode[SIZE]; //this array stores the code generated randomly by the computer
int guess[SIZE]; //this array stores the code inputted by the player/user
//you may add more variables as needed
//Step 2: Output game instructions by calling function game_instructions
game_instructions(SIZE);
//Step 3: Generate a random code and store it in the array randcode one digit at a time.
//Each digit should be between 0 and 9 and should be stored as one array element
//Recall that rand() % 10 can be used to generate a number between 0 and 9
srand(time(0));
for(int i=0;i<SIZE;i++)
randcode[i]= (rand() % 10); //Computers random 5 numbers generated
cout<<"\nRandom C-numbers::"<<endl;
for(int i=0;i<SIZE;i++)
cout<<randcode[i] << " ";
//Step 4: Repeat step 3 if the array randcode contains duplicates
//You must use function contains_duplicates to implement this step
//Step 5: Ask the user for his guess and store it in the array guess.
//Read one digit at a time, validate it to make sure it is between 0 and 9, and store it as one array element
for (int i=0; i<SIZE; i++) {
cout<<"\nEnter Digit "<< i+1 << ": ";
cin >> guess[i];}
cout << endl;
//Step 6: Output the array guess on a single line with a space after each element (see the sample output provided)
for (int n=0; n < SIZE; ++n) {
cout << guess[n] << " ";
}
//Step 7: Compare the randomly generated code (randcode) with the user's guess (guess)
//and display feedback for each digit as: *, + or –, as explained below:
//For each digit in the user's guess do the following:
// If it matches the digit from the random code (both value and position), output *
// Otherwise, if it appears anywhere in the random code, output + (use function search_array here)
// Otherwise, output -
//Step 8: Repeat steps 5,6,7 until all digits have been guessed correctly
//Step 9: Output congratulations message
cout << endl << endl;
cout << "Good job! You guessed the code!";
return 0;
}
void game_instructions(int n)
//This function outputs the game instructions.
//Its parameter n represents the length of the code.
{
cout << "A random " << n << " digit code has been generated. You have to guess it. \n";
cout << "For every digit you will receive feedback in the form of *, + or - \n";
cout << " * means the digit is in the code and it is in the correct position.\n";
cout << " + means the digit is in the code but it is not in the correct position.\n";
cout << " - means the digit is not in the code.\n";
}
bool search_array(int a[], int n, int t)
//This function searches the array a (of size n) for a target value t.
//If t is found in the array the function returns true; otherwise it returns false.
{
for (int i = 0; i < n; i++)
{
if (a[i] == t) return true;
}
return false;
}
bool contains_duplicates(int a[], int n)
//This function searches the array a (of size n) and returns true if the array contains duplicates; otherwise, it returns false.
{
for (int i = 0; i < n; i++)
{
//compare element a[i] with all the remaining elements from index i+1 to n
for (int j = i+1; j < n; j++)
{
if (a[i] == a[j]) return true;
}
}
return false;
}
I got most the side code done but im just stumped on how to get this array to match any help would be nice
Here is how I would implement the program to generate the number without duplicate:
Step3 would look like this:
int tempNumber;
int i = 0;
while (i < SIZE) {
tempNumber = (rand() % 10);
if (contains_duplicates(randcode, tempNumber, i) == false) {
// every time there is no duplicate we push and add i by 1;
randcode[i] = tempNumber; // Computers random 5 numbers generated
i++;
}
}
contains_duplicates function would look like this:
bool contains_duplicates(int arr[], int tempNum, int currentArrSize)
// This function searches the array a (of size n) and returns true if the
//array
// contains duplicates; otherwise, it returns false.
{
for (int j = 0; j <= currentArrSize; j++) {
// if the array[index] not equal generated number the loop will
//iterate again without going to the line below
if (arr[j] != tempNum) {
continue;
}
// if the array[index] equal the function will return true and end
//the function
// uncomment this to check how many time it duplicate (not
//necessary tho)
//cout << "if return true, this will appear"<< endl;
return true;
}
// if the loop is done and no duplicate, function will return false
return false;
}
With this method it is not necessary to do step 4 because we already prevent duplicate array!
Here is the last problem from your question which is step 7:
cout << endl;
for (int i = 0; i < SIZE; i++) {
if (guess[i] == randcode[i]) {
cout << "* ";
} else if (search_array(randcode, SIZE, guess[i])) {
cout << "+ ";
} else {
cout << "- ";
}
}
Seems like the problem has been solved, now try to implement step 8 by yourself, good luck :)

A program to find out if a word is palindrome

Written some algorithm to find out if a given word is a palindrome. But one of my variables (counter) seems not updating when I debugged and I can't figure out what is wrong with it. I may be wrong though... any help will be needed as I don's wanna copy some code online blindly.
Below is the code:
#include <iostream>
#include <cstring>
using namespace std;
int main(){
//take input
string input;
cout << "Enter your word: ";
cin >> input;
//initialize arrays and variables
int counter = 0, k = 0;
int char_length = input.length();
char characters[char_length];
strcpy(characters, input.c_str());//copy the string into char array
//index of character at the midpoint of the character array
int middle = (char_length-1)/2;
int booleans[middle]; //to keep 1's and 0's
//check the characters
int m = 0, n = char_length-1;
while(m < middle && n > middle){
if(characters[m] == characters[n]){
booleans[k] = 1;
} else {
booleans[k] = 0;
}
k++;
m++;
n--;
}
//count number of 1's (true for being equal) in the booleans array
for(int i = 0; i < sizeof(booleans)/sizeof(booleans[0])-1; i++){
counter += booleans[i];
}
//compare 1's with size of array
if(counter == middle){
cout << input << " is a Palindrome!" << endl;
} else {
cout << input << " is not a Palindrome!" << endl;
}
return 0;
}
Brother it seems difficult to understand what your question is and what code you are typing. I am not very much experienced but according to me palindrome is a very very simple and easy program and i would have wrote it as:
#include <iostream>
#include <string.h>
using namespace std;
int main()
{
char str1[20], str2[20];
int i, j, len = 0, flag = 0;
cout << "Enter the string : ";
gets(str1);
len = strlen(str1) - 1;
for (i = len, j = 0; i >= 0 ; i--, j++)
str2[j] = str1[i];
if (strcmp(str1, str2))
flag = 1;
if (flag == 1)
cout << str1 << " is not a palindrome";
else
cout << str1 << " is a palindrome";
return 0;
}
It will work in every case you can try.
If you get a mismatch i.e. (characters[m] == characters[n]) is false then you do not have a palindrome. You can break the loop at that point, returning false as your result. You do not do that, instead you carry on testing when the result is already known. I would do something like:
// Check the characters.
int lo = 0;
int hi = char_length - 1;
int result = true; // Prefer "true" to 1 for better readability.
while (lo < hi) { // Loop terminates when lo and hi meet or cross.
if(characters[lo] != characters[hi]) {
// Mismatched characters so not a palindrome.
result = false;
break;
}
lo++;
hi--;
}
I have made a few stylistic improvements as well as cleaning up the logic. You were doing too much work to solve the problem.
As an aside, you do not need to check when the two pointers lo and hi are equal, because then they are both pointing to the middle character of a word with an odd number of letters. Since that character must be equal to itself there is not need to test. Hence the < in the loop condition rather than <=.
Existing Code does not work for Palindromes of Odd Length because of
for(int i = 0; i < sizeof(booleans)/sizeof(booleans[0])-1; i++)
Either use i<=sizeof(booleans)/sizeof(booleans[0])-1; or i<sizeof(booleans)/sizeof(booleans[0]);.
Currently, you are not counting the comparison of character[middle-1] and character[middle+1].
For palindromes of even length, you will have to change your logic a bit because even length palindromes don't have a defined middle point.
#include <iostream>
#include <cstring>
using namespace std;
int main(){
//take input
string input;
cout << "Enter your word: ";
cin >> input;
//initialize arrays and variables
int counter = 0, k = 0;
int char_length = input.length();
char characters[char_length];
strcpy(characters, input.c_str());//copy the string into char array
//index of character at the midpoint of the character array
int middle = (char_length+1)/2;
int booleans[middle]; //to keep 1's and 0's
//check the characters
int m = 0, n = char_length-1;
while(m<=n){
if(characters[m] == characters[n]){
booleans[k] = 1;
} else {
booleans[k] = 0;
}
k++;
m++;
n--;
}
//count number of 1's (true for being equal) in the booleans array
for(int i = 0; i < sizeof(booleans)/sizeof(booleans[0]); i++){
counter += booleans[i];
}
cout<<counter<<" "<<middle<<endl;
//compare 1's with size of array
if(counter == middle){
cout << input << " is a Palindrome!" << endl;
} else {
cout << input << " is not a Palindrome!" << endl;
}
return 0;
}
Over here the size of the boolean array is (length+1)/2,
For string s like abcba it will be of length 3.
This corresponds to a comparison between a a, b b and c c. Since the middle element is the same, the condition is always true for that case.
Moreover, the concept of middle is removed and the pointers are asked to move until they cross each other.

Visual Studio shows warning C6330: 'char' passed as _Param_(1) when 'unsigned char' is required in call to 'isdigit'. when I try to build

This is only a small part from my code. What I'm trying to do is writing at the end of the file (add record) which in this case is "books.txt" that already has 40 records. But when I debug, it would still prompt the user to enter isbn code but after entering, (process 3296) exited with code 3. came out. Which part am I doing wrong? The counter() function is to count how many records I already have in my file. And I'm also using array of struct to store my records.
int add_record(DATA book[])
{
int count = counter();
system("CLS");
cout << "\t\t\t\t\t\t\t\t : :Add Book Record: :\n\n";
bool cont;
ofstream outfile("books.txt", ios::app);
if (outfile.is_open() && !outfile.eof())
{
do
{
cont = true;
cout << "ISBN Code: ";
cin.getline(book[++count].isbn_code, 14, '\n');
//cin.ignore(numeric_limits<streamsize>::max(), '\n');
int length = strlen(book[++count].isbn_code);
for (int i = 0; i <= length; i++)
{
if (!isdigit(book[++count].isbn_code[i]))
{
cont = false;
cout << "Your input is invalid. Enter again.\n";
break;
}
}
} while (cont == false);
do
{
cont = true;
cout << "Author: ";
cin.getline(book[++count].author, 50, '\n');
int length = strlen(book[++count].author);
for (int i = 0; i <= length; i++)
{
if (isdigit(book[++count].author[i]))
{
cont = false;
cout << "Your input is invalid. Enter again.\n";
break;
}
}
} while (cont == false);
outfile << book[++count].isbn_code << "," << book[++count].author ;
outfile.close();
}
else
cout << "File is not open\n";
return 0;
}
Yes, the error message is completely correct. This is a rare case where using a cast is the correct thing to do
if (isdigit(static_cast<unsigned char>(book[++count].author[i])))
Reference, https://en.cppreference.com/w/cpp/string/byte/isdigit
But this has nothing to do with your crash which is caused by other errors. For instance
cin.getline(book[++count].isbn_code, 14, '\n');
//cin.ignore(numeric_limits<streamsize>::max(), '\n');
int length = strlen(book[++count].isbn_code);
You definitely don't want to increment count twice. I would guess the correct code is
cin.getline(book[count].isbn_code, 14, '\n');
int length = strlen(book[count].isbn_code);
and to increment count once later in your loop.
Remember ++count is not the same as count + 1. The first increments the count variable, that is it changes the value of the count variable, but count + 1 just adds one to count and does not change the value of the count variable.
This is also wrong
for (int i = 0; i <= length; i++)
In C++ string indexes start at zero and go upto the length of the string minus one, so the correct code is
for (int i = 0; i < length; i++)
Also not part of your question but X can be a legal character in an ISBN.

How do I count the number of indexes used in an array

Write a program that asks the user to enter their name. First Name and Last Name are entered separately by the user. The program then tells the following:
• Which part (First name, or Last name), has more character, and how many more characters.
• Total number of vowels used in the complete name.
• Tells the user if the First Name and Second Name are same.
This is my assignment and we cannot use strings library. We are supposed to use the character arrays to go about doing this.
Up till now I haven't been able to understand how can I figure out the number of indexes I use to store characters.
int count = 0;
cout << "Enter you first name: ";
char arr[10];
cin.getline(arr, 10);
for (int i = 0; i < 10; i++) {
if (arr[i] != ' ') {
count++;
}
else {
break;
}
}
int x= sizeof(arr) / sizeof(arr[10]);
cout << arr;
cout << endl << count<< endl<<x;
return 0;
but still I haven't come around to a solution.
I was using the wrong character for comparison. I should have used \0 but I was using ' '.
for (int i = 0; i < 10; i++) {
if (arr[i] != '\0') {
count++;
}
else {
break;
}
}

Beginner c++ array and loop?

Trying to reverse the order of the characters input. I'm getting really close but no cigar.
#include <iostream>
using namespace std;
const int MAX = 10;
int main()
{
char a[MAX], next;
int index = 0;
cout << "Please enter in up to 10 letters ending with a period: " << endl;
cin >> next;
while((next != '.') && (index < 10))
{
a[index] = next;
index++;
cin >> next;
//cout << " " << next << endl;
}
int numbers_used = index;
for(index = 0; index <= numbers_used; index++)
{
a[index] = a[numbers_used -1];
numbers_used--;
cout << a[index] << " " << endl;
}
}
I'm getting everything but the last switch and even though my code is not as clean I'm failing to see where I'm going wrong.
The book code is:
for(index = numbers_used -1; index >= 0; index--)
cout<<a[index];
cout<< endl;
and why is it index = numbers_used - 1 ?? Since numbers_used was set to index and index was initialized at 0 and not 1 wouldn't I want to run the loop "numbers_used" amount of times? What am I missing?
Try this:
char* flip(char* str, int len) {
for(int x=0; x<(len/2); x++) {
swap(str[x], str[len-x-1]);
}
return str;
}
As of right now, after you get to the middle of the string, you'll have overwritten the values that you would need to copy to the second half. With a string like "FooBarBiz", your code will produce the following over iterations (I've put spaces in to try and make things clearer):
1: FooBarBiz
2: z ooBarBiz
3: zi oBarBiz
4: ziB BarBiz
5: ziBr arBiz
6: ziBra rBiz
7: ziBrar Biz
...
The code I posted however, uses the c++ swap function to swap the complimentary values, that way there are no lost values (we're not doing any overwriting), and you won't need to store the whole string in a placeholder variable. Does this make sense?
If you want to reverse the list you have to start from the last element and decrease the index .
You can approach this in at least two different ways. You can reverse the order of the string and then print, or you can leave the original string unmodified and simply print in reverse. I'd recommend the latter approach, in which case all you'd need to do is to change your last for loop to this:
for(index = 0; index < numbers_used; index++)
{
cout << a[numbers_used-index-1] << " " << endl;
}
Wouldn't it be easier this way ?
#include<iostream>
#include<string>
using namespace std;
const int MAX = 5;
int main()
{
char a[MAX], next;
int index = 0;
bool period = false;
cout << "Please enter in up to 10 letters ending with a period: " << endl;
for(int i = 0; i < MAX && !period; i++)
{
cin >> next;
if(next != '.')
{
a[i] = next; // put the value into the array
index++;
}
else
period = true;
}
for(int i = index - 1; i >= 0 ; i--)
{
cout << a[i] << " ";
}
cout << endl;
return 0;
}
The problem can be solved by using the iterators from the standard library. The BidirectionalIterator as for example offered by std::string, std::list or std::vector can be traversed in both directions.
Using a std::string the solution could be:
#include <iostream>
#include <string>
using namespace std;
int main(int, char**) {
char n = 0;
string a;
while (n != '.' && a.size() < 10) {
cin >> n;
if (n != '.') {
a.push_back(n);
}
}
for (string::reverse_iterator it = a.rbegin(); it != a.rend(); ++it) {
cout << *it << endl;
}
}
I will start by saying: use std::string instead of C-style strings - it's universally less messy and more flexible.
Still, let's go with C-style strings since that's how you are attempting to do it and apparently your textbook also.
I won't comment on the way the user input is read, because I'm not sure if it's copied from the textbook (yikes!!) or you've done it yourself either way I find it to be pointless and wrong because it can lead to several problems. Note that the given book solution only prints out the characters in the reversed order and doesn't reverse the character array itself. You are apparently trying to reverse it.
Your solution is decrementing the numbers_used variable inside the for loop itself. This is a very bad idea since that variable is used in the conditional statement of the for loop. This means the loop will stop before it has iterated over the whole array. Even if the loop worked properly you still wouldn't have reversed the array since once this line executes
a[index] = a[numbers_used -1];
the original value of a[index] is overwritten and forgotten.
I'll try and write a simple solution to reverse a character array for a beginner:
#include <iostream>
#include <cstring> //getline, strlen
using namespace std;
const int MAX_LETTERS = 10;
int main() {
char a[MAX_LETTERS + 1]; //since it's zero terminated
cout << "Enter at most " << MAX_LETTERS << "characters (anything over " <<
MAX_LETTERS << " will be truncated):\n";
cin.getline(a, MAX_LETTERS + 1);
int length = strlen(a); //returns length of input
int last_char = length - 1;
//reverse array
for (int i = 0; i < length / 2; i++) {
char temp = a[i];
a[i] = a[last_char];
a[last_char] = temp;
last_char--;
}
//print array
for (int i = 0; i < length; i++)
cout << a[i];
return 0;
}
Read this tutorial on C style strings, it will help you a lot.
The last for loop in your code is
int numbers_used = index;
for(index = 0; index <= numbers_used; index++)
{
a[index] = a[numbers_used -1];
numbers_used--;
cout << a[index] << " " << endl;
}
If we consider 10 letters abcdefghij and according to your code the numbers_used=10after first loop.So in second loop
//In for loop
//index=0
a[index]=a[numbers_used-1]; // a[0]=a[9] => a[0]=j
numbers_used--; //numbers_used=9;
//index=1
a[index]=a[numbers_used-1]; //a[1]=a[8] => a[1]=i
numbers_used--; //numbers_used=8;
//index=2
a[index]=a[numbers_used-1]; //a[2]=a[7] => a[1]=h
numbers_used--; //numbers_used=7;
//index=3
a[index]=a[numbers_used-1]; //a[3]=a[6] => a[1]=g
numbers_used--; //numbers_used=6;
//index=4
a[index]=a[numbers_used-1]; //a[4]=a[5] => a[4]=f
numbers_used--; //numbers_used=5;
//index=5
a[index]=a[numbers_used-1]; //a[5]=a[5] => a[5]=e
numbers_used--; //numbers_used=4;
// index=6 and numbers_used becomes 4 => index <= numbers_used condition is violated
so you will out of for loop.
This is why u cant get through. And in the second code i,e in the Book.
for(index = numbers_used -1; index >= 0; index--)
cout<<a[index];
cout<< endl;
The numbers_used value is 10 but a[9] is the last value in the array so index is assigned to numbers_used-1. so that you can print from a[9] to a[0].