QT. Is any way to multiplicate string several times? - string

In python i can write
s = "dad" * 3
Result will be: s = "daddaddad"
I want to append "tabs" to my string. Something like:
QString tabs = "\t" * count;
What would be a simple, idiomatic way to do it?

You can do it quite simply with a loop:
QString mystring("somestring");
QString output;
for (int i = 0; i < 3; ++i)
output.append(mystring);
//'output' will contain the result string
Please note that the code I provide is in C++, not Python, but the concept still applies (and should be easily ported).
EDIT:
If you need to concatenate single characters, you could do it more easily like this:
int size = 5;
QString output(size, QChar('\t'));
//'output' contains 5 tab characters
Or, if you need to assign to another string (output is already created):
int size = 5;
output.fill(QChar('\t'), size);
//'output' contains 5 tab characters

#include <QString>
QString s;
for(int i = 0; i < 3; ++i)
{
s << "dad";
}

Related

Assigning a new string crashes?

I'm trying to write my first real program with dynamic arrays, but I've come across a problem I cannot understand. Basically, I am trying to take a dynamic array, copy it into a temporary one, add one more address to the original array, then copy everything back to the original array. Now the original array has one more address than before. This worked perfectly when trying with ints, but strings crash my program. Here's an example of the code I'm struggling with:
void main()
{
int x = 3;
std::string *q;
q = new std::string[x];
q[0] = "1";
q[1] = "2";
q[2] = "3";
x++;
std::string *temp = q;
q = new std::string[x];
q = temp;
q[x-1] = "4";
for (int i = 0; i < 5; i++)
std::cout << q[i] << std::endl;
}
If I were to make q and temp into pointers to int instead of string then the program runs just fine. Any help would be greatly appreciated, I've been stuck on this for an hour or two.
q = temp performs only a shallow copy. You lose the original q and all of the strings it pointed to.
Since you reallocated q to have 4 elements, but then immediately reassigned temp (which was allocated with only 3 elements), accessing (and assigning) the element at x now is outside the bounds of the array.
If you have to do it this way for some reason, it should look like this:
auto temp = q;
q = new std::string[x];
for(int x = 0; x < 3; ++x)
q[x] = temp[x];
delete [] temp;
q[x] = 4;
However, this is obviously more complex and very much more prone to error than the idiomatic way of doing this in C++. Better to use std::vector<std::string> instead.

Longest Common Substring non-DP solution with O(m*n)

