Getting Rid of Extra Blank at the End - c++

I'm supposed to take command line inputs and output them in reverse order. The code I have so far is
#include<iostream>
#include<fstream>
using namespace std;
int main(int argc, char *argv[]) {
for(int num = argc; num >= 2; num--)
cout << argv[num - 1] << " ";
for(int num = argc; num < 2; num--)
cout << argv[num - 1];
return 0
}
It does its job, but I'm getting an unwanted white space the end of the very last output so for example if I did
./reverse first second third
It would output
third_second_first_
The space after the first is unwanted and I'm having trouble getting rid of it. It's supposed to take as many arguments as I'd like. Is there a simple way to delete the last space?

Best way to delete it is by not printing it in the first place.
Test to make sure you have at least one printable input and print it. Then for all remaining inputs print out the delimiter followed by the input.
#include<iostream>
int main(int argc, char *argv[]) {
if (argc > 1)
{ // Ensure that where is at least one argument to print
std::cout << argv[argc - 1]; // print last argument without adornment
for(int num = argc - 2; num > 0; num--)
{ // Print a space and all remaining arguments.
// For visibility, I've replaced the space with an underscore
std::cout << "_" << argv[num] ;
}
}
/* unsure what this loop is supposed to do. Doesn't do anything in it's current state,
so I've commented it out.
for(int num = argc; num < 2; num--)
{
std::cout << argv[num - 1];
}
*/
return 0;
}
Input:
first second third
Output:
third_second_first

For the "simple" solution, I would do something like this:
#include <iostream>
int main(int argc, char* argv[])
{
while (--argc > 0)
std::cout << argv[argc] << ' ';
std::cout << '\n':
}
Do note that it will print the trailing space after the last (first) argument, but unless your professor has a requirement to not have it, or you have an online judge or something similar that disallows it I don't see how it really matters. It's easy to fix though:
while (--argc > 1)
std::cout << argv[argc] << ' ';
std::cout << argv[argc] << '\n':

Related

How to check if a character matches another character in a char array?

I'm currently trying to figure out how I can replace a certain character in a char array using a for loop to check each index position in the array. However, when I assign the correct character to the char variable "letterGuessed" and it is checked it instantly goes to the else statement. This leaves the character as an asterisks. This is the code below:
#include <iostream>
#include <cstring>
void hide_Word(char hide[], int size);
int main()
{
char hiddenWord[] = "Hello";
char displayWord[30] = { 0 };
int length = strlen(hiddenWord);
hide_Word(displayWord, length);
std::cout << hiddenWord << std::endl;
std::cout << displayWord << std::endl;
char letterGuessed;
std::cout << "Enter a character: ";
std::cin >> letterGuessed;
for (int i = 0; i < length; i++)
{
if (displayWord[i] == letterGuessed)
{
letterGuessed == displayWord[i];
}
else
{
std::cout << "*";
}
}
std::cout << std::endl;
std::cout << displayWord << std::endl;
std::cin.get();
return 0;
}
void hide_Word(char hide[], int size)
{
for (int i = 0; i < size; i++)
{
hide[i] = '*';
}
}
When I compile your code I get the warning
main.cpp|27|warning: statement has no effect [-Wunused-value]
for the line
letterGuessed == displayWord[i];
This, for one, means that what you do to make correctly guessed letters visible is achieving nothing. Reading and considering warning messages is really helpful, you know.
I guess that your goal here is to turn the "*", which you filled displayWord with, should be replaced by the correctly guessed character.
That would better be achieved by an assignment using =.
letterGuessed = displayWord[i]; /* still unhelpful */
But that line would still not achieve anything visible.
To change something in the displayWord, it should be what gets the guessed character as a new value, not the other way around.
displayWord[i] = letterGuessed;
This is however still not satisfying, because you don't do this in the right situation.
Let's have a look at the condition which determines when you do it.
if (displayWord[i] == letterGuessed) /* unhelpful */
This will trigger, when the guessed character is an asterisk "*", because displayWord is filled with asterisks early on.
Which means that the condition only triggers if the user guesses an asterisk, which is unlikely. Even if it happens, the result is to overwrite an asterisk with an asterisk.
The condition you need should not check the asterisk-filled displayWord, it should instead check the "Hello"-filled hiddenWord.
if (hiddenWord[i] == letterGuessed)
In total, the code should hence be
for (int i = 0; i < length; i++)
{
if (hiddenWord[i] == letterGuessed)
{
displayWord[i]=letterGuessed;
std::cout << letterGuessed;
}
else
{
std::cout << "*";
}
}
This turns an asterisk in the displayed word into the correctly guessed character at each found position.
Note that I added an output of the guessed letter, to complete the letter-by-letter output. I guess you want to delete that output, or the word-output after the loop, so that the filled in word is only seen once.
Output:
Hello
*****
Enter a character: l
**ll*
**ll*

