This is for use in a GUI using C++ and FLTK.
Say I have a string x = "ABCDEFG" and an array of boxes y[7].
I'd want to put one of those letters as the label on a box using a for loop such as:
for (int i=0; i<7; i++) {
y[i] = new Fl_Box(120+31*i,40,30,30,"A");
}
but rather than "A" on all of them, of course I'd want "A" on y[0], "B" on y[1], "C" on y[2], etc - with the letter called from the string as the element x[i].
I tried simply using x[0], etc and found that it needed a conversion to char.
I then tried &x[0] and found it just prints the whole string on each of them as its a const char.
Assuming FL_Box expects a C-string style (null terminated), consider using a temporary value.
std::string(x[i], 1).c_str()
This is similar to passing
char temp[2] = { 0 };
temp[0] = x[i];
and passing temp.
you can use the substr() method of std::string like:
for (int i=0; i<7; i++) {
y[i] = new Fl_Box(120+31*i,40,30,30, x.substr(i, 1).c_str());
}
Here is the signature of substr():
string substr (size_t pos = 0, size_t len = npos) const;
Here is a quick test program an its output.
#include <stdio.h>
#include <string>
int main(int argc, char *argv[])
{
std::string x = "ABCDEFG";
for (int i = 0; i < 7; ++i) {
printf("i(%d) c(%s)\n", i, x.substr(i, 1).c_str());
}
return 0;
}
# ./a.out
i(0) c(A)
i(1) c(B)
i(2) c(C)
i(3) c(D)
i(4) c(E)
i(5) c(F)
i(6) c(G)
Related
I want to update a character array by reversing it. The character array is correct when output inside function, but not in main after the function is called.
I believe that the character array is passed by reference, but when updating the array, the character array in the main function is not updated. What am I doing wrong here?
#include <iostream>
#include <cstring>
using namespace std;
void StringReverse(char *ch, int size){
char sh[100] = {0};
for(int i=0 ; i<size ; i++){
sh[i] = ch[size-1-i];
}
sh[size] = '\0';
ch = sh;
cout<<ch<<endl;
}
int main(){
char ch[100];
cin.getline(ch, 100);
int size = strlen(ch);
StringReverse(ch,size);
cout<<ch;
}
I do not want to print the result inside the function, but update the character array 'ch' in the main function by calling the function StringReverse.
You want to use strncpy() instead of ch = sh;. As other people have kindly pointed, you are not modifying ch. You are modifying the local variable sh only.
#include <iostream>
#include <cstring>
using namespace std;
void StringReverse(char *ch, int size){
char sh[100] = {0};
for(int i=0 ; i<size ; i++){
sh[i] = ch[size-1-i];
}
sh[size] = '\0';
strncpy(ch, sh, 100);
cout<<ch<<endl;
}
int main(){
char ch[100];
cin.getline(ch, 100);
int size = strlen(ch);
StringReverse(ch,size);
cout<<ch;
}
The ch in StringReverse function is local to that function. And that's why when assign ch = sh;, it doesn't change the ch in main.
While you can copy sh, a better approach is to use reverse in-place so that you wouldn't need a local copy at all.
For example:
void StringReverse(char *ch, int size){
for(int i = 0, j= size - 1 ; i < j ; i++, j--){
int t = ch[i];
ch[i] = ch[j];
ch[j] = t;
}
cout << ch << endl;
}
If you use std::string instead of a plain char array, it would be a lot easier to do this. You could for example use std::reverse.
I am building a small project for spelling correction, this is not homework.
Given two strings str1 and str2. One has to find out the number of characters matching between two strings.
For example if str1 = "assign" and str2 = "assingn", then the output should be 6.
In str2, characters, "a", "s", "s", "i", "g", "n" are there in str1, "assign". Thus output should be 6.
If str1 = "sisdirturn" and str2 = "disturb", then output should be 6.
In the str2, characters, "d", "i", "s", "t", "u", "r" are there in string str1, "sisdirturn". Thus output should be 6.
I've tried many attempts, however I am unable to get the answer. Kindly help to sort this out and if there is any idea to improve upon this, do tell.
Here is my attempt so far:
int char_match (string str1, string str2)
{
//Take two strings, split them into vector of characters and sort them.
int i, j, value = 0;
vector <char> size1, size2;
char* cstr1 = new char[str1.length() + 1];
strcpy(cstr1, str1.c_str());
char* cstr2 = new char[str2.length() + 1];
strcpy(cstr2, str2.c_str());
for(i = 0, j = 0 ; i < strlen(cstr1), j < strlen(cstr2); i++, j++)
{
size1.push_back( cstr1[i] );
size2.push_back( cstr2[j] );
}
sort (size1.begin(), size1.end() );
sort (size2.begin(), size2.end() );
//Start from beginning of two vectors. If characters are matched, pop them and reset the counters.
i = 0;
j = 0;
while ( !size1.empty() )
{
out :
while ( !size2.empty() )
{
if (size1[i] == size2[j])
{
value++;
pop_front(size1);
pop_front(size2);
i = 0;
j = 0;
goto out;
}
j++;
}
i++;
}
return value;
}
#include <iostream>
#include <algorithm> // sort, set_intersection
std::string::size_type matching_characters(std::string s1, std::string s2) {
sort(begin(s1), end(s1));
sort(begin(s2), end(s2));
std::string intersection;
std::set_intersection(begin(s1), end(s1), begin(s2), end(s2),
back_inserter(intersection));
return intersection.size();
}
int main() {
std::cout << matching_characters("assign", "assingn") << '\n'; // 6
std::cout << matching_characters("sisdirturn", "disturb") << '\n'; // 6
}
The above uses sort and so it has O(N*log N) performance, if that matters. If all your inputs are small then this may be faster than the second solution:
Sora's solution has better complexity, and can also be implemented concisely using standard <algorithm>s:
#include <iostream>
#include <algorithm> // for_each
#include <numeric> // inner_product
int matching_characters(std::string const &s1, std::string const &s2) {
int s1_char_frequencies[256] = {};
int s2_char_frequencies[256] = {};
for_each(begin(s1), end(s1),
[&](unsigned char c) { ++s1_char_frequencies[c]; });
for_each(begin(s2), end(s2),
[&](unsigned char c) { ++s2_char_frequencies[c]; });
return std::inner_product(std::begin(s1_char_frequencies),
std::end(s1_char_frequencies),
std::begin(s2_char_frequencies), 0, std::plus<>(),
[](auto l, auto r) { return std::min(l, r); });
}
int main() {
std::cout << matching_characters("assign", "assingn") << '\n'; // 6
std::cout << matching_characters("sisdirturn", "disturb") << '\n'; // 6
}
I'm using C++14 features, such as generic lambdas, for convenience. You may have to make some modifications if your compiler doesn't support C++14.
For me the solution using sort and set_intersection takes about 1/4th the time as the other solution for these inputs. That's because sorting and iterating over arrays of 6 or 7 elements can be faster than having to walk over arrays of 256 elements.
sort/set_intersection (3667ns) vs. for_each/inner_product (16,363ns)
Once the input is large enough the speed advantage will tip the other way. Furthermore, at the point where the input is too large to take advantage of the small-string optimization then the sort/set_intersection method will start doing expensive memory allocations.
Of course this performance result is highly implementation dependent, so if the performance of this routine matters you'll have to test it yourself on your target implementation with real input. If it doesn't matter then the O(N) solution is the better choice.
I am not 100% on what it is you are actually trying to achieve, but in the case of trying to see how many characters that match in the words, it would be a simple case of just running a loop through them and adding 1 every time you found a match, like this
int char_match (string str1, string str2)
{
//Take two strings, split them into vector of characters and sort them.
unsigned int matches = 0;
unsigned int stringLength = (str1.length > str2.length) ? str2.length : str1.length;
for(unsigned int i = 0; i < stringLength; ++i)
{
if(str1[i] == str2[i])
{
++matches;
}
}
return matches;
}
but from your code it looks like you want to find out exactly how many of the same characters they have that is to say ignoring the actual position of each character then it would be a rather different process. Something along the lines of this
int char_match (string str1, string str2)
{
unsigned int str1CharCount[256] = {0};
unsigned int str2CharCount[256] = {0};
unsigned int matches = 0;
for(unsigned int i = 0; i < str1.length; ++i)
{
++str1CharCount[static_cast<unsigned short>(str1[i])];
}
for(unsigned int i = 0; i < str2.length; ++i)
{
++str2CharCount[static_cast<unsigned short>(str1[i])];
}
for(unsigned int i = 0; i < 256; ++i)
{
matches += (str1CharCount[i] > str1CharCount[i]) ? str1CharCount[i] - (str1CharCount[i] - str2CharCount[i]) : str2CharCount[i] - (str2CharCount[i] - str1CharCount[i]);
}
return matches;
}
please note that for this second function there are probably a lot more efficient ways of doing it, but it should work all the same
EDIT:
This code should do what you wanted, main difference being it checks the ascii value to make sure it is a valid character
int char_match (string str1, string str2)
{
unsigned int str1CharCount[256] = {0};
unsigned int str2CharCount[256] = {0};
unsigned int matches = 0;
for(unsigned int i = 0; i < str1.length; ++i)
{
unsigned short aValue = static_cast<unsigned short>(str1[i]);
if(aValue >= static_cast<unsigned short>('a') && aValue <= static_cast<unsigned short>('z'))
{
++str1CharCount[static_cast<unsigned short>(str1[i]) - 32];
}
else if(aValue >= static_cast<unsigned short>('A') && aValue <= static_cast<unsigned short>('Z'))
{
++str1CharCount[static_cast<unsigned short>(str1[i])];
}
}
for(unsigned int i = 0; i < str2.length; ++i)
{
++str2CharCount[static_cast<unsigned short>(str1[i])];
}
for(unsigned int i = static_cast<unsigned short>('a'); i <= static_cast<unsigned short>('Z'); ++i)
{
matches += (str1CharCount[i] > str1CharCount[i]) ? str1CharCount[i] - (str1CharCount[i] - str2CharCount[i]) : str2CharCount[i] - (str2CharCount[i] - str1CharCount[i]);
}
return matches;
}
I wrote the following code to convert string of type 'aaadddbbbccc' to 'a3d3b3c3' :
#include <iostream>
#include <string.h>
using namespace std;
void stringCompression(char *str,char *newStr){
int a[256] = {0};
int newCount = 0;
for(int i = 0; i < strlen(str) ; i++){
int j = str[i];
if (a[j] == 0 && strlen(newStr) <= strlen(str)){
a[j] = 1 ;
newStr[newCount] = str[i];
newCount++;
int count = 0;
for (int n = i; n < strlen(str); n++){
if(str[i] == str[n]){
count = count + 1;
}
}
newStr[newCount] =(char) count;
newCount++ ;
} else if (strlen(newStr) > strlen(str)){
strcpy(newStr,str);
}
}
}
int main() {
char str[] = "abcdabcdabcd";
char *newStr = new char[strlen(str)+1];
stringCompression(str,newStr);
cout << newStr;
return 0;
}
My problem is at step
newStr[newCount] =(char) count;
even though it is inserted but the output is not a3b3c3d3 but a*squarebox*b*squarebox*c*squarebox*d*squarebox*. squarebox being 2*2 matrix with one value as the number that is desired. I am using eclipse IDE.
. I would really appreciate your help. How can I correct this. Am I using the correct approach?
Thanks in advance.
The problem is that
newStr[newCount] =(char) count;
converts the number "count" into the character corresponding to that number according to the ascii table (http://www.asciitable.com/), which is "end of text" for "3", that does not correspond to any number.
You should convert "count" into a string instead. See here for example:
Easiest way to convert int to string in C++
However, be aware that it might be longer than one digit, for example if count is "11", it will take two letters in string representation.
Hey you have to use http://www.cplusplus.com/reference/cstdlib/itoa/ to convert integer to char string
When I try to compile my program says this" cannot convert âstd::stringâ to âintâ for argument â1â to âint toupper(int)â"
#include <iostream>
#include <cstring>
using namespace std;
int main(){
string names[10];
for (int i=0;i<=9;i++){
cout<<"Please enter name for student "<<i+1<<": ";
cin>>names[i];
}
for(int j=0;j<=9;j++){
names[j]=toupper(names[j]);
cout<<names[j]<<endl;
}
return 0;
}
You must pass a char to std::toupper not whole string:
for (auto &x : names)
std::transform(x.begin(), x.end(), x.begin(), ::toupper);
std::toupper() takes an int, but you are passing it a string. Do something like this:
for(int j=0;j<=9;j++){
for(int p = 0; p < names[j].length(); ++p){
names[j][p]=toupper(names[j][p]);
}
cout<<names[j]<<endl;
}
By the way, you can use strupr function:
char str[] = "sample text";
strupr( str );
cout << str; // will print SAMPLE TEXT
Change this loop
for(int j=0;j<=9;j++){
names[j]=toupper(names[j]);
to
for (int j = 0; j < 10; j++ ) names[j][0] = toupper( names[j][0] );
In your loop names[j] returns an element of the array that is an object of type std::string while you need to gett access only to the first character of the object.
You could do the same the following way using the range-based for statement
for ( std::string &s : names ) s[0] = toupper( s[0] );
toupper(int) accepts only one letter, not the whole string. To capitalize whole string, you should write a function such as:
void ToUpperString(std::string& str)
{
for(int i = 0; i < str.length(); ++i)
{
str[i] = toupper(str[i]);
}
}
And then call it for each string that you want to capitalize:
for(int j = 0; j <= 9; j++)
{
ToUpperString(names[j]);
}
I have a few questions:
How do you get a certain char from a string?
How do you get a char to a int?
How do you get a int to a char?
How do you append a char to a string?
I was just making a simple keyed cipher... just playing around to learn cpp. I do know java so if you could relate to that it would be great!
Here is my code so please tell me how to improve... thanks! :)
#include <string>
using namespace std;
string encrypt(string data, string pass) {
// Use a Keyed Cipher //
string encrypted;
int index = 0;
for (int x = 0; x < sizeof(data); x++) {
int tmp = static_cast<int>(data.substr(x));
int tmpPass = static_cast<int>(pass.substr(index));
tmp += tmpPass;
if (tmp > 126) {
tmp -= 95;
}
if (index > sizeof(pass)) {
index = 0;
}
encrypted += static_cast<char>(tmp);
}
return data;
}
How do you get a certain char from a string?
By using index operator. string::operator[]
How do you get a char to a int?
int charToInteger = stringName[i] ;
How do you append a char to a string?
Using string::append
From the link -
string& append ( size_t n, char c );
Appends a string formed by the repetition n times of character c.
First of all with a string: const char& operator[] ( size_t pos ) const; e.g.:
char tmp = encrypted[x];
For conversion, you can just use C-style conversions:
int tmp = (int)encrypted[x];
This should generally work, as long as you're using an architecture with sizeof(char) <= sizeof(int) (e.g. some Texas Instruments calculators :)
But, in your code, you can just operate with chars, because chars can also be used as numeric types.
The easiest way to append a char to string is using += :
string s = "Hello worl";
s += 'd';
How do you get a certain char from a string?
the class "string" implements the operator [], so to get the "i" char you can use mystring[i].
std::string has a function called "c_str()" which returns "const char*" that is inside the string.
so another way to get a char from a std::string is *(mystring.c_str()+i).
How do you get a char to a int?
char is a 1 byte data type, so you can cast char into an int just like in java.
char c = 'a';
int i = (int)c;
How do you get a int to a char?
just like in Java. notice that int is usually 4 bytes (doesn't have to be 4 bytes!!!), so you might lose data because char is 1 byte.
int i=0xFFFF
char c = (char)i;
c is 0xFF! lost some data!
How do you append a char to a string?
std::string implements operator += so you can use it.
string s = "foo"; char c=s[1];
char c = 'a'; int i = c;
int i = 65; char c = (char) i;
string s = "foo"; char c = 'X'; s += c;
for (int x = 0; x < sizeof(data); x++) won't work - use data.size() not sizeof(data)
int tmp = static_cast<int>(data.substr(x)); won't work either. If you want the ascii value of data[x] just do int tmp = data[x];
if (index > sizeof(pass)) won't work - you need to use pass.size()
And finally, you never increase index within the loop, and you return the wrong string.
#include <string>
using namespace std;
string encrypt(string const & data, string const & pass) { // Pass arguments by const reference, not as values which are copied
// Use a Keyed Cipher //
string encrypted;
int index = 0;
for (int x = 0; x < data.size(); ++x) { // Loop over the length of the string, not the size of the string object
int tmp = data[x]; // No need to cast
int tmpPass = pass[index]; // No need to cast
tmp += tmpPass;
if (tmp > 126) {
tmp -= 95;
}
++index; // Remember to loop over the password as well
if (index >= pass.size()) { // Check against length of string, not size of object
index = 0;
}
encrypted += static_cast<char>(tmp);
}
return encrypted; // Return the encrypted string
}