Beginner c++ array and loop? - c++

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].

Related

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.

Stuck with an infinite loop and whitespaces detection c++

This is the question that needs to be implemented:
Write a C++ program that stops reading a line of text when a period is
entered and displays the sentence with correct spacing and capitalization. For this program, correct spacing means only one space between words, and all letters should be lowercase, except the first letter. For example, if the user enters the text "i am going to Go TO THe moVies.", the displayed sentence should be "I am going to go to the movies."
I have written my piece of code which looks like this:
// Processing a sentence and verifying if it is grammatically correct or not (spacing and capitalization)
//#include <stdio.h>
//#include <conio.h>
#include <iostream>
#include <string>
using namespace std;
int main()
{
string sentence;
cout << "Enter the sentence: ";
getline(cin, sentence);
int len = sentence.length();
// Dealing with capitalizations
for (int j = 0; j <= len; j++)
{
if (islower(sentence[0]))
sentence[0] = toupper(sentence[0]);
if(j>0)
if(isupper(sentence[j]))
sentence[j] = tolower(sentence[j]);
}
int space = 0;
do
{
for (int k = 0; k <= len; k++)
{
if(isspace(sentence[k]))
{
cout << k << endl;
int n = k+1;
if(sentence[n] == ' ' && n <=len)
{
space++;
cout << space <<endl;
n++;
cout << n <<endl;
}
if(space!= 0)
sentence.erase(k,space);
cout << sentence <<endl;
}
}
len = sentence.length();
//cout << len <<endl;
} while (space != 0);
}
With this I was able to deal with capitalization issue but problem occurs when I try to check for more than one whitespace between two words. In the do loop I am somehow stuck in an infinite loop.
Like when I try and print the length of the string (len/len1) in the first line inside do-while loop, it keeps on running in an infinite loop. Similarly, when I try and print the value of k after the for loop, it again goes into infinite loop. I think it has to do with my use of do-while loop, but I am not able to get my head around it.
This is the output that I am receiving.
there are a few different issues with this code, but i believe that the code below addresses them. hopefully this code is readable enough that you can learn a few techniques. for example, no need to capitalize the first letter inside the loop, do it once and be done with it.
the usual problem with infinite loops is that the loop termination condition is never met--ensure that it will be met no matter what happens in the loop.
#include <iostream>
#include <string>
using namespace std;
int main() {
string sentence;
cout << "Enter the sentence: ";
getline(cin, sentence);
int len = sentence.find(".", 0) + 1; // up to and including the period
// Dealing with capitalizations
if (islower(sentence[0]))
sentence[0] = toupper(sentence[0]);
for (int j = 1; j < len; j++)
if(isupper(sentence[j]))
sentence[j] = tolower(sentence[j]);
// eliminate duplicate whitespace
for (int i = 0; i < len; i++)
if (isspace(sentence[i]))
// check length first, i + 1 as index could overflow buffer
while (i < len && isspace(sentence[i + 1])) {
sentence.erase(i + 1, 1);
len--; // ensure sentence decreases in length
}
cout << sentence.substr(0, len) << endl;
}
Here goes
std::string sentence;
std::string new_sentence;
std::cout << "Enter the sentence: ";
std::getline(std::cin, sentence);
bool do_write = false; // Looking for first non-space character
bool first_char = true;
// Loop to end of string or .
for (unsiged int i = 0; i < sentence.length() && sentence[i] != '.'; ++i) {
if (sentence[i] != ' ') { // Not space - good - write it
do_write = true;
}
if (do_write) {
new_sentence += (first_char ? toupper(sentence[i]) : tolower(sentence[i]);
first_char = false;
}
if (sentence[i] == ' ') {
do_write = false; // No more spaces please
}
}
if (i < sentence.length()) { // Add dot if required
new_sentence += '.';
}

Is there a way in C++ to only return the the last instance of a for loop?

Like for example:
#include <iostream>
using namespace std;
int main()
{
for (int n=10; n>0; n--){
cout<< n <<", ";}
}
This will output the numbers 10,9,8,7,6,5,4,3,2,1
So is there a new way so I just get the last instance of the loop, the 1?
I new at this and google isn't giving me any answers.
There is no direct way to detect whether the current iteration of a for loop is the last one. But if the behavior of the loop is predictable, you can usually write code that can detect when you're on the last iteration.
In this case, you could do something like:
if (n == 1) {
cout << n << "\n";
}
in the body of the loop. (Of course it would be simpler in this case to replace the entire loop with cout << "1\n";, but I presume this is an example of something more complex.)
In more complicated cases, you can save whatever information you need in the body of the loop:
int value_to_print:
for ( ... ) {
value_to_print = i;
}
std::cout << value_to_print << "\n";
On each iteration, value_to_print is replaced by the current value of i. The final value is the value of i on the last iteration.
You could create a variable (outside the loop) to hold the "current" value of n; whatever happens to the loop (exit condition reached, break, an exception is thrown...) the value will stay there:
int last_n;
for (int n=10; n>0; n--) {
last_n = n;
cout<< n <<", ";
if (something) {
break; // works in this case
} else if (something else) {
throw some_random_error; // works in this case too
}
}
cout << "The last value of 'n' was " << last_n << endl;
You can use a simple if statement for that.
int main()
{
for (int n=10; n>0; n--) {
cout << n << ", ";
if( n == 1 ) {
return n;
}
}
}
The simplest way to accomplish this is: -
#include <iostream>
using namespace std;
int main()
{
int x;
for (int n = 10; n > 0; n--){
x = n;
}
cout << x;
return 0;
}
I'm new to programming too and was trying to figure out something which will allow me to get the last instance of my loop as output.
I tried something and got the output, see if it can help you (if there's a mistake please let me know).
Here user input string is being replaced by "*" and instead of giving output of every instance i have made so only last instance is given as output.
#include <iostream>
#include <string>
using namespace std;
int main()
{
string str;
int string_length;//string length
cout<<"Enter your Email-ID: ";
cin>>str;
string_length = str.length(); //to give the length of input string and use it for the loop
cout<<"lentgh of the string: "<<string_length <<endl;
for(int x = 0; x <= string_length; x++){
str[x] = '*';
while(x==string_length) //string_length is the last instance of the loop
{
cout<<"Here's your Encrypted Email-ID: " <<str<<endl;
break;
}
}
return 0;
}

C++:array functions

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;
}
}

