I need some help with the use of parallel vectors. What I want to do is have 2 vectors, 1 containing the alphabet, and the other containing the alphabet the other way around. When someone types in a word, it prints out the word using the inverted alphabet.
This is what I've done up until now and I'm not too sure if I'm on the right track or not:
#include <iostream>
#include <ctype.h>
using namespace std;
void search(char alfab[], char cripto[], int code){
cout << "Introduce your message: " << endl;
cin >> code;
for(int i = 0; i < code; i++)
{
if(code == 0){
cout << "Your code is:" << cripto[i] << endl;
}
}
}
int main(){
char alfab[26] = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
char cripto[26] = {'z','y','x','w','v','u','t','s','r','q','p','o','n','m','l','k','j','i','h','g','f','e','d','c','b','a'};
char code;
}
Think about how you would do this by hand. Then try to translate those steps to code.
Get user input
for each letter:
decide which letter of your reversed alphabet it is
write that new letter down in the same position as the original
output new string
Try something more like this instead:
#include <iostream>
#include <string>
static const char alfab[26] = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
static const char cripto[26] = {'z','y','x','w','v','u','t','s','r','q','p','o','n','m','l','k','j','i','h','g','f','e','d','c','b','a'};
std::string invert(const std::string &word){
std::string inverted = word;
for(std::string::size_type i = 0; i < inverted.size(); ++i)
{
char ch = inverted[i];
for(int j = 0; j < 26; ++j)
{
if (alfab[j] == ch)
{
inverted[i] = cripto[j];
break;
}
}
}
return inverted;
}
int main(){
std::string word;
std::cout << "Enter a word: " << std::endl;
std::cin >> word;
std::cout << "Your code is: " << invert(word) << std::endl;
}
You could try using one array:
std::string invert(const std::string& original)
{
static const char cripto[26] =
{
'z','y','x','w',
'v','u','t','s','r',
'q','p','o','n','m',
'l','k','j','i','h',
'g','f','e','d','c',
'b','a'
};
const size_t length = original.length();
std::string inverted_text;
for (unsigned int i = 0; i < length)
{
char c = original[i];
inverted_text += cripto[c - 'a'];
}
return inverted_text;
}
Edit 1: Using some math
You could simplify the encryption (inversion) by using some math.
std::string invert(const std::string& original)
{
const size_t length = original.length();
std::string inverted_text;
for (unsigned int i = 0; i < length)
{
char c = original[i];
inverted_text += (25 - (c - 'a')) + 'a';
}
return inverted_text;
}
Using transform
You could use std::transform:
char invert_char(char c)
{
return (25 - (c - 'a')) + 'a':
}
//...
std::transform(original_word.begin(), original_word.end(),
original_word.begin(), invert_char);
Related
So, i need to insert space after space in char string, for example:
we have string: hello world, and function should be return hello world
hello world something else => hello world something else
hello world => hello world (4 spaces) (not necessarily, but preferably)
how?? (definitely need to be used char string)
my solution (it does not work correctly because it insert only 1 space)
from hello world something it returns hello world something:
#include <iostream>
#include <string>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
char* addSpaces(char* str) {
char* p = strchr(str, ' ');
if (p) {
p++;
int n = strlen(p);
p[n + 1] = 0;
while (n) {
p[n] = p[n - 1];
n--;
}
*p = ' ';
}
return str;
}
int main(void) {
const int stringCount = 1;
const int c = 500;
char cstring[stringCount][c];
string str[stringCount];
for (int i = 0; i < stringCount; i++) {
cout << "Enter " << i + 1 << ". line: ";
cin.getline(cstring[i], c);
str[i] = cstring[i];
}
for (int i = 0; i < stringCount; i++) {
cout << "First function result with char in parameter: ";
char* result = addSpaces(cstring[i]);
cout << result << endl;
}
}
Using Dynamic Array:
#include <iostream>
#include <string>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
char *add(char *arr, int lastIndex, char key)
{
int len = sizeof(&arr);
if (len == 0 || arr[len - 1] != '\0')
{
char newArr[len + 100];
newArr[len + 100 - 1] = '\0';
strncpy(newArr, arr, len);
*arr = *newArr;
}
arr[lastIndex] = key;
return arr;
}
int main(void)
{
std::string line;
const int stringCount = 1;
const int c = 500;
cout << "Enter line: ";
std::getline(std::cin, line);
int spaceCount = 0;
char cstring[0];
int lastUpdated = 0;
for (int i = 0; i < sizeof(line); i++)
{
add(cstring, lastUpdated++, line[i]);
if (line[i] == ' ')
{
add(cstring, lastUpdated++, ' ');
}
}
cout << cstring << endl;
}
OR
Check for space first and start char str with len+spaces. and add extra space on each iterate. Else error out of index bound can come.
#include <iostream>
#include <string>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
int main(void)
{
std::string line;
const int stringCount = 1;
const int c = 500;
cout << "Enter line: ";
std::getline(std::cin, line);
cout << line << endl;
int spaceCount = 0;
for (int i = 0; i < sizeof(line); i++)
{
if (line[i] == ' ')
{
spaceCount += 1;
}
}
char cstring[stringCount + spaceCount];
int j = 0;
for (int i = 0; i < sizeof(line); i++)
{
if (line[i] == ' ')
{
cstring[j++] = ' ';
cstring[j++] = ' ';
}
else
{
cstring[j++] = line[i];
}
}
cout << cstring << endl;
}
Modify the main() function according to your needs:
#include <iostream>
#include <cstring>
#include <cstdlib>
#define MAXLEN 500
void add_space(char* str, size_t index, size_t n) {
if (n >= MAXLEN) {
std::cerr << "Cannot further expand the array!" << std::endl;
abort();
}
for (auto i = n; i >= index; --i)
str[i] = str[i - 1];
str[index] = ' ';
}
char* double_spaces(char* str, size_t n) {
for (size_t i = 0; i < n; ++i)
if (str[i] == ' ')
add_space(str, i++, n++);
return str;
}
int main() {
char str[MAXLEN] = "hello world";
std::cout << double_spaces(str, std::strlen(str)) << std::endl;
return 0;
}
Sample Output:
For str[] = "hello world" function returns "hello world"
For str[] = "hello world something else" function returns "hello world something else"
For str[] = "hello world" function returns "hello world"
PS: Better algorithms are possible but they mostly require use of advanced data structures so sticking to the asker's demand of using simple cstrings I have provided one of the simplest and easy to understand solution.
Analysis: The insertion operation requires O(n-index) time which can be reduced by using something similar to ArrayLists.
two loops reading chars from string
void ReadCharWithFreq(string str){
int n = str.size();
int count = 0;
// loops to read all char from string and frequency
for(int i = 0;i<n;i++){
for(int x =0;x<n;x++ ){
if(str[i]==str[x]){
count++;
}
}
//enqueue char with frequency
enqueue(str[i],count);
count=0;
}
} //end of function
same function with different method
using heap array freq[] and memeset
and i dont understand function of memeset(array,int,int)
void ReadCharWithFreq(string str){
int n = str.size();
int SIZE = 40;
int spf=0;
memset(freq, 0, sizeof(freq));
for (int i = 0; i < n; i++){
freq[str[i] - 'a']++;
}
for (int i = 0; i < n; i++) {
if (freq[str[i] - 'a'] != 0) {
cout << str[i] <<" "<< freq[str[i] - 'a'] << " - >";
enqueue(str[i], freq[str[i] - 'a']);
freq[str[i] - 'a'] = 0;
}
}
} //end of function
which one of the above algorithms is more accurate and efficient
i want to read all chars from a string and count their occurrence/frequency
I would use a std::array with space enough to hold the count of all the characters you may encounter:
#include <array>
#include <limits>
constexpr size_t ArrSize = std::numeric_limits<unsigned char>::max()+1;
std::array<unsigned char, ArrSize> ReadCharWithFreq(const std::string& str){
std::array<unsigned char, ArrSize> freq{};
for(unsigned char ch : str)
freq[ch]++;
return freq;
}
Example usage:
#include <iostream>
#include <iomanip>
#include <vector>
int main(int argc, char* argv[]) {
std::vector<std::string> args(argv+1, argv+argc);
for(const auto& str : args) {
auto result = ReadCharWithFreq(str);
for(size_t i=0; i<ArrSize; ++i) {
if(result[i]) {
std::cout << std::setw(3) << i << " " << static_cast<char>(i) << " " << static_cast<int>(result[i]) << "\n";
// enqueue here?
}
}
}
}
So I have this assignment where you have to reposition letters in a char array by given number of repositions. The last letter must become first. For example:
Input: Hello 3
Output: lloHe
But if you have a sentence, you have to do it for each word seperately and, what is more, if there are numbers, you must ignore them. So I have trouble dealing with the check for numbers and dealing with seperate words(I use strtok to split them). This is what I have so far:
#include <iostream>
#include <cstring>
using namespace std;
void Reposition(char text[10000], int n, char result[10000])
{
int startIndex = strlen(text)-1;
int k = n-1;
int currentIndex = 0;
for(int i = 0; i < n; i++)
{
result[k] = text[startIndex];
k--;
startIndex--;
currentIndex++;
}
for(int i = 0; i <= startIndex; i++)
{
result[currentIndex] = text[i];
currentIndex++;
}
}
int main()
{
char text[10000];
cin.getline(text,10000);
int n;
cin >> n;
char result[10000];
char *words;
words = strtok(text, " .,");
while(words != NULL)
{
Reposition(text, n, result);
words = strtok(NULL, " .,");
}
for(unsigned i = 0; i <= strlen(result); i++)
cout << result[i];
return 0;
}
Use std::string instead of C-style string
To remove numbers from a string, use std::remove_if from <algorithm>:
std::string s;
. . .
s.erase(std::remove_if(s.begin(), s.end(), ::isdigit), s.end());
To reposition characters in a string, use std::rotate:
std::rotate(s.begin(), s.begin() + 1, s.end());
I did your homework.
Don't know if you are familiar with all this code.
I Also rewrote your reposition code. It looked very messy.....
One time favour from me. Try to learn something from this.
#include <iostream>
#include <cstring>
#include <ctype.h>
using namespace std;
void Reposition(char * text, int len, int n, char * result)
{
int k = n - 1;
for(int i = 0; i < len; i++)
{
result[i] = text[k++];
if(k == len) k = 0;
}
}
int main()
{
char text[10000];
cin.getline(text,10000);
int n;
cin >> n;
char result[10000];
char * word;
char * beginOfWord = text;
char * resultPointer = result;
int wordLen;
while(* beginOfWord)
{
// copy up to somthing from the alphabet
if(!isalpha(* beginOfWord))
{
*resultPointer++ = * beginOfWord++;
continue;
}
// Find the end of this word
word = strpbrk(beginOfWord, " .,0123456789");
if(word != NULL)
{
// len is distance between end of word and begin of word
wordLen = word - beginOfWord;
}
else
{
// Maybe it is the end of the string
wordLen = strlen(beginOfWord);
}
//reposition the word
Reposition(beginOfWord, wordLen, n, resultPointer);
// Move the pointers beyond the word
beginOfWord += wordLen;
resultPointer += wordLen;
}
//Always terminate
*resultPointer ='\x0';
cout << result;
return 0;
}
//reverse will reverse the string starting at position xn and ending at position (yn-1)
void reverse(char *str, int xn, int yn)
{
//positioning the pointers appropriately
char *start = str + xn;
char *end = str + yn - 1;
char temp;
while(start < end)
{
temp = *start;
*start = *end;
*end = temp;
++start;
--end;
}
}
//one of the logic to reposition
void reposition(char *str, int n)
{
int length = strlen(str);
n = (length > n) ? n : (n % length);
reverse(str, 0, n);
reverse(str, n, length);
reverse(str, 0, length);
}
int main()
{
char text[10000];
cin.getline(text,10000);
int n;
cin >> n;
char result[10000];
strcpy(result, text);
cout << "before: " << result << endl;
char *word;
word = strtok(text, " .,");
while(word != NULL)
{
//check if it is not a number
if(isdigit(word[0]) == 0)
{
reposition(word, n);
//find the word postion in text
int word_position = word - text;
//copy the repositioned word in result at its corresponding position.
int i = 0;
while(word[i])
{
result[word_position + i] = word[i];
++i;
}
}
word = strtok(NULL, " .,");
}
cout << "after : " << result << endl;
return 0;
}
Output:
abcd 345 pqrst 321
3
before: abcd 345 pqrst 321
after : dabc 345 stpqr 321
What's the best way of counting all the occurrences of a substring inside a string?
Example: counting the occurrences of Foo inside FooBarFooBarFoo
One way to do is to use std::string find function:
#include <string>
#include <iostream>
int main()
{
int occurrences = 0;
std::string::size_type pos = 0;
std::string s = "FooBarFooBarFoo";
std::string target = "Foo";
while ((pos = s.find(target, pos )) != std::string::npos) {
++ occurrences;
pos += target.length();
}
std::cout << occurrences << std::endl;
}
#include <iostream>
#include <string>
// returns count of non-overlapping occurrences of 'sub' in 'str'
int countSubstring(const std::string& str, const std::string& sub)
{
if (sub.length() == 0) return 0;
int count = 0;
for (size_t offset = str.find(sub); offset != std::string::npos;
offset = str.find(sub, offset + sub.length()))
{
++count;
}
return count;
}
int main()
{
std::cout << countSubstring("FooBarFooBarFoo", "Foo") << '\n';
return 0;
}
You should use KMP Algorithm for this.
It solves it in O(M+N) time where M and N are the lengths of the two strings.
For more info-
https://www.geeksforgeeks.org/frequency-substring-string/
So what KMP Algorithm does is, it search for string pattern. When a pattern has a sub-pattern appears more than one in the sub-pattern, it uses that property to improve the time complexity, also for in the worst case.
The time complexity of KMP is O(n).
Check this out for detailed algorithm:
https://www.geeksforgeeks.org/kmp-algorithm-for-pattern-searching/
#include <iostream>
#include<string>
using namespace std;
int frequency_Substr(string str,string substr)
{
int count=0;
for (int i = 0; i <str.size()-1; i++)
{
int m = 0;
int n = i;
for (int j = 0; j < substr.size(); j++)
{
if (str[n] == substr[j])
{
m++;
}
n++;
}
if (m == substr.size())
{
count++;
}
}
cout << "total number of time substring occur in string is " << count << endl;
return count;
}
int main()
{
string x, y;
cout << "enter string" << endl;
cin >> x;
cout << "enter substring" << endl;
cin >> y;
frequency_Substr(x, y);
return 0;
}
#include<iostream>
#include<string>
using namespace std;
int main()
{
string s1,s2;
int i=0;
cout<<"enter the string"<<endl;
getline(cin,s1);
cout<<"enter the substring"<<endl;
cin>>s2;
int count=0;
string::iterator it=s1.begin();
while(it!=s1.end())
{
if(*it==s2[0])
{
int x =s1.find(s2);
string subs=s1.substr(x,s2.size());
if(s2==subs)
count++;
}
++it;
}
cout<<count<<endl;
return 0;
}
While trying to duplicate PHP's bin2hex($s) and pack('H*',$s) (aka hex2bin($s) in PHP 5.4.3+) in GCC/Linux C++, I seem to have it figured out except that it's dropping punctuation for some strange reason. Can you figure out what I might be doing wrong in the hex2bin() function? I compared PHP's bin2hex() with mine and it appears to be working there properly, so the problem is in hex2bin().
#include <strings.h>
#include <string>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
string bin2hex(string s) {
int nLen = s.length();
string sOut;
char cBuff[2];
for (int i = 0; i < nLen; i++) {
sprintf(cBuff,"%.2x",s[i]);
sOut.append(cBuff);
cBuff[0] = '\0';
}
return sOut;
}
string hex2bin(string s) {
int nLen = s.length();
string sOut;
char cBuff1[2];
char cBuff2[2];
char cBuff[1];
int n,n1,n2;
for (int i = 0; i <= nLen; i+=2) {
sprintf(cBuff1,"%c",s[i]);
sprintf(cBuff2,"%c",s[i+1]);
n1 = atoi(cBuff1);
n2 = atoi(cBuff2);
n = (n1 * 16) + n2;
sprintf(cBuff,"%c",n);
sOut.append(cBuff);
cBuff[0] = '\0';
cBuff1[0] = '\0';
cBuff2[0] = '\0';
}
return sOut;
}
int main() {
string s;
string sResult;
s = "This is a 123 test.";
sResult = bin2hex(s);
printf("ENCODED: %s\n",sResult.c_str());
sResult = hex2bin(sResult);
printf("UNENCODED: %s\n",sResult.c_str());
return 1;
}
This emits:
ENCODED: 5468697320697320612031323320746573742e
UNENCODED: This is a 123 test
Okay, sleeves rolled up: let's look at C++ version:
Live on Coliru
Don't use C strings unless you need to (sprintf to build a two-char string is not... very efficient)
Use iostreams to encode/decode the hex digits (std::hex)
The hex2bin could optimized, but I went for "simpler"
I added a modicum of input sanitizing on hex2bin
#include <string>
#include <sstream>
#include <iomanip>
std::string bin2hex(std::string const &s) {
std::ostringstream oss;
for (unsigned char ch : s)
oss << std::hex << std::setw(2) << std::setfill('0') << (int) ch;
return oss.str();
}
#include <cassert>
std::string hex2bin(std::string const& s) {
assert(s.length() % 2 == 0);
std::string sOut;
sOut.reserve(s.length()/2);
std::string extract;
for (std::string::const_iterator pos = s.begin(); pos<s.end(); pos += 2)
{
extract.assign(pos, pos+2);
sOut.push_back(std::stoi(extract, nullptr, 16));
}
return sOut;
}
#include <iostream>
int main() {
std::cout << "ENCODED: " << bin2hex("This is a 123 test.") << "\n";
std::cout << "DECODED: " << hex2bin(bin2hex("This is a 123 test.")) << "\n";
}
Output:
ENCODED: 5468697320697320612031323320746573742e
DECODED: This is a 123 test.
With all but the period '.' you just went lucky: the hex digits didn't use an actual hexadecimal value. However, for the period you got 2e but you tried to decode the e using atoi("e"), roughly: that won't work as atoi() requires a decimal value. You could use strtol(str, 0, 16) instead to decode the hexadecimal value.
Note that you have a few buffer overruns when you are using sprintf(): this function writes a terminating null character. In general, you are much better off to snprintf() to avoid buffer overruns. Also, in your decoding routine you access values beyond the end of your string (you use i <= nLen with nLen = s.length() and then access s[i] and s[i+1]). Of course, the code is far too complex:
#include <string>
#include <sstream>
#include <iostream>
#include <iomanip>
std::string bin2hex(std::string s) {
std::ostringstream out;
out << std::hex << std::setfill('0');
for (char c: s) {
out << std::setw(2) << int(c);
}
return out.str();
}
std::string hex2bin(std::string s) {
std::string rc;
int nLen = s.length();
int tmp;
for (int i(0); i + 1 < nLen; i += 2) {
if (std::istringstream(s.substr(i, 2)) >> std::hex >> tmp) {
rc.push_back(tmp);
}
}
return rc;
}
int main() {
std::string s;
std::string sResult;
s = "This is a 123 test.";
sResult = bin2hex(s);
std::cout << "ENCRYPTED: " << sResult << '\n';
sResult = hex2bin(sResult);
std::cout << "UNENCRYPTED: " << sResult << '\n';
return 1;
}
Your code does not convert hexadecimal digits correctly because atoi can only handle decimal digits. Try this
sprintf(cBuff1,"%c",s[i]);
sprintf(cBuff2,"%c",s[i+1]);
n1 = strtoul(cBuff1, 0, 16);
n2 = strtoul(cBuff2, 0, 16);
Also your for loop should be
for (int i = 0; i < nLen; i+=2) {
n1 = atoi(cBuff1);
n2 = atoi(cBuff2);
n = (n1 * 16) + n2;
if cbuff1 is, say, "a", then this won't work, since a is not a digit. It works fine for digits that are '0-9', but not 'a-f'.
You will need to translate non-digits to numeric values.
There are quite a few ways to convert a hex value string to a byte. I think this is pretty decent:
int hexchar(char c)
{
if (c >= '0' && c <= '9') return c - '0';
// if you need to support upper-case hex:
// c = tolower(c);
if (c >= 'a' && c <= 'f') return c - 'a' + 10;
// If we get here, panic
cout << "Error, invalid hex digit:" << c << endl;
return -1;
}
int hexbyte(string s)
{
for(i = 0; i < s.length(); i+=2)
{
char c = hexbyte(s[i]);
c <<= 4;
c += hexbyte(s[i+1];
cout << c;
}
}
Try these trivial routines, good for C and C ++
/*------------------------------------------+
| bin2hex bin2hex bin2hex |
+------------------------------------------*/
static char *bin2hex(unsigned char *s, long L)
{
static char hex[2048];
long i,l=0;
for (i=0; i<L; i++) l+=sprintf(&hex[l], "%02x", 0xFF & (*(s+i)));
hex[l]=0;
return hex;
}
/*------------------------------------------+
| hex2bin hex2bin hex2bin |
+------------------------------------------*/
static char *hex2bin( char *s)
{
static char bin[2048];
unsigned int i,e,l=0,L=strlen(s);
for (i=0; i<L; i+=2) { sscanf(s+i, "%02x",&e); bin[l++]=(char)e; }
bin[l]=0;
return bin;
}