Error while converting string from EBCDIC to ASCII in C/C++ - c++

I am writing c++ code to convert ebcdic to ascii
My main() is shown below
int main()
{
char text[100];
int position;
int count;
printf("Enter some text\n");
cin >> text;
char substring[] = "\\x";
if(strlen(text) 2 != 0)
{
cout << "Length of the string is not even" << endl;
}
else
{
position = 1;
int len_string;
len_string = strlen(text)/2;
cout<<"len_string"<<len_string<<endl;
for (count = 0; count < len_string;count++)
{
insert_substring(text, substring, position);
printf("text is s\n",text);
position = position + 4;
}
}
ebcdicToAscii((unsigned char*)text);
cout << "Converted text" <<text << endl;
char str[]="\xF5\x40\x40\x40\x40\xD4"; //Hardcoded string
ebcdicToAscii((unsigned char*)str);
printf ("converted str is s\n", str);
return 0;
}
Output:
Enter some text
F54040404040D4
len_string7
text is \xF54040404040D4
text is \xF5\x4040404040D4
text is \xF5\x40\x40404040D4
text is \xF5\x40\x40\x404040D4
text is \xF5\x40\x40\x40\x4040D4
text is \xF5\x40\x40\x40\x40\x40D4
text is \xF5\x40\x40\x40\x40\x40\xD4
Converted text**?*?*?*?*?*
converted str is 5 M
Before conversion I need to append \x infront of string
Example:
F540404040D4 must be inserting escape sequence \x
I have written the logic so I got the output:
\xF5\x40\x40/x40\x40\xD4
Now conversion of ebcdic to ascii starts using
ebcdicToAscii((unsigned char*)text);
But I am not getting desired output.
At the same time when I hardcode the string as
\xF5\x40\x40/x40\x40\xD4
the output is as expected
i.e
5 M
I am confused. Please Guide me. I have not shown called functions in code assuming that it is giving proper return.

You shouln't insert \x in inputted string and by the way with or without inserting, that will not work.
Here:
char str[]="\xF5\x40\x40\x40\x40\xD4";
it's just indication, that for example F5 is hexademical number and character with this ascii code should be used (not just symbols F and 5).
Look here for more info: What does \x mean in c/c++?
You should construct string from your input, that will store, not just symbols, but use each 2 bytes for ascii code.
For conversion you can for example use following code:
#include <iostream>
#include <string>
int main()
{
const std::string s ="F540404040D4";
std::string converted;
converted.reserve(s.size() / 2);
for (size_t i = 0; i < s.size(); i += 2)
{
const std::string tmp = s.substr(i, 2);
const int a = std::strtol(tmp.c_str(), 0, 16);
converted += static_cast<char>(a);
}
std::cout << converted.size() << std::endl;
}

Related

The conversion of the alphabetical digit string[z] to its ASCII value and the replacement in the string with the respective integers is not working

It's not giving me any output and I don't know why.
I have tried switching for a while loop.
cin >> input;
for (z=0; z > input.size(); z++) {
input[z]=(int)input[z];
cout << input; }
Expected result:
Input = abc
output = 979899
No Error message.
With the subscript operator [] you can only access one element from the string and you need to write more than one digit to the string ('A' -> "97"). To do that you need to convert the char value to a literal with std::to_string().
The simples solution is to use a second string as output, then you don't get in trouble with the indexing of the input string when you need to resize the string.
std::string str = "abc";
std::string out;
for(auto a : str )
{
out.append(std::to_string((unsigned int)a));
}
std::cout << out << std::endl;

How to look up a pattern in string input?

How can I parse a string that looks like "xxxx-xxxx" and get those xxxx parts as a number? For an example, the user will type in "9349-2341" and I will get those numbers as two different integers.
I need to do that for a random number generator, which chooses the number between these xxxx variables.
Thanks.
You can use std::stringstream to extract numbers from string. It looks like that:
std::stringstream str_stream;
std::string str_to_parse = "1234-5678";
int num[2];
str_stream << str_to_parse;
str_stream >> num[0];
str_stream.ignore(1); // otherwise it will extract negative number (-5678)
str_stream >> num[1];
Also, there is C functions, like sscanf(). For example, your pattern can be extracted with this format: "%d-%d".
std::string str = "1234-5678";
std::string str1 = str.substr (0,4);
std::string str2 = str.substr(5, 4);
int n1 = std::stoi(str1);
int n2 = std::stoi(str2);
// do your random number generation between n1 and n2
Using regular expression
If your input is assured to resemble "xxxx-xxxx" where 'x' represents a digit, you can simply ultilize the following function:
#include <iostream>
#include <string>
#include <regex>
using namespace std;
int main()
{
string input = "9349-2341";
// This pattern matches any string begining with 4 digits and ending with 4 digits, both parts seperated by a slash
string pattern = "([0-9]{4})-[0-9]{4}";
smatch matcher;
regex prog (pattern);
if (regex_search(input, matcher, prog))
{
auto x = matcher[1];
cout << x << " " << endl;
input = matcher.suffix().str();
}
else
{
cout << "Invalid input!" << endl;
}
return 0;
}
As for how to convert string to number, check out this article, from which the following segment is quoted:
string Text = "456";//string containing the number
int Result;//number which will contain the result
stringstream convert(Text); // stringstream used for the conversion initialized with the contents of Text
if ( !(convert >> Result) )//give the value to Result using the characters in the string
Result = 0;//if that fails set Result to 0
//Result now equal to 456
Or, simply as followed:
Using sscanf
#include <cstdio>
using namespace std;
int main(int argc, char ** argv)
{
char input[] = "1234-5678";
int result, suffix;
sscanf(input, "%i-%i", &result, &suffix);
printf("Output: '%i-%i'.\n", result, suffix);
return 0;
}
You should check out C++ reference websites, such as CPlusPlus.