C++ Novice regarding Vectors and for/while loops

I’m trying to make something that will take lines of input from the user, separate them into strings in a vector, then print them one at a time (8 per line).
so far this is what I’ve got:
#include <iostream>
#include <vector>
#include <string>
#include <sstream>
int main(void)
{
using namespace std;
vector<string> svec1;
string temp;
while(getline(cin, temp)) //stores lines of text in temp
{
if(temp.empty()) //checks if temp is empty, exits loop if so.
break;
stringstream ss(temp);
string word;
while(ss >> word) //takes each word and stores it in a slot on the vector svec1
{
svec1.push_back(word);
}
}
}
I’m stuck on getting it to print them 8 at a time, the solutions I’ve tried keep getting subscript out of range errors.
Something like this:
for(int i = 0; i < svec1.size(); i++)
{
cout << svec1[i];
if ((i+1) % 8 == 0)
cout << endl;
else
cout << " ";
}
?
EDIT:
the solution above outputs extra space/newline at the end. It can be avoided by something like this:
for(int i = 0; i < svec1.size(); i++)
{
if (i == 0)
/*do nothing or output something at the beginning*/;
else if (i % 8 == 0)
cout << endl; /*separator between lines*/
else
cout << " "; /*separator between words in line*/
cout << svec1[i];
}
Walk over your vector with an index:
for (unsigned int idx = 0; idx < svec1.size(); ++idx) {
std::cout << svec[idx] << sep(idx); // sep(idx) is conceptual; described below
}
What is this sep(idx)? It is the separator to print after the idxth word. This is
A newline after having printed eight words on a line. idx will be 7, 15, 23, etc: One shy of an integer multiple of 8. In code, (idx+1)%8 == 0.
A newline for the last item in the vector; you probably want the last item to be followed with a newline. In code idx+1 == svec.size().
A space otherwise.
An easy way to do this is with the ternary operator:
for (unsigned int idx = 0; idx < svec1.size(); ++idx) {
const char * sep = (((idx+1)%8 == 0) || (idx+1 == svec.size())) ? "\n" : " ";
std::cout << svec[idx] << sep;
}
If you don't like that,
for (unsigned int idx = 0; idx < svec1.size(); ++idx) {
const char * sep;
if (((idx+1)%8 == 0) || (idx+1 == svec.size())) {
sep = "\n";
}
else {
sep = " ";
}
std::cout << svec[idx] << sep;
}
Normally you iterate over a vector using a for loop clause. So if you want to print all elements of your vector<string> you have to make something like this:
for(vector<string>::iterator it = myvec.begin(); it != myvec.end(); ++it) {
cout << *it;
}
EDIT: as Vlad has posted correctly, you can also use array indices, which are less efficient in lists, but equally efficient with vectors.