The definition of the problem is:
Given two strings, find the longest common substring.
Return the length of it.
I was solving this problem and I think I solved it with O(m*n) time complexity. However I don't know why when I look up the solution, it's all talking about the optimal solution being dynamic programming - http://www.geeksforgeeks.org/longest-common-substring/
Here's my solution, you can test it here: http://www.lintcode.com/en/problem/longest-common-substring/
int longestCommonSubstring(string &A, string &B) {
int ans = 0;
for (int i=0; i<A.length(); i++) {
int counter = 0;
int k = i;
for (int j=0; j<B.length() && k <A.length(); j++) {
if (A[k]!=B[j]) {
counter = 0;
k = i;
} else {
k++;
counter++;
ans = max(ans, counter);
}
}
}
return ans;
}
My idea is simple, start from the first position of string A and see what's the longest substring I can match with string B, then start from the second position of string A and see what's the longest substring I can match....
Is there something wrong with my solution? Or is it not O(m*n) complexity?
Good news: your algorithm is O(mn). Bad news: it doesn't work correctly.
Your inner loop is wrong: it's intended to find the longest initial substring of A[i:] in B, but it works like this:
j = 0
While j < len(B)
Match as much of A[i:] against B[j:]. Call it s.
Remember s if it's the longest so far found.
j += len(s)
This fails to find the longest match. For example, when A = "XXY" and B = "XXXY" and i=0 it'll find "XX" as the longest match instead of the complete match "XXY".
Here's a runnable version of your code (lightly transcribed into C) that shows the faulty result:
#include <string.h>
#include <stdio.h>
int lcs(const char* A, const char* B) {
int al = strlen(A);
int bl = strlen(B);
int ans = 0;
for (int i=0; i<al; i++) {
int counter = 0;
int k = i;
for (int j=0; j<bl && k<al; j++) {
if (A[k]!=B[j]) {
counter = 0;
k = i;
} else {
k++;
counter++;
if (counter >= ans) ans = counter;
}
}
}
return ans;
}
int main(int argc, char**argv) {
printf("%d\n", lcs("XXY", "XXXY"));
return 0;
}
Running this program outputs "2".
Your solution is O(nm) complexity and if you look compare the structure to the provided algorithm its the exact same; however, yours does not memoize.
One advantage that the dynamic algorithm provided in the link has is that in the same complexity class time it can recall different substring lengths in O(1); otherwise, it looks good to me.
This is a kind of thing will happen from time to time because storing subspace solutions will not always result in a better run time (on first call) and result in the same complexity class runtime instead (eg. try to compute the nth Fibonacci number with a dynamic solution and compare that to a tail recursive solution. Note that in this case like your case, after the array is filled the first time, its faster to return an answer each successive call.

How to set the selection items for CComboBox to be the CString array all at once?

I am look for the combobox to display 4 rows where the first row shows "a", 2nd row shows "b"..."c"..."d"
cb1 = new CComboBox;
cb1->Create( WS_VSCROLL | CBS_DROPDOWN | WS_VISIBLE | WS_BORDER, CRect(20,200,200, 300), this, 30 );
CString itemSet[] = {"a","b","c","d"};
//I am to set the array all at once with out doing each itme ??
cb1.AddString(itemSet); //fails
There's no function to do so in one go. You could do as Jeeva suggest, a simple loop traversing your array:
CString itemSet[] = {"a","b","c","d"};
for (int i = 0; i < _countof(itemSet); ++i)
{
cb1.AddString(itemSet[i]);
}
However, if you are going to use it often, you could create your own CCombobox derived class and add a function that does it.
class CMyCombo : public CCombobox
{
public:
CMyCombo();
void AddStrings(const CString* strings, int num);
// ...
}
void CMyCombo::AddStrings(const CString* strings, int num)
{
for (int i = 0; i < num; ++i)
{
cb1.AddString(strings[i]);
}
}
Actually, I would probably use a container, such as std::vector or CStringArray, but you get the idea.
By the way, if you are using strings that could be localized, you should not rely on strings only. A better approach can be found here.
One last thing: there's usually no need to create controls on the fly. It's usually easier to create member variables for them.
Do something like this
CString arr[2] = {_T("A"),_T("B")};
for(int i =0 ;i <2; i++)
{
m_ctrlCombo.AddString(arr[i]);
}

triangle pattern centered

i want to create a pattern in c++ that looks like a trianlge(or half a diamond)
using asteriscks: the pattern should have 1, 2, 3, 4, and end in 5 stars like this
*
**
***
****
*****
(but straight!)
my code is as follows:
-`#include
using namespace std;
int main()
{
int size;
cout<<"size:"<<endl;
cin>>size;
int blank=size/2;
int newsize=1;
for (int i=0; i<=size/2; i++)
{
for(int j=blank;j>0;j--)
cout <<" ";
blank--;
for(int j=newsize; j>0; j--)
cout <<"*";
newsize+=2;
cout <<endl;
}
return 0;
}
`
my only problem with it is that it displays 1, 3,and 5 stars like this.
*
***
*****
its just a minor problem but although i have changed different parts of the code
i dont seem to get it right.
any suggestions?
thanks
:)
I'm not sure what you mean by "but straight", so I'll just ignore that for now...
Start with blank the same value as size, so that you can decrement the value each time without having to decrement by a half:
int blank=size;
Loop up to size instead of size/2 to get more lines:
for (int i=0; i<=size; i++)
Decrement by two in the loop for spaces to get half the number of spaces:
for(int j=blank;j>0;j-=2)
Increase the size by one instead of two to get the slower increase:
newsize++;
That should produce the output that you showed.
Edit:
I tested this to be sure, and the output is:
*
**
***
****
*****
******
To get the exact output that you asked for, start with blank one less:
int blank=size - 1;
Did I get it right: you want to place some asterisks on borders of character places? If so, it isn't possible. Every asterisk (or any other symbol), when displayed in monospace fonts, will reside in a middle of a character place, like in a grid. You can place asterisks inside the cells, but you cannot place asterisks on the borders of the grid.
int NUMLINES = 5;
void display(int, char);
void main(){
for (int i=1; i<= NUMLINES; ++i){
display((NUMLINES + 1 - i), ' ');
display(( 2 * i - 1 ), '*');
cout << endl;
}
}
void display (int howmany, char symbol){
for (int i = 1; i<=howmany; ++i)
cout << symbol;
}