How can I convert string like "\u94b1" to one real character in C++?

We know in string literal, "\u94b1" will be converted to a character, in this case a Chinese word '钱'. But if it is literally 6 character in a string, saying '\', 'u', '9', '4', 'b', '1', how can I convert it to a character manually?
For example:
string s1;
string s2 = "\u94b1";
cin >> s1; //here I input \u94b1
cout << s1 << endl; //here output \u94b1
cout << s2 << endl; //and here output 钱
I want to convert s1 so that cout << s1 << endl; will also output 钱.
Any suggestion please?
In fact the conversion is a little more complicated.
string s2 = "\u94b1";
is in fact the equivalent of:
char cs2 = { 0xe9, 0x92, 0xb1, 0}; string s2 = cs2;
That means that you are initializing it the the 3 characters that compose the UTF8 representation of 钱 - you char just examine s2.c_str() to make sure of that.
So to process the 6 raw characters '\', 'u', '9', '4', 'b', '1', you must first extract the wchar_t from string s1 = "\\u94b1"; (what you get when you read it). It is easy, just skip the two first characters and read it as hexadecimal:
unsigned int ui;
std::istringstream is(s1.c_str() + 2);
is >> hex >> ui;
ui is now 0x94b1.
Now provided you have a C++11 compliant system, you can convert it with std::convert_utf8:
wchar_t wc = ui;
std::codecvt_utf8<wchar_t> conv;
const wchar_t *wnext;
char *next;
char cbuf[4] = {0}; // initialize the buffer to 0 to have a terminating null
std::mbstate_t state;
conv.out(state, &wc, &wc + 1, wnext, cbuf, cbuf+4, next);
cbuf contains now the 3 characters representing 钱 in utf8 and a terminating null, and you finaly can do:
string s3 = cbuf;
cout << s3 << endl;
You do this by writing code that checks whether the string contains a backslash, a letter u, and four hexadecimal digits, and converts this to a Unicode code point. Then your std::string implementation probably assumes UTF-8, so you translate that code point into 1, 2, or 3 UTF-8 bytes.
For extra points, figure out how to enter code points outside the basic plane.
With utfcpp (header only) you may do:
#include </usr/include/utf8.h>
#include <cstdint>
#include <iostream>
std::string replace_utf8_escape_sequences(const std::string& str) {
std::string result;
std::string::size_type first = 0;
std::string::size_type last = 0;
while(true) {
// Find an escape position
last = str.find("\\u", last);
if(last == std::string::npos) {
result.append(str.begin() + first, str.end());
break;
}
// Extract a 4 digit hexadecimal
const char* hex = str.data() + last + 2;
char* hex_end;
std::uint_fast32_t code = std::strtoul(hex, &hex_end, 16);
std::string::size_type hex_size = hex_end - hex;
// Append the leading and converted string
if(hex_size != 4) last = last + 2 + hex_size;
else {
result.append(str.begin() + first, str.begin() + last);
try {
utf8::utf16to8(&code, &code + 1, std::back_inserter(result));
}
catch(const utf8::exception&) {
// Error Handling
result.clear();
break;
}
first = last = last + 2 + 4;
}
}
return result;
}
int main()
{
std::string source = "What is the meaning of '\\u94b1' '\\u94b1' '\\u94b1' '\\u94b1' ?";
std::string target = replace_utf8_escape_sequences(source);
std::cout << "Conversion from \"" << source << "\" to \"" << target << "\"\n";
}

Reading In Data From A Text File And Separating Out The Data Contained In Each Line

