char* multiLineString(constchar* line, int lineLen, int linePadding){
string multiLine = "";
for(int i = 0; line[i] != '\0'; i++){
if(i != 0 && i % lineLen == 0){
multiLine += '\n';
for(int j = 0; j < linePadding; j++){
multiLine += ' ';
}
// Before we start printing the second line, the length needs to be
// reduced to lineLen - linePadding to keep lines all the same length.
// If the first character(s) of a new line is a space, don't print it.
while(line[i] == ' '){
// Skip character
i++;
}
}
multiLine += line[i];
}
char* lines = const_cast<char*>(multiLine.c_str());
return lines;
}
I would think that if the second line prints, the first one would, but it doesn't. What's even odder is that in the loop that that cout statement is in will sometimes output what it should, and other times it won't. And to toss even one more twist on it, two of the outputted values are the exact same. I even double checked with strcmp().
And, if you want to toss one other twist on this, I have multiple functions that print slightly different results. One prints nothing, one prints a couple, and one prints all. I compared the one's that print something and everything, and except for one additional line in the cout statement, they are basically identical.
Does anybody have any idea what might be causing this problem?
I would try a different approach : make use of stringstreams, substr function, setw and setfill.
It seems that you current approach is sort of a C approach in that you are processing 1 char at a time. IMO, if you find yourself doing this in C++ there is probably a better way ....
I also try to avoid char arrays, and use std::string exclusively.
Afaik it's not illegal to use const_cast, why else would it be in the language like that?
And you're right about the pointer; multiLine's destructor will delete [] it at scope exit. The returned pointer points to unallocated memory directly after the call.
Afaik it's not illegal to use const_cast, why else would it be in the language like that?
It isn't illegal. If the original variable was const, it results in undefined behavior. In this case, I think it's reasonable to assume the original variable was not const, but the use of it here is definitely not something I would recommend.
Also, I used a char* because my bookTitle has to be a char[] due to me saving it to a file.
And how is char by char non-C++? Any parsing is character by character.
Coder777, const_cast is necessary for assignment, due to c_str() returning a constant variable. If I don't do it that way, I have to make several other things const. I also see what you mean about the local variable thing. Is there a good way around this?
It occurred to me that even though this accepts a char*, it's for output. Chances are I'll never need to assign the results back to the same type of variable passes. So I just changed the function to a string, and returned multiline. Which makes the function (I think) compatible with both c strings and strings (Using c_str()). The function works perfectly now.
And how is char by char non-C++? Any parsing is character by character.
I am just saying that functions like substr do the same job, that is why they exist in the STL, so one doesn't have to reinvent the wheel.
So for this example all you want to do, is place a newline character (with insert)in the positions that are multiples of the width you want, and pad the last line so that it is right aligned, which you could do with the setfill function.
Yeah, I see what you mean. I'm thinking I'm going to have to keep it like that though, as on my TODO list is to add an option so it will break it at words instead of characters. Which means I'd have to check each character for a space, so I can add word by word, so I can check each word length, etc... Unless there's a better way?
Which means I'd have to check each character for a space, so I can add word by word, so I can check each word length, etc... Unless there's a better way?
Well, basically I need to read the first 50 characters, unless the spaces are at positions 47 and 53, then I'd need to just read the first 47.
Of course, the only way to do that is to read word by word, and calculate to see if that new word with the space before it is longer than the length.
So I need a loop to wrap through the string.
Something to extract up to the next space
An if else statement after each word is read to calculate
Something to add X spaces before the next line starts.
Etc.
I see what you're saying that there are other functions out there, but I really wouldn't be saving any speed, or lines (One or two, maybe?) by using them.
After all, is it really easier to create a variable to hold the result of find_first_of to use it with substr rather than just looping through?
Also, a lot of the functions you're giving me is for stream objects, while I'm not using input, I'm using variables. (Get, streamstring, etc)
I see what you're saying that there are other functions out there, but I really wouldn't be saving any speed, or lines (One or two, maybe?) by using them.
Well, it is up to you, but the whole idea of the STL is so one can just use the tools, rather than write them again themselves. The find_first_of example was pretty concise & easy in my view.
The STL stuff might be optimised in ways you hadn't thought of, and do other things like throw exceptions which can be handy. They are also overloaded - if you write your own code, you would have to write more code to cope with different types of arguments.
meesa wrote:
Also, a lot of the functions you're giving me is for stream objects, while I'm not using input, I'm using variables. (Get, streamstring, etc)
But a std::string can be used to create a stream object, here is an example from the stringstream constructor :
#include <iostream>
#include <sstream>
#include <string>
#include <iomanip>
#include <cstddef>
using std::cout;
using std::cin;
using std::endl;
int main()
{
std::string MyStr = "The quick, brown fox, jumps over, the lazy, dog";
const std::size_t FieldWidth = 10;
std::size_t found = 0;
// Split using the comma char
found = MyStr.find_first_of(",");
while (found!=std::string::npos) {
MyStr[found]='\n';
found=MyStr.find_first_of(",",found+1);
}
cout << "With comma \n\n" << MyStr << "\n\n";
// Same again with spaces
//reset the variables - we are using them again
MyStr = "The quick brown fox jumps over the lazy dog";
found = MyStr.find_first_of(" ");
while (found!=std::string::npos) {
MyStr[found]='\n';
found=MyStr.find_first_of(" ",found+1);
}
cout << "With spaces \n\n" << MyStr << "\n\n";
// This time with a field width and padding of the last line
MyStr = "The quick brown fox jumps over the lazy dog";
std::size_t i;
for (i = 0; i < MyStr.length(); i += (FieldWidth+1)) {
MyStr.insert(i, "\n");
}
i -= FieldWidth; // the pos of i before the end of the string
std::size_t Padding = FieldWidth - (MyStr.length()-i); // Padding needed for last part
MyStr.insert(i, Padding, ' ' );
std::cout << "With Fieldwidth \n\n" <<MyStr << "\n\n";
// this version doesn't modify the string
const std::string MyConstStr = "The quick brown fox jumps over the lazy dog";
cout << "With non modified string \n\n";
for (size_t i =0; i < MyConstStr.length(); i+=FieldWidth) {
cout << std::setw(FieldWidth)<< std::setfill(' ');
cout << MyConstStr.substr(i,FieldWidth) << endl;
}
return 0;
}
With comma
The quick
brown fox
jumps over
the lazy
dog
With spaces
The
quick
brown
fox
jumps
over
the
lazy
dog
With Fieldwidth
The quick
brown fox
jumps over
the lazy
dog
With non modified string
The quick
brown fox
jumps over
the lazy
dog