The string str_hex contains the hex-values for the letters A-J, which corresponds to the decimal values 65-74. I'm trying to cast each hex-value to its decimal value following this example. It works nice for the std::cout case inside the for-loop, but the output-std::string still has the ascii-values. Why does this not work or is there a nicer/more proper way to build my output string?
#include <string>
#include <iostream>
#include <stdint.h>
int main()
{
std::string str_hex("\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b", 10);
std::string str_output = "";
for (int i = 0; i < 10; ++i)
{
uint8_t tmp = str_hex[i];
str_output.append(1, (unsigned)tmp);
std::cout << "cout+for: " << (unsigned)tmp << std::endl;
if(i<9)
str_output.append(1, '-');
}
std::cout << std::endl << "cout+str_append: " << str_output << std::endl;
return 0;
}
Compiling and running the program gives the following output:
cout+for: 65
cout+for: 66
cout+for: 67
...
cout+str_append: A-B-C-D-E-F-G-H-I-J
The desired output is:
cout+str_append: 65-66-67-68-...
The method string::append accepts, among the various overload, a size_t and a char, see reference.
string& append (size_t n, char c);
Therefore, in your code line
str_output.append(1, (unsigned)tmp);
you are implicitly converting the unsigned tmp to a char, i.e., to a single letter. To obtain the output you want, you have to convert tmp to a string containing the number, and then append it to str_output. You can do that by using
str_output+=std::to_string(tmp);
instead of str_output.append(1, (unsigned)tmp);.
You have to change your string append to for the change from a number to its "string":
str_output.append(std::to_string(tmp));
It's not one character that you want to add, but a string representing the number.
Related
I am writing a program that uses a substitution cipher.
I am trying to replace each char in a string (that the user entered) with a char from another string (the encryption key string).
But I am having a bunch of issues doing this with the string.replace() function. It does not replace the the char in the userMessage with the correct char. Although this is not an issue when using a string literal as initialization value for letterReplacement. In addition to this, it somehow temporarily increases the size of the userMessage resulting in the loop running for e.g 5 times in a message 3 char long (no matter how letterReplacement was initialized). I would appreciate any information on why this happens.
#include <iostream>
#include <string>
#include <vector>
int main()
{
std::string userMessage;
std::cout << "\nWelcome to my Military Grade* Encryption Software!" << std::endl;
std::cout << "--------------------------------------------------" << std::endl << std::endl;
std::cout << "Please enter a secret message you would like to encrypt:\n-" << std::endl;
getline(std::cin, userMessage);
std::cout << "-" << std::endl << std::endl;
const std::vector <std::string> encryptionKey {"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZT.,<>!?+- '",
"ß?pl ,;0=}okm9)]ijN8([uhb7/{zgv6&ctf%xdrys4$e3w|<2Q>1!+#ä-:*GnB"};
for(size_t i {0}; i < userMessage.size(); ++i) // Here we encrypt the Message
{
char currentCharInUM {userMessage.at(i)};
size_t currentKeyPosition {encryptionKey.at(0).find(currentCharInUM)}; //finds the position that currentChar is at in first encryptionKey String
std::cout << "currentKeyPosition: " << currentKeyPosition << " - " << i << std::endl;
if(currentKeyPosition == std::string::npos) // is letter in userMessage is not in encryptionKey just keep it (skip iteration)
continue;
std::string letterReplacement {encryptionKey.at(1).at(currentKeyPosition)};
userMessage.replace(i,1,letterReplacement);
}
std::cout << userMessage;
return 0;
}
The first character of 2nd element of the vector encryptionKey 'ß' is equal to 2 bytes. So that when you enter 'a' it returns '├' and when you enter b it returns 'ş'. You can try to put another character instead of 'ß'.
If your intention was indeed to store non-ASCII characters, it would have been more advantageous to use a lookup table.
The table could be a std::unordered_map<char, wchar_t> to map the English letters to the encrypted characters:
#include <iostream>
#include <string>
#include <unordered_map>
int main()
{
// Strings
const char encryptionKeyA[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZT.,<>!?+- '";
const wchar_t encryptionKeyW[] = L"ß?pl ,;0=}okm9)]ijN8([uhb7/{zgv6&ctf%xdrys4$e3w|<2Q>1!+#ä-:*GnB";
// Create the lookup table bassed on the above strings
std::unordered_map<char, wchar_t> encryptionMap;
for (int i = 0; i < sizeof(encryptionKeyA); ++i)
encryptionMap[encryptionKeyA[i]] = encryptionKeyW[i];
// Test
std::string userMessage = "abcTest";
// The output string
std::wstring encryptedString;
// Now go through each character of the userMessage
for(auto ch : userMessage)
{
// If the character exists, append the associated encrypted character
auto iter = encryptionMap.find(ch);
if (iter != encryptionMap.end())
encryptedString += iter->second;
else
encryptedString += L' '; // Just append a space if it didn't exist
}
std::wcout << encryptedString;
}
Output:
ss?p1 N8
Note that the output is what is displayed if the locale is English. If the terminal/output were set to German, I would assume that the output would be:
ß?p1 N8
since the first character is the "double-s".
Also note that I am assuming that both the original and encrypted character strings are of the same size (in terms of the number of characters) when building the map. If they're not the same size, then the loop to build the map should be adjusted accordingly.
I'm a beginner to C++ so forgive me if I'm making a stupid mistake here.
I want to loop through a string of integers in the following code:
#include <string>
using namespace std;
int main() {
string str = "12345";
for (int i : str) {
cout << i << endl;
}
return 0;
}
But I receive the output:
49
50
51
52
53
I know that I get normal output if I use char instead of int, but why do I receive an output of integers 48 more than they should be?
When you loop through a string you get elements of type char. If you convert a char to an int you get the ASCII value of the char, which is what happens when you do:
string str = "12345";
for (int i : str) { // each char is explicitly converted to int
cout << i << endl; // prints the ascii value
}
The ASCII value of '0' is 48, and '1' is 49, etc, which explains the output you get.
Just what #cigien said, You just need to change it from int to char i.e
string str = "12345";
for (char i : str) {
cout << i << endl;
}
Or one solution for all auto keyword
string str = "12345";
for (auto i : str) {
cout << i << endl;
}
The first thing you need to know is that a string is an array/sequence of chars.
You can think of a char as a single character.
But the way it is encoded is as a number.
For example, the char 'a' is encoded (in ASCII) as the number 97.
Now your for loop says int i: str.
You're telling it to look for integers in the string.
But a string is an array/sequence of chars, not of integers.
So the loop takes each char,
and instead of looking at what the character itself is,
it gives you the integer encoding value of the char,
the ASCII value.
Now the numbers are encoded with the char '0' having the lowest encoding value,
'1' having the next value,
'2', having the next,
and so on through digit '9'.
I can never remember what the actual ASCII value for '0' is . . . .
But because the digit chars are encoded consecutively in this way,
you can convert any digit char to its int value by subtracting the underlying integer encoding value of '0'.
#include <string>
using namespace std;
int main() {
string str = "12345";
for (char c: str) {
cout << (c - '0') << endl; // gives you the actual int value, but only works if the char is actually a digit
}
return 0;
}
for (int i : str) { is infact syntactic sugar for
for (auto iterator = str.begin(); iterator != str.end(); iterator++) {
int i = (int) *iterator;
But the *-operator from string::iterator is infact an overload which returns the current char. It will as such be casted to an int. What you then see is this number. It is the integer value of the byte. Not necessarily ASCII. It could be ANSI too.
I'm working on this code that takes a numeric string and fills an array with each "digit" of the string. The issue I'm having is trying to convert an integer to a string. I tried using to_string to no avail.
Here is the code (note this is pulled from a larger program with other functions):
#include <cstdlib>
#include <stdlib.h>
#include <iostream>
#include <time.h>
#include <typeinfo>
int fillarr(int &length) {
int arr[length];
string test = "10010"; //test is an example of a numeric string
int x = 25 + ( std::rand() % ( 10000 - 100 + 1 ) );
std::string xstr = std::to_string(x); //unable to resolve identifier to_string
cout << xstr << endl;
cout << typeid (xstr).name() << endl; //just used to verify type change
length = test.length(); //using var test to play with the function
int size = (int) length;
for (unsigned int i = 0; i < test.size(); i++) {
char c = test[i];
cout << c << endl;
arr[int(i)] = atoi(&c);
}
return *arr;
}
How can I convert int x to a string? I have this error: unable to resolve identifier to_string.
As mentioned by user 4581301, you need an #include <string> to use string functions.
The following, though is wrong:
arr[int(i)] = atoi(&c);
The atoi() will possibly crash because c by itself is not a string and that mean there will be no null terminator.
You would have to use a buffer of 2 characters and make sure the second one is '\0'. Something like that:
char buf[2];
buf[1] = '\0';
for(...)
{
buf[0] = test[i];
...
}
That being said, if your string is decimal (which is what std::to_string() generates) then you do not need atoi(). Instead you can calculate the digit value using a subtraction (much faster):
arr[int(i)] = c - '0';
Okay I modified my code a bit per suggestion from everyone and ended up handling the conversion like this:
string String = static_cast<ostringstream*>( &(ostringstream() << x) )->str();
cout << String << endl;
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*.
I am learning C++ for the first time. I have no previous programming background.
In the book I have I saw this example.
#include <iostream>
using::cout;
using::endl;
int main()
{
int x = 5;
char y = char(x);
cout << x << endl;
cout << y << endl;
return 0;
}
The example makes sense: print an integer and the ASCII representation of it.
Now, I created a text file with these values.
48
49
50
51
55
56
75
I am writing a program to read this text file -- "theFile.txt" -- and want to convert these numbers to the ASCII value.
Here is the code I wrote.
#include <iostream>
#include <fstream>
using std::cout;
using std::endl;
using std::ifstream;
int main()
{
ifstream thestream;
thestream.open("theFile.txt");
char thecharacter;
while (thestream.get(thecharacter))
{
int theinteger = int(thecharacter);
char thechar = char(theinteger);
cout << theinteger << "\t" << thechar << endl;
}
system ("PAUSE");
return 0;
}
This is my understanding about the second program shown.
The compiler does not know the exact data type that is contained in "theFile.txt". As a result, I need to specify it so I choose to read the data as a char.
I read the each digit in the file as a char and converted it to an integer value and stored it in "theinteger".
Since I have an integer in "theinteger" I want to print it out as a character but char thechar = char(theinteger); does not work as intended.
What am I doing incorrect?
You are reading char by char, but you really (I think) want to read each sequence of digits as an integer. Change your loop to:
int theinteger;
while (thestream >> theinteger )
{
char thechar = char(theinteger);
cout << thechar << endl;
}
+1 For a very nicely formatted & expressed first question, BTW!
You are reading one char at a time from the file. Hence, if your file contains:
2424
You will first read the char "2" from the file, convert it to an int, and then back to a char, which will print "2" on cout. Next round will print "4", and so on.
If you want to read the numbers as full numbers, you need to do something like:
int theinteger;
thestream >> theinteger;
cout << char(theinteger) << endl;