How to properly understand the carriage return (a.k.a. \r)?

I have seen this carriage return example online about a loading effect but I am failing to understand it properly. Why does it have to be 2 \rLoading and not one? Can someone explain it to me?
for (int j = 0; j < 3; j++) {
cout << "\rLoading \rLoading";
for (int i = 0; i < 3; i++) {
cout << ".";
sleep(300);
}
}
The first section
\rLoading____
is printed to have the string "Loading" and three empty spaces at the beginning of the line. The next carriage return then sets the cursor to the beginning of the line. Then
Loading
is printed again, but the cursor is now directly behind the word, at the first of the three spaces. Now here:
for (int i = 0; i < 3; i++) {
cout << ".";
sleep(300);
}
three dots are printed in an interval of 300 seconds each into the places, where the three dots are.
This whole procedure is iterated three times, so the main purpose of the three blanks of the first "Loading" is, to delete the dots from the previous iteration.
The key is that \r will not clear characters which were printed on the screen earlier. So the first \rLoading act as a display eraser.
In fact you can use 10 spaces instead of the Loading , but you must count it accurately, which is not intuitional.
The following is the optimized code, which can be directly compiled and run on an modern x86 & linux machine. You can try to delete one of the \rLoading and see what will happen for easily understanding.
#include <iostream>
#include <unistd.h>
int main(int argc, char* argv[]) {
for (int j = 0; j < 3; j++) {
std::cout << "\rLoading \rLoading" << std::flush;
// std::cout << "\r \rLoading" << std::flush; // same effect
for (int i = 0; i < 3; i++) {
std::cout << "." << std::flush;
sleep(1);
}
}
std::cout << std::endl;
return 0;
}
Two promotions:
a std::flush is needed or you will not see the effects
300 seconds is too long -> 1 seconds

Why is my code printing the wrong ciphertext?

