Programming Principles & Practices Using C++ - Ch 04 'Try This' exercise - c++

I'm a bit confused about this exercise in the above mentioned book-
"The character 'b' is char('a'+ 1), 'c' is char('a'+ 2), etc. Use a loop to write out a table of characters with their corresponding integer values:
a 97
b 98
c 99
...
z 122"
The book has just gone over while loops, and I read a bit ahead as I was still confused as to how to do this without just listing out each value individually (which I assume isn't the point here), and the next section is about for loops. I thought that maybe you can somehow increase letters in the alphabet by 1 in a loop (so a -> b, b -> c, etc.), but if this is indeed possible, the book hasn't yet gone over how to accomplish this yet.
Thanks in advance, I'm working through this book alone in my spare time so I don't have a professor to ask questions like this, and the Try This exercises don't have their answers listed on Bjarne's website.

Just write a simple loop:
for(auto c = 'a';c <= 'z' ;c++)
cout<<c<<" "<<int(c)<<endl;

Here is my solution to your problem :)
int main (void) {
char c = 'a';
while (c <= 'z') {
std::cout << c << "\t" << c - 0 << '\n'; // c - 0 is convertion to int without cast
++c;
}
return 0;
}

The book is referring to the idea that you can iterate over integers and use the control variable in character arithmetic to get the table. For example, with integers you can iterate over the integers 0 to 25 with
int i = 0;
while (i <= 25) {
cout << i << endl;
i = i + 1; // or ++i
}
Now you can apply the problem hint char('a' + i) to get the rest of the answer. I'll let you work that out.

int main()
{
char ch = 'a';
int i = 0;
while(i < 26)
{
cout << (char)(ch + i) << "\t" << (ch + i) << "\n";
++i;
}
}

You can do something like this:
char ch = 'a';
for (int i = 0; i < 26; ++i)
cout << (char)(ch + i) << " " << (ch + i) << endl;
This will generate the output that you expect.

Here is one way to do it using the while loop:
#include <iostream>
int main()
{
int i = 0; //Initialize i to 0.
while (i < 26) // 0 - 25.
{
int val = 'a' + i; // char('a' + 1), int('a' + 1).
std::cout << char(val) << "\t" << int(val) << std::endl;
++i; //Increments the while loop variable i
}
return 0;
}
Output:
a 97
b 98
c 99
d 100
e 101
f 102
g 103
h 104
i 105
j 106
k 107
l 108
m 109
n 110
o 111
p 112
q 113
r 114
s 115
t 116
u 117
v 118
w 119
x 120
y 121
z 122

I included comments so that you can understand my thoughts and also so that it can be updated.
Here's the answer to the Chapter 4 Try this exercise for the book by Bjarne Stroustrup: Programming Principles and Practice Using C++:
// Description- Try this exercise using a while statement to provide a series of characters from the ASCII code.
#include "stdafx.h"
#include "Std_lib_facilities.h"
int main()
{
int i = 96; // Beginning/initialisation of the integers which will be converted to char (s) in cout.
while (i<122) // The limit for the while statement is the integer which will be safely converted to the last char.
{
cout << i + 1 << '\t'<< char (i+1)<<'\n'; ++i; // The first integer will be 1 plus the initial = 97. Then followed by a tab.
// Then followed by the integer 97 being safely converted to an char using the ASCII.
// The while loop in the two comments is repeated till 122 is converted safely to z.
}
}

Related

Why can't my integers be transferred to an array?