Converting a 1D pointer array (char) into a 2D pointer array (char) in Visual C++.

I am new to c++ programming I have to call a function with following arguments.
int Start (int argc, char **argv).
When I try to call the above function with the code below I get run time exceptions. Can some one help me out in resolving the above problem.
char * filename=NULL;
char **Argument1=NULL;
int Argument=0;
int j = 0;
int k = 0;
int i=0;
int Arg()
{
filename = "Globuss -dc bird.jpg\0";
for(i=0;filename[i]!=NULL;i++)
{
if ((const char *)filename[i]!=" ")
{
Argument1[j][k++] = NULL; // Here I get An unhandled
// exception of type
//'System.NullReferenceException'
// occurred
j++;
k=0;
}
else
{
(const char )Argument1[j][k] = filename [j]; // Here I also i get exception
k++;
Argument++;
}
}
Argument ++;
return 0;
}
Start (Argument,Argument1);
Two things:
char **Argument1=NULL;
This is pointer to pointer, You need to allocate it with some space in memory.
*Argument1 = new char[10];
for(i=0, i<10; ++i) Argument[i] = new char();
Don't forget to delete in the same style.
You appear to have no allocated any memory to you arrays, you just have a NULL pointer
char * filename=NULL;
char **Argument1=NULL;
int Argument=0;
int j = 0;
int k = 0;
int i=0;
int Arg()
{
filename = "Globuss -dc bird.jpg\0";
//I dont' know why you have 2D here, you are going to need to allocate
//sizes for both parts of the 2D array
**Argument1 = new char *[TotalFileNames];
for(int x = 0; x < TotalFileNames; x++)
Argument1[x] = new char[SIZE_OF_WHAT_YOU_NEED];
for(i=0;filename[i]!=NULL;i++)
{
if ((const char *)filename[i]!=" ")
{
Argument1[j][k++] = NULL; // Here I get An unhandled
// exception of type
//'System.NullReferenceException'
// occurred
j++;
k=0;
}
else
{
(const char )Argument1[j][k] = filename [j]; // Here I also i get exception
k++;
Argument++;
}
}
Argument ++;
return 0;
}
The first thing you have to do is to find the number of the strings you will have. Thats easy done with something like:
int len = strlen(filename);
int numwords = 1;
for(i = 0; i < len; i++) {
if(filename[i] == ' ') {
numwords++;
// eating up all spaces to not count following ' '
// dont checking if i exceeds len, because it will auto-stop at '\0'
while(filename[i] == ' ') i++;
}
}
In the above code i assume there will be at least one word in the filename (i.e. it wont be an empty string).
Now you can allocate memory for Argument1.
Argument1 = new char *[numwords];
After that you have two options:
use strtok (http://www.cplusplus.com/reference/clibrary/cstring/strtok/)
implement your function to split a string
That can be done like this:
int i,cur,last;
for(i = last = cur = 0; cur < len; cur++) {
while(filename[last] == ' ') { // last should never be ' '
last++;
}
if(filename[cur] == ' ') {
if(last < cur) {
Argument1[i] = new char[cur-last+1]; // +1 for string termination '\0'
strncpy(Argument1[i], &filename[last], cur-last);
last = cur;
}
}
}
The above code is not optimized, i just tried to make it as easy as possible to understand.
I also did not test it, but it should work. Assumptions i made:
string is null terminated
there is at least 1 word in the string.
Also whenever im referring to a string, i mean a char array :P
Some mistakes i noticed in your code:
in c/c++ " " is a pointer to a const char array which contains a space.
If you compare it with another " " you will compare the pointers to them. They may (and probably will) be different. Use strcmp (http://www.cplusplus.com/reference/clibrary/cstring/strcmp/) for that.
You should learn how to allocate dynamically memory. In c you can do it with malloc, in c++ with malloc and new (better use new instead of malloc).
Hope i helped!
PS if there is an error in my code tell me and ill fix it.

Resources