I am trying to make a program that turns a string into encryption by going ten letters ahead of each letter. https://gyazo.com/86f9d708c2f02cf2d70dbc1cd9fa9a06 I am doing part 2. When I input "helloworld" something like 0x45 something comes up. Please help! This is due soon!
I am tried messing around with the for loops but it didn't help.
#include <iostream>
using namespace std;
int main()
{
//Input Message
cout << "Enter a message" << endl;
string message;
getline(cin, message);
//Convert Message to Numbers
int numMess[message.length()];
for (int i = 0; i<message.length(); i++) {
numMess[i] = (int)message[i];
}
cout << numMess << endl;
//Encrypt Number Message by adding ten to each one
int encryptNumMess[message.length()];
for (int a = 0; a < message.length(); a++){
encryptNumMess[a] = numMess[a] + 10;
if (encryptNumMess[a] > 122) {
encryptNumMess[a] = 97;
}
}
cout << encryptNumMess << endl;
//Convert Encrypted Number Message to letters
string encryption[message.length()];
for (int b = 0; b<message.length(); b++) {
encryption[b] = (char)encryptNumMess[b];
}
cout << encryption << endl;
return 0;
}
I expect when I type "helloworld" the final product will be "rovvygybvn"
If you are willing to scrap the hand-coded loops, you can use the STL algorithms such as std::transform to accomplish this:
But first, there are a few things you should do:
Don't use magic numbers such as 122, 97, etc. Instead use the actual character constants, i.e a, b, etc. However if we assume ASCII, where the alphabetic character codes are contiguous, your particular program could simply use a constant string to denote the alphabet, and then use simple indexing to pick out the character.
const char *alphabet = "abcdefghijklmnopqrstuvwxyz";
Then to get the letter a, a simple subtraction is all that's required to get the index:
char ch = 'b';
int index = ch - 'a'; // same as 'b' - 'a' == 98 - 97 == 1
std::cout << alphabet[index]; // will print 'b'
Given this, the next thing is to figure out what character is reached if you add 10 to the value, and if greater than 26, wrap around to the beginning of the alphabet. This can be done using modulus (remainder after division)
char ch = 'x';
int index = (ch - 'a' + 10) % 26; // Same as ('x' - 'a' + 10) % 26 == (120 - 97 + 10) % 26 == 33 % 26 == 7
std::cout << alphabet[index]; // will print 'h'
The next thing is to figure out the opposite, where given an encrypted character, you have to find the unencrypted character by subtracting 10. Here this wraps the opposite way, so a little more work needs to be done (not shown, but code sample reflects what is done).
Putting this all together, and using std::transform and lambdas, we get the following small program:
#include <iostream>
#include <algorithm>
#include <string>
#include <iterator>
#include <cmath>
int main()
{
//Input Message
const char *alphabet="abcdefghijklmnopqrstuvwxyz";
std::string message = "helloworld";
std::string result;
// set the encrypted string using the formula above and std::transform
std::transform(message.begin(), message.end(), std::back_inserter(result),
[&](char ch) { return alphabet[(ch - 'a' + 10) % 26]; });
std::cout << "Encrypted: " << result << '\n';
// convert back to unencrypted using the above formula and std::transform
std::string result2;
std::transform(result.begin(), result.end(), std::back_inserter(result2),
[&](char ch)
{ int index = ch - 'a' - 10; index = index < 0?26 - (abs(index) % 26):index % 26; return alphabet[index];});
std::cout << "Unencrypted: " << result2;
}
Output:
Encrypted: rovvygybvn
Unencrypted: helloworld
This code works for encrypt, if you want to decrypt you should chande newAlphabet and oldAlphabet
I comment in the code that which newAlphabet and oldAlphabet are for encrypt and which are for decrypt
#include <windows.h>
#include <stdio.h>
#include <string>
#include <iostream>
using namespace std;
int main()
{
// For Encrypt
string newAlphabet = "abcdefghijklmnopqrstuvwxyz";
string oldAlphabet = "klmnopqrstuvwxyzabcdefghij";
// For Decrypt
//string newAlphabet = "klmnopqrstuvwxyzabcdefghij";
//string oldAlphabet = "abcdefghijklmnopqrstuvwxyz";
string input = "";
string output = "";
getline(cin, input);
int inputLen = input.size();
if (oldAlphabet.size() != newAlphabet.size())
return false;
for (int i = 0; i < inputLen; ++i)
{
int oldCharIndex = oldAlphabet.find(tolower(input[i]));
if (oldCharIndex >= 0)
output += isupper(input[i]) ? toupper(newAlphabet[oldCharIndex]) : newAlphabet[oldCharIndex];
else
output += input[i];
}
cout << output << endl;
return 0;
}
As others have already mentioned int numMess[message.length()]; is not valid c++.
If it works for you, you're using compiler extension which you really shouldn't rely on. The correct way would be:
std::vector <int> numMess(message.length());
Look up the std::vector reference for more info.
Next, int encryptNumMess[100]; creates a C array style array. encryptNumMess is the base pointer to the array. when you try std::cout << encryptNumMess it'll output the pointer value, NOT the array. You'll need a for loop for doing that, like so :
for(int i = 0; i < 100; ++i)
std::cout << encryptNumMess[i] << " ";
std::cout << endl;
The above also works when you convert this to a vector like we did with numMess whereas in that case, std::cout << encryptNumMess wouldn't even compile.
Thirdly, string encryption[100] creates an array of 100 strings! Not a string of size 100. To do that:
std::string foo(message.length(), '\0');
We have to specify what character to fill the string with. Thus us '\0'.
And now, for the string, to output it, you may use std::cout << foo.
Lastly, since arithmetic is allowed on char, the entire program may be shortened to just this
#include <iostream>
int main()
{
// Input Message
std::cout << "Enter a message" << std::endl;
std::string message, encryption;
getline(std::cin, message);
// Resize encryption string to the desired length
encryption.resize(message.length());
// Do the encryption
for(size_t i = 0; i < message.length(); ++i) {
encryption[i] = message[i] + 10;
if (encryption[i] > 122) {
encryption[i] = 97;
}
}
// Output the string
std::cout << encryption << std::endl;
return 0;
}
Of course, your encryption algorithm is still not correct as per instructions, but I'll leave that for you to figure out. I believe #PaulMcKenzie has already told you most of how to fix it, and also to not use magic numbers.