I want to make a program that works with integers that were inputted using space and not enter. when you input the integers 12 80 33 99 with space between each one of them, then the code will separate the integers and put them into an array.
I'm using codeblocks, C++
int main(){
int A;
int j [10] ={0,0,0,0,0,0,0,0,0,0};
cin >> A;
string As;
bool code = true;
int hasil [A][10];
getline(cin,As);
for (int i = 0 ; i < A ; i++){
while (code){
if( cin.get() != '\n'){
cin >> hasil[i][j[i]];
j[i]++;
}else{ code = false;}
}}
for (int i = 0 ;i < A ; i++){
for (int x = 0; x != j[i]; x++){
cout << hasil[i][x]<< " " ;
}
cout << " " << endl;
}
return 0;}
When I input 25 17 70 88, I expected the output to be 25 17 70 88 too, but the actual output was 5 17 70 88. Where is my first 2?
Your 2 was eaten by the call to cin.get() which reads one character which your code then throws it away.
I can't understand exactly what you are trying to do but i can see an error in your code which might cause undefined behaviour. int hasil[A][10] is a static array which means compiler must know its size at compile time, however A is not a compile time constant. If you don't know the size of your array you should use a pointer instead or even better a std container such as std::vector.
To make your code more readable you can also delete the code variable and replace your first for loop body with
while(cin.get() != '\n)
{
cin >> .....
...
}

Output not as expected from the array

I am writing a code where I take user user text input, convert it to binary, store each binary character in an element in an array and then print A or T for 0 and G or C for 1 at random. But the ATGC seem to not follow this rule and they come at random for every digit; 0 and 1. So If the binary is 0010101 I need output as ATGACTG. Also when I store the binary in an int variable, the zero in front of it vanishes. Is there a way to keep it?
#include <iostream>
#include <cstdlib>
#include <bitset>
#include <string>
#include <ctime>
int main()
{
using namespace std;
int p, i=0, a[100000];
int s;
string myString;
int binary;
cout << "Type your text: ";
std::getline (std::cin,myString);
for (std::size_t k=0; k < myString.size(); ++k)
{
std::bitset<8> y(myString[k]);
std::string dna = y.to_string();
binary = atoi(dna.c_str());
cout << binary;
while (binary != 0)
{
a[i] = binary % 10;
binary = binary / 10;
i++;
}
}
std::cout << std::endl;
srand(time(0));
for (int j = (i-1); j>-1; j--)
{
if (a[j] == 0)
{
p = rand() %2;
if (p==0)
cout<< "A";
else
cout<< "T";
}
if (a[j] == 1)
{
s = rand() %2;
if (s == 0)
cout<< "G";
else
cout<< "C";
}
else
{
cout << "";
}
}
}
I don't know why exactly you wrote so much wrong code, but I've managed to extract (and change) the code that actually does the job.
#include <iostream>
#include <string>
#include <bitset>
#include <ctime>
int main()
{
int i = 0, a[8];
std::string myString;
std::cout << "Type your text: " << std::endl;
std::getline(std::cin, myString);
for(auto x : std::bitset<8>(myString).to_string())
a[i++] = x == '1';
std::cout << std::endl;
srand(time(0));
for(int j = 0; j < i; ++j)
if(a[j] == 0)
std::cout << (rand() % 2 ? "T" : "A");
else if(a[j] == 1)
std::cout << (rand() % 2 ? "C" : "G");
std::cout << std::endl;
}
And here's neater version of main:
int main()
{
std::vector<int> a; // using std::vector
std::bitset<8> bs;
std::cout << "Type your text: " << std::endl;
std::cin >> bs; // std::bitset can be read from stream via operator>>
for(auto x : bs.to_string())
a.push_back(x == '1');
std::cout << std::endl;
srand(time(0));
for(auto x : a)
if(x == 0)
std::cout << (rand() % 2 ? "T" : "A");
else if(x == 1)
std::cout << (rand() % 2 ? "C" : "G");
std::cout << std::endl;
}
Just ask if you want an explanation on some specific part.
I told you not to convert the string to an integer. You didn't listen. This is why leading 0 vanishes.
Your output seams to be completely random because you reverse the order of characters in the sequence when reading the information from a.
Here is how I'd solve your problem: run online
#include <iostream>
#include <string>
#include <bitset>
#include <ctime>
#include <cstdlib>
int main()
{
std::cout << "Type your text: " << std::endl;
std::string in_str;
std::getline(std::cin, in_str);
std::string binary_str;
for(int i = 0; i < in_str.size(); ++i)
{
char c = in_str.at(i);
binary_str.append(std::bitset<8>(c).to_string());
}
std::cout << binary_str << std::endl;
srand(time(0));
for(int i = 0; i < binary_str.size(); ++i)
{
char c = binary_str.at(i);
if(c == '0')
std::cout << (rand() % 2 ? "T" : "A");
else
std::cout << (rand() % 2 ? "C" : "G");
}
std::cout << std::endl;
}
If you have any questions, ask me in the comments.
Edit: the OP asked me to explain all mistakes in his program.
Where did all those zeros gone?
To answer this question I'll have to explain all things your program does line-by-line.
Here you convert a symbol to a bitset:
std::bitset<8> y(myString[k])
For example: if k is 'a', then the y would be 01100001.
Here you convert the bitset to a string:
std::string dna = y.to_string();
In our example the dna would be "01100001".
Here you convert the string to an integer:
binary = atoi(dna.c_str());
A very simplified version of what atoi does:
binary = 0;
for(int i = 0; i < dna.size(); ++i)
binary = binary * 10 + (dna.at(i) - '0')
In our example the binary would be 1100001.
Note: that's NOT where you loose zeros. At this point you are still able to extract them because you know that you need to extract 8 digits. So you can append leading zeros to up it's length to 8.
The next line is where you actually loose zeros the first time because cout doesn't know that you want to print 8 digits.
cout << binary;
In our example it would print 1100001.
And here you loose zeros again because you stop extracting digits as soon as binary == 0 even if you extracted less than 8 digits. Also note that you are actually reversing what the function atoi just did with the only difference that you don't get your leading zeros back and the reverse order of bits (see the next paragraph):
while (binary != 0)
{
a[i] = binary % 10;
binary = binary / 10;
i++;
}
Why the output is "random"?
Here you are iterating through myString in the standard order
for (std::size_t k=0; k < myString.size(); ++k)
e.g. if myString is "abc" than
in the first iteration myString[k] would be 'a'
in the second iteration myString[k] would be 'b'
in the third iteration myString[k] would be 'c':
But in this loop you extract digits in reverse order:
while (binary != 0)
{
a[i] = binary % 10;
binary = binary / 10;
i++;
}
eg if binary is 1100001
in the 1st iteration you extract 1 and binary becomes 110000
in the 2nd iteration you extract 0 and binary becomes 11000
in the 3rd iteration you extract 0 and binary becomes 1100
in the 4th iteration you extract 0 and binary becomes 110
in the 5th iteration you extract 0 and binary becomes 11
in the 6th iteration you extract 1 and binary becomes 1
in the 7th iteration you extract 1 and binary becomes 0
Now you end up with an array where bits inside a character code are reversed, but different characters are stored in the array in the normal order.
e.g. If the input string was "abc", then a would become:
1,0,0,0,0,1,1, 0,1,0,0,0,1,1, 1,1,0,0,0,1,1
reversed 'a' reversed 'b' reversed 'c'
If you iterate through a in normal order, the order of bits inside character codes would be reversed. If you iterate through a in reverse order, you get the reversed order of characters.
As a rule of thumb: don't program by guessing, program by thinking.
Further reading
The Zen of Python. Most of this aphorisms are applicable to every programming language with the exception of Brainfuck
Raw C arrays are evil

Why does adding two spaces produce incorrect output?

I have the following program meant to calculate primes:
#include "stdafx.h"
#include <iostream>
#include <vector>
using namespace std;
bool primeTest(int number){
if ((number == 0) || (number == 1)){
return false;
}
if ((number == 2) || (number == 3)){
return true;
}
for (int j = 2; j <= number / 2; j++){
if (number%j == 0){
return false;
}
}
return true;
}
int main(){
vector<int> primeVector;
for (int i = 0; i <= 100; i++){
if (primeTest(i)){
primeVector.push_back(i);
}
}
int pvSize = primeVector.size();
for (int i = 0; i < pvSize; i++){
cout << primeVector[i] << ' ';
}
cin.get();
}
If I change the line cout << primeVector[i] << ' '; to cout << primeVector[i] << ' '; (I added a space) it gives me
28224382245822478224118224138224178224198224238224298224318224378224418224438224
478224538224598224618224678224718224738224798224838224898224978224
instead of
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
Why does this occur? Only a space was added. It doesn't occur with double quotes.
String literals should be enclosed in double quotes, not single quotes. Single quotes are used for character literals. If you have multiple characters in a single character literal, the value is some implementation-defined integer. Multi-character literals are rarely useful.
(Note that this doesn't apply to something like '\n', which is a single character represented by an escape sequence.)
Use " " instead.
Simply put, one space is one characer, two spaces is two characters or a C-Style string.
' ' -- single character.
" " -- two spaces require double quotes.

C++ for loop with char type

>The character 'b' is char('a'+1),'c' is char('a'+2),etc. Use a loop to write out a table of characters with their corresponding integer values.
I cannot finish this exercise because of this error.
error: lvalue required as increment operand
for(char a='a'; a<24; ++a)
{
cout<<char('a'++);
}
The loop body will never execute with the controlling expression a < 24 because you have initialized variable a with character a and all printable characters are not less than ASCII value 32.
Try this:
for(char a='a'; a < 'a' + 24; ++a)
{
cout << a;
}
I think you would be less confused if you named your variable letter instead of a, because it only represents the letter 'a' at the very beginning.
for(char letter='a'; letter<24; ++letter)
{
cout<<char('a'++);
}
I'm going to assume you actually want to print out the entire alphabet, not just the first 24 letters.
It looks from here like you tried to do a mix of two possible approaches. In the first approach, you increment a char from a to z with each iteration of the for loop and print it out each time. In the second approach, you increment some offset from 0 to 25 and print out 'a' + offset.
You mix these two approaches up in the first line. You're starting the loop with letter set to 'a', which you do not know the numerical value of. You then compare letter to see if it is less than 24. Well in any ASCII-compatible character set, the character 'a' has value 97, so this condition will never pass.
You then misuse ++ on the cout line. The ++ operator attempts to modify its operand, yet 'a' is a literal and so cannot be modified. Have a look at what your assignment told you. You can do 'a' + 1 to get 'b', for example, so this assumes you have an offset (which you don't with your current approach).
So to repeat, you have two options. First: keep letter as a char starting at 'a' and fix the condition so that it checks if letter is less than or equal to the value of 'z' and then just print out letter. Second: change letter to offset and start it off at 0 and increment it while it is less than 26, and then print out 'a' + offset.
Note, however, that both of these approaches assume that the letters have consecutive values in the execution character set. This is not necessarily true.
The ++ operator is a "hidden assignment" (the operand's value is changed by it). But you can only assign to variables, which 'a' is not.
I know this has been closed for a while but since the exercise was about while loops and not for loops, I thought I would offer my solution. I'm just going through the book myself and someone in the future might stumble over this.
int i = 0;
char n = 'a'; // this will list the alphabet
int conv = 0;
conv = n; // this converts the alphabet into integer
while (i < 26) { // starts from 0 and goes to 25
cout << char(n + i) << '\t' << conv + i << '\n';
++i;
}
You may use the following: (http://ideone.com/akwGhl)
#include <iostream>
int main()
{
for (char c = 'a'; c <= 'z'; ++c) {
std::cout << "letter " << c << " has value " << int(c) << std::endl;
}
return 0;
}
hey through troubleshooting i obtained a sample that worked , i have yet to perfectly understand how my code works but as the solutions that were proposed to me here seemed too technical for my level i figured that i should publish mine
#include"header files . h"//i use the libraries given in the book
int main () {
char a ='a';
int i = 0 ;
while (i <= 25)//for (i = 0 ; i <= 25 ; i++)
//for those who used for
{
cout << a << '\t' << 'a' + i << endl;
a += 1; // augments the character value of a to b ... then to z
i++; // augments the value of i allowing us thus to make the augmentation,if you are using the for structure do not put I in your code
}
}

C++ display char while loop rows

I am very new to programming, so I apologize if this question seems absurdly simple. I am working on some extra questions in the current chapter of my C++ book. I have actually found a correct answer to the problem, but while doing so, I ran into a situation that is driving me crazy because I can't figure out WHY one particular solution works and another one doesn't.
So, the problem asks to print the ASCII values between 32 and 127 in a few rows with 16 characters per row. The solution I have come to (that works correctly) is this:
#include <iostream>
using namespace std;
int main()
{
char letter;
int count = 0;
for (letter = 32; letter < 127; letter++, count++)
{
if (count == 16)
{
cout << endl;
count = 0;
}
cout << letter << " ";
}
cout << endl;
return 0;
}
Again, the above code runs fine and does what I want it to. The difficulty lies in something I tried before this. I attempted to do the same problem with a nested while loop, like so:
#include <iostream>
using namespace std;
int main()
{
char letter = 32;
int count;
while (letter < 127)
{
count = 0;
while (count < 16)
{
cout << letter << " ";
letter++;
count++;
}
cout << endl;
}
cout << endl;
return 0;
}
This while loop just runs infinitely and also spits out some garbage after the ASCII characters I want, and I can't figure out why. What's even weirder is if I change the variable 'letter' in the code with while loops to an int instead of a char, it runs exactly the way I want it to and terminates when it should, just displaying the actual numbers instead of the ASCII values.
It's only when 'letter' is a char that I get an infinite loop. I'm sure it's something really simple, and I might just be too tired to see it right now, but any help/hints would be much appreciated! Even though I technically got the answer, it's driving me crazy that I don't know WHY the second answer fails so horribly.
Thanks in advance.
The answer is simple, true enough. Here is what happens - (signed)char can have values in the range [-128, 127] in the inner loop after you output the row up to 112, you increment count with another 16 and therefor you also increment letter with 16, this makes letter equal to 112 + 16 = 128, which due to the range of signed char is actually overflowing and becomes -128. So after this execution of the inner loop the condition of the outer loop still holds: -128 < 127. That is also why you get weird chars - these will be the values between -128 and 32.
How to fix the problem? Change the check in the inner loop:
while (count < 16 && letter < 127)
The inner while loop exits when letter == 48, 64, ..., 128. But as it is a (signed) char, 128 is interpreted as -128 and the outer loop will not terminate.
Change the inner loop to
while (count < 16 && letter < 127)
to get the same behavior as in your first example.
Or change letter to int, if it's OK to print all characters including 127:
int letter = 32;
...
cout << (char)letter << " ";
Try this code :
#include <iostream>
using namespace std;
int main()
{
int letter;
for (letter = 32; letter < 128; ++letter)
{
if (letter != 32 && letter % 16 == 0)
cout << endl;
cout << (char)letter << ' ';
}
}