In the program currently I wish to read in text from a text file line by line, extracting data from each line. Each line in the text file contains a letter such as “A” followed by a colon “:” followed by an integer such as “2”. The function in the program that should read in the data currently looks like this:
void readFile()
{
std::ifstream aFile;
std::string alldata;
std::string letter;
aFile.open("KeyPopularity.txt");
while (std::getline(aFile, alldata))
{
letter = alldata[0];
for (int i = 0; i < keyboardKeys.size(); i++)
{
if (keyboardKeys[i].character==letter)
{
keyboardKeys[i].noOfPresses = int(alldata[2]);
}
std::cout << letter << " ";
std::cout << int(alldata[2]) << "\n";
}
}
aFile.clear();
}
However the alldata variable at position 0 (alldata[0]) instead of listing just a single character ie the letter lists a number such as 87 before the letter eg. 87 W as opposed to just W. The question is why is this happening and is there a way to extract the data from each line in the text file line by line to obtain the letter at position 0 of a line string and the number at position 2 of the line string?
Some observation/mistakes in your program:
letter is a std::string, however you assign a character to it; this is allowed but are you sure that this is the intent? You can use char instead of string.
alldata[2] is a char. For the line "A:2" for example, the value will be '2' (with ascii value 50, which is not the same as value 2). You cannot simply convert it to int with int(). To convert a character of a digit ('0'..'9') to its respective integer value you need to subtract the value 48 from the ascii code (or '0').
also change type of keyboardKeys[i].character to char instead of std::string
You can rewrite your code like this:
void readFile()
{
std::ifstream aFile;
std::string alldata;
char letter;
aFile.open("KeyPopularity.txt");
while (std::getline(aFile, alldata))
{
letter = alldata[0];
for (int i = 0; i < keyboardKeys.size(); i++)
{
if (keyboardKeys[i].character == letter)
{
keyboardKeys[i].noOfPresses = alldata[2] - '0';
}
std::cout << letter << " ";
std::cout << alldata[2] - '0' << "\n";
}
}
aFile.clear();
}

C++ XOR encryption - decryption issue

I followed a tutorial on stephan-brumme website for XOR encryption (unfortunately I cannot include URL because I do not have enough reputation). What I want to do is following: read the content of example.txt file and decrypt the text that it includes. For example, this is the content of example.txt:
\xe7\xfb\xe0\xe0\xe7
This, when decrypted using password "password" should return "hello". This is the code I got:
#include <string>
#include <iostream>
#include <fstream>
using namespace std;
std::string decode(const std::string& input)
{
const size_t passwordLength = 9;
static const char password[passwordLength] = "password";
std::string result = input;
for (size_t i = 0; i < input.length(); i++)
result[i] ^= ~password[i % passwordLength];
return result;
}
int main(int argc, char* argv[])
{
string line;
ifstream myfile ("example.txt");
if (myfile.is_open())
{
while ( getline (myfile,line) )
{
cout << decode(line);
}
myfile.close();
}
return 0;
}
And this is the result of running the application:
click for image
As you can see, the decryption was not successful. Now, if I make it so it doesn't read the .txt, but directly decrypts the text, like this:
cout << decode("\xe7\xfb\xe0\xe0\xe7");
It works perfectly:
click for image
What am I doing wrong here?
Many thanks in advance! :)
Character XOR by same character is zero, so the result may include zero. std::string doesn't like that because zero terminates the string.
You also can use std::vector<char> instead of std::string for the actual encoding/decoding. You would have to change the decode function to handle vector<char>
And read/write the file in binary.
Edit: Using std::string only, and std::string decode(const std::string& input)
int main()
{
std::string line = "hello";
{
line = decode(line);
std::ofstream myfile("example.txt", std::ios::binary);
myfile.write(line.data(), line.size());
//Edit 2 *************
//std::cout << std::hex;
//for (char c : line)
// std::cout << "\\x" << (0xff & c);
//*************
//This will make sure width is always 2
//For example, it will print "\x01\x02" instead of "\x1\x2"
std::cout << std::hex << std::setfill('0');
for (char c : line)
std::cout << "\\x" << std::setw(2) << (0xff & c);
std::cout << std::endl;
}
{
std::ifstream myfile("example.txt", std::ios::binary | std::ios::ate);
int filesize = (int)myfile.tellg();
line.resize(filesize);
myfile.seekg(0);
myfile.read(&line[0], filesize);
line = decode(line);
std::cout << line << std::endl;
}
return 0;
}
I bet example.txt contains the characters '\', 'x', 'e', '7' etc. You have to read those, process all the backslash escapes, and then feed it to decode.
\xe7 is a common way of representing a single character with hex value E7. (Which is quite likely to be the single character 'ç' depending on your character set). If you want to store (encrypted) readable text, I suggest dropping the \x, and having the file contain lines like "e7fbe0e0e7". Then
- read each line into a string.
- Convert each pair of characters from a hex number into an integer, and store the result in a char.
- Store that char in the string.
- Then xor decrypt the string.
Alternatively, ensure the file contains the actual binary characters you need it to.
Also beware that you are XOR-ing with the terminating nul byte of the password. Did you mean to do that?