atoi() Not Working with std::string::substr()

This is a snippet of my code:
#include <iostream>
#include <fstream>
#include <string>
#include <stdlib.h> // atoi()
int main() {
std::string line;
std::ifstream numbers("numbertest.txt");
if (numbers.is_open()) {
while (std::getline(numbers, line)) {
for (int i = 0; i < line.length() - 4; i++) {
for (int n = 0; n < 5; n++) {
std::cout << atoi((line.substr(i, 5)[n]).c_str());
}
I want to operate with numbers in groups of 5, from a file. Why is atoi() not working here? It says "expression must have class type" under the second parentheses on the atoi line.
line.substr(i, 5) creates a temporary std::string containing 5 characters in line from position i
std::string foo = "hello world";
int i = 2;
std::cout << foo.substr(2, 5) << '\n';
would print "llo wo".
The [n] operator returns the nth character of the substring, which is of type char, you are then calling .c_str() on that character rather than on the substring.
You can avoid the .c_str() entirely by using std::stoi, e.g.
std::cout << "line.substr(i, 5) = " << line.substr(i, 5) << '\n';
std::cout << std::stoi(line.substr(i, 5));
aoti and stoi both take a string representation of a number as their input and return the numeric value. For example:
std::string input = "123a";
// std::cout << input * 10 << '\n'; // illegal: input is a string, not a number.
int i = std::stoi(input); // converts to integer representation, i.e. 123
std::cout << i * 10 << '\n'; // outputs 1230
----- EDIT -----
You're actually asking all the wrong questions. What you want to do is take an input pattern and output all of the patterns of 5 characters in it.
Example input: "1020304050"
Example output: 10203 02030 20304 03040 30405 04050
You don't need to convert these to numbers to output them, you can just output the characters. The problem with your original code wasn't the conversion it was the incorrect sequence of operators.
std::substring is expensive, it has to create a new, temporary string, copy characters from the original into it, and then return it, and it does it for every call.
The following should achieve what you're trying to do:
while (std::getline(numbers, line)) {
for (size_t i = 0; i < line.length() - 4; i++) {
for (size_t n = 0; n < 5; n++) {
std::cout << line[i + n];
}
std::cout << '\n';
}
}
If you really want to invoke substr, you could also implement this as
while (std::getline(numbers, line)) {
for (size_t i = 0; i < line.length() - 4; i++) {
std::cout << line.substr(i, 5) << '\n';
}
}
Here's a working demonstration: http://ideone.com/mXv2z5
Try atoi( line.substr(i,5).c_str() )
Or if you want for each character
std::cout << ((line.substr(i, 5)[n]) - '0');
Or even better
std::cout << (line[i+n]) - '0');
Note that: atoi is not ascii to integer. It converts a ctype string to number. For a single character, this conversion should be done using arithmetic or lookup table.
Also there is no point converting characters to integer and then print it (back to chacters). You should better print digit character itself.
Moreover in C++, I would prefer to use stringstream instead or atoi. On C++11 there are even more advanced solutions like sto*.

Convert argv[1] into an int and it's digits into an array

I've been trying to create a program in C++ that tries to accomplish this pseudocode:
get argv[1] into int
get int’s digits into array[int length]
for int i = array length; i >= 0;
gen random number into check
if check == array[i]
i
say Number i was check
end if
And I think the part I'm really struggling with is the
get argv[1] into int
get int’s digits into array[int length]
part. In my full code there isn't even an attempt because nothing I've tried works. The error I get the most is that the code compiles, but everytime it tries to cout << "Number 1:" << number I just get Number 1: 0 no matter the actual number I enter. And when 0 == 0 the code doesn't even notice.
My broken propably convention-breaking code follows:
#include <iostream>
#include <string>
int main (int argc, char **argv) {
if (argc == 1 || argc == 3) {
std::cout << "Argument count does not match (one argument expected)\n";
return(-1);
}
std::cout << "Input: " << argv[1] << "\n";
const char* text = argv[1];
int number = atoi(text);
int check = rand() % 10;
std::cout << "Check 1: " << check << "\nNumber 1: " << number << "\n";
if (check == array[i]) {
i++;
std::cout << "Success! Number " << i << " was " << check << ".\n";
}
}
}
TL;DR: My "sort of" number cracker doesn't want to put argv1 into an int with the int's digits being later put into an array.
Feel free to make me feel stupid. Hope the question isn't too specific. I'll expand on details as asked.
EDIT: This is an earlier attempt at conversion:
int array[];
for (int i = strlen(text); i >= 0; i--) {
array[i] = number % 10;
number /= 10;
}
EDIT2: So many responses, no solutions. Thank you for trying to explain this newbie so many things at once. BTW: Git
The earlier attempt is almost good: it's just that you have to actually allocate space for the array, like this:
int array[strlen(text)];
if your compiler supports variable-length arrays as an extension, and
std::vector<int> array;
array.resize(strlen(text));
if you want to stick with standard C++ and follow some good practices.
However, if you want to be tricky, you don't even need to convert the argument to a number:
if (argv[1][i] == check % 10 + '0')
does the trick too. All in all, the complete program would look like this:
#include <iostream>
#include <cstdlib>
int main(int argc, char *argv[])
{
int check = std::rand();
std::cout << check << std::endl;
char *p = argv[1] + strlen(argv[1]);
while (p - argv[1] >= 0) {
if (*--p == '0' + check % 10)
std::cout << "guessed " << p - argv[1] << "th digit" << std::endl;
check /= 10;
}
return 0;
}
Your code is relatively close to being right. You are struggling with the declaration of the array (you must specify the size for it). 32-bit int cannot have more than ten digits, so declaring
int array[10];
should be sufficient.
Before converting the number to an array of digits, check if it is negative, and flip its sign if it is negative:
if (number < 0) {
number = -number;
}
Otherwise, your number%10 trick is not going to work.
When you do the conversion, count how many digits you have. Put the result in actualCount variable: chances are that you are not going to use up all the digits in your array, so
int check = rand() % 10; // 10 is the max, not the actual digit count
should be
int check = rand() % actualCount;
Your argument checking also needs improvement: think what would happen if the user passes five parameters? If you expect exactly one argument, you should write
if (argc != 2) {
std::cout << "Argument count does not match (one argument expected)\n";
return(-1);
}
In order to extract only one digit at a time from a number you have a couple of choices.
For convenience you can use a std::string, inserting the original string (argv[1]) in it, then extracting one char at a time:
#include <string>
...
// put the input in a string
std::string text = argv[1];
for (unsigned i = 0; i < text.size(); i++)
{
// extract only one char, a digit
char ch = text.at(i);
// convert that char in a number
int n = ::atoi(& ch);
// use n
...
}
If you don't want to use std::string, you can always use a c-like array (argv[1] itself):
#include <cstring>
...
for (unsigned i = 0; i < strlen(argv[1]); i++)
{
// extract only one char, a digit
char digit = argv[1][i];
// convert that char in a number
int num = ::atoi(& digit);
// use n
...
}