I am creating a time class (string base) for my school project! I get a pointer character for the time!I have a function to normalize the time if it is weird.
in normalize function I have a character array to store the correct time but when I want to Assign the character array to the pointer character it is going false!
char st[10] = "", sh[3] = "", sm[3] = "", ss[3] = "";
itoa(hour, sh, 10);
itoa(minute, sm, 10);
itoa(second, ss, 10);
if(hour<10){strcat(st, "0");}
strcat(st, sh);strcat(st, ":");
if(minute<10){strcat(st, "0");}
strcat(st, sm);strcat(st, ":");
if(second<10){strcat(st, "0");}
strcat(st, ss);strcat(st, "");
stime = st;
stime is pointer character which save the time in class.
when I want to use value of stime I get very weird result. stime get the value of last class stime. for example I have this code:
time a("1:50:0"), b("4:5:10");
a.print();
b.print();
but I get 04:05:10 for two classes and I don't know why!
If you need the rest of code I upload it here: Google Drive link to file
When I compile your code I get the following warning:
warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
time(char *t = "0:0:0"):stime(t){normalize(-1, -1, -1);}
This is what is causing your issue.
"0:0:0" in C++ is a const char[5] which can be converted implicitly to a const char * but not to a simple char *, which is the storage type you have chosen for time.
As others have mentioned, in C++ you should use std::string rather than char*.
As a general rule you should never ignore warnings unless you are sure you know why they are appearing. Often, as in this case, they are telling you that your code is not going to behave in the way you'd expect.
You can try this as a C++ solution:
#include <sstream>
#include <iomanip>
#include <iostream>
using namespace std;
string GetComponent(int value)
{
ostringstream oss;
oss << setfill('0') << setw(2) << value;
return oss.str();
}
void PrintTime(int hh,int mm,int ss)
{
cout << GetComponent(hh) << ':' << GetComponent(mm) << ':' << GetComponent(ss) << endl;
}
Usage example:
PrintTime(1,2,3);
PrintTime(1,2,33);
PrintTime(1,22,33);
PrintTime(11,22,33);
Related
So basically I'm trying to add a character in the middle of a string. Normally in something like Python, this would be pretty straightforward, but I'm really not sure how to achieve this in C++. What I'm trying to achieve is something like this:
void converter(){
converted = ":regional_indicator_" + character + ":";
}
So basically, I'm trying to add the variable character of a type char in a string. Should I be storing character as a string instead?
For reference here's all of my code:
#include <iostream>
using namespace std;
string inputLine;
char character;
string converted;
void input(){
cout << "Please input the text in which you would like to be converted" << endl;
cin >> inputLine;
}
void converter(){
converted = ":regional_indicator_" + character + ":";
}
int main(){
input();
for (int i = 0; i < inputLine.length(); i++ ){
character = tolower(inputLine[i]);
}
return 0;
}
Append s behind the strings literals to treat them as std::strings instead of const char*s:
converted = ":regional_indicator_"s + character + ":"s;
You would need to do either using namespace std::literals or using namespace std::string_literals for it to work.
On a side note, in C++, it is strange to have a function converter() to modify a global variable using another global variable. You might want to consider passing character as a parameter to the function instead.
You can do it like this:
converted = ":regional_indicator_" + std::string(1, character) + ":";
This works because adding a string literal (const char *) to a string yields a string. But adding const char * and char results in pointer arithmetic. So, by constructing a std::string from "character" you end up with const char * + std::string yielding a string and then std::string + const char * again yields a string as the final result.
You can avoid invoking the std::string() constructor and memory allocation by using following. I have tested this before posting and it works:
void converter(){
converted = ":regional_indicator_";
converted.push_back(character);
converted.push_back(':');
}
It's better because "converted" already will have some extra memory reserved, so you will just be filling that extra memory with two more characters and won't be allocating new memory.
The wasy way to build strings is to use a std::ostringstream like this:
void converter(){
std::ostringstream oss;
oss << ":regional_indicator_" << character << ":";
converted = oss.str(); // copy the string out
// ... etc ...
}
The added advantage of that method is it converts numbers to string automatically too.
That's not the fastest way so if speed was important I would take advantage of the static nature of this concatenation like this:
std::string converter(){
static char* template = ":regional_indicator_X:";
template[20] = character; // replace the `X` with your character
converted.assign(template, 21); // assign your string all at once
// ... etc ...
}
That works because your string is of fixed length. If thread safety is required you can use thread_local static char* template....
I have a problem, do not to compile this code but, to execute this program. When I run it in the terminal it prints the first 2 cout then the program stops working and the screen on the windows that tells you, i think the problem is to strcat.
I'm using DEVC++ and I have windows 7 pro.
#include <iostream>
#include <string>
#include <cstdlib>
#include <string.h>
using namespace std;
int main() {
char* cambia[] = {"ciao "};
char* c[] = {"mondo"};
cout << "*c: " << *c << endl;
cout << "*cambia: " << *cambia << endl;
strcat( *cambia, *c );
cout << "*cambia: " << *cambia << endl;
}
You don't use strcat() in C++ if you don't absolutely have to (e.g. when maintaining legacy code and touching as little stuff as possible).
Use std::string and its member functions like find or substr for simple tasks, string streams or Boost libraries for more complex string splitting.
At any rate, stay away from strcat().
The method strcat() adds the string from the second argument to the buffer of which you submit to the first argument.
First, the buffer has to be writable. In your example, you are passing a string literal as buffer. Naturally, string literals are read-only. But even then, the string literal has no spare space where the new string could be added.
Instead of fixing your code, let me show you some proper examples how to concat strings in C++ and in C.
This example is showing you how to concat two C++ strings:
#include <iostream>
#include <string>
int main(int argc, const char * argv[])
{
// Create a new C++ string with an initial text.
std::string result = "First string part ";
std::cout << "Result: " << result << std::endl;
// Add some text
std::string textToAppend = "and the second part";
result.append(textToAppend);
std::cout << "Result: " << result << std::endl;
return 0;
}
The following example is showing you how to concat two strings in C:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, const char * argv[])
{
// The two texts to concat
const char *firstText = "This is the first text ";
const char *secondText = "and this is the second one";
// A buffer which is large enough for the operation.
const int bufferSize = 1024;
char buffer[bufferSize];
// Copy the initial text into the buffer.
strncpy(buffer, firstText, bufferSize);
// Add the secon string
strncat(buffer, secondText, bufferSize-strlen(buffer));
// Output the string
printf("Result: %s\n", buffer);
return 0;
}
I suggest, you should use C++ strings if possible. They automatically manage the memory which prevent many memory related issues with C strings.
This line
char* cambia[] = {"ciao "};
creates a variable named cambia in a dynamically created part of memory, called 'stack'. The variable is an array with no declared size, and elements of that array are pointers to characters.
The size of the array follows from the initializer
{"ciao "}
which implies the array will have only one element, and that element is initialized with a value pointing at the first character of string "ciao ". However, the string "ciao " is placed in some completely different area of memory - it is in static block, initialized by a compiler with values found in the program's code. Compiler does not know how you use these values, in particular it doesn't know you will extend it with strcat, so it will not reserve any additional space after the string.
As a result when you concatenate "mondo" to "ciao ", you overwrite some data in memory, possibly some important data...
I'd suggest you to declare local variables for your string, with explicit size:
char cambia[ 20] = "ciao ";
char c[] = "mondo";
This will make a cambia variable long enough to keep 19-character string (plus implicit terminating zero byte '\0', ASCII NUL) and initialize its first 6 bytes with letters 'c', 'i', 'a', 'o', a space ' ' and NUL. Variable c is implicitly sized to 6 (the initializing string length 5 plus 1 for terminating NUL).
Then you can safely concatenate
strcat( cambia, c);
to obtain 11-character string "ciao mondo" and print it out
cout <<"cambia: "<<cambia<<endl;
The problem here is that you are trying to write to a read-only string storage.
These declarations:
char* cambia[] = {"ciao "};
char* c[] = {"mondo"};
declare two arrays, each with a constant string member. The "ciao " and "mondo" are located in read-only memory.
So when you call strcat(*cambia, *c), you are trying to write "mondo" onto the end of "ciao ". Not only does this write to read-only memory, but it also writes outside the memory space given for the string - there is only space for 6 char in the "ciao " string, and you are trying to add another 5 to the end of that.
The solution is to reserve some space for each string. There are various ways to do this. Here's a simple one:
char acambia[20] = "ciao "; // Space for 20 characters.
char* cambia[] = { acambia };
Of coruse, not using the extra level of indirection would make it simpler:
char cambia[20] = "ciao ";
char c[] = "mondo";
strcat(cambia, c);
would achieve the correct result.
First of all you need not headers
#include <string>
#include <cstdlib>
because neither declaration from them is used.
Aslo header
#include <string.h>
should be substituted for
#include <cstring>
In these statements
char* cambia[] = {"ciao "};
char* c[] = {"mondo"};
you defined two arrays each of them having one element of type const char *. The compiler should issue either an error or a warning because these definitions are not correct. It would be correctly to define the arrays the following way
const char* cambia[] = {"ciao "};
const char* c[] = {"mondo"};
These two statements define arrays of const pointers to string literals. It is undefined behaviour if there ia an attempt to change a string literal in a program. Programs are allowed to place string literals in a read-only memory.
You are right saying that the main problem is in statement
strcat( *cambia, *c );
Function strcat appends one character array to the end of another character array. So the second cjaracter array must reserve enough memory that accomodates the appended character array. If you even would define correctly array cambia as
char cambia[] = {"ciao "};
it had no enough memory to store also characters of array c.
So before using strcat you need to reserve enough memory where the concatenated result array would be placed.
You could do this for example the following way
char s[11];
strcpy( s, *cambia );
strcat( s, c );
cout << "s: " << s << endl;
Take into account that instead of character arrays you could use objects of standard class std::string
In this case to append one string to another is made very simply. For example
std::string cambia = "ciao ";
std::string c = "mondo";
cambia += c;
Or
cambia.append( c );
So i have a char *. And i want to cut off some bit at the end. So
char *sentence = "My name is Ted";
How do I cut off the Ted. I could make it a string and then use substring (coming from Java thats my go to method) but id rather not do that way. But im not sure how to do it with a char *.
EDIT: Further on the problem. The issue is in a function that takes a process and is meant to return the location when that process is started from. Thats fine i can get that. But the parameter char *procLocation is passed by reference so the location will be sent back there.
I can only get the location that includes the name of the process. I want to cut off the name of the process and just return the location. Ive tried making the location a string and doing a substring (string - length of the processName). Thats fine. But
procLocation = location.c_str(); // where location.substr is the location - the process name
gives back an error: error C2440: '=' : cannot convert from 'const char *' to 'char *'
Since that is a string literal, you can't modify it.
If you did:
char sentence[] = "My name is Ted";
You could simply set the character before Ted to \0.
You might be better off using std::string though.
Instead of cutting off your literal, you could use std::string constructor that copies fewer characters than is available in your char*:
const char *data = "Hello, Ted!";
string s(data, data+8);
cout << s << endl;
This prints Hello, T
This approach is less wasteful than making a std::string and taking a substring.
To your original problem, as you're coming from Java, you should (should, in the sense of RFC2119) definitely use std::string:
#include <string>
#include <iostream>
using namespace std;
int main(int argc, const char** argv) {
// copy c-string to std::string
string arg0 = argv[0];
cout << arg0 << endl;
// find last occurrence of path separator
size_t found = arg0.find_last_of("/\\");
// split off filename part of string
cout << arg0.substr(0,found) << endl;
return 0;
}
Further, you should not (should not, in the sense of RFC2119) declare the char array as a char pointer, but as a char array:
char[] s0 = "Hello World!"; // <-- is better
char * s1 = "Hello World!"; // <-- avoid this
See this post for actual reasons why this is better. It also gives the reasons for why not to modify such rvalue strings.
You've tagged the question 'c++' and 'string' but you say you don't want to do this with string and substr ? Not sure why that is. You should prefer these over char* and C style string manipulation functions wherever possible.
To do it the C++ way:
string sentence = "My name is Ted";
cout << "\"" << sentence.substr(0, sentence.rfind(' ') ) << "\"" << endl;
Although you could (modifying your code slightly so that you have a mutable string) do this in C:
char sentence[] = "My name is Ted";
*strrchr(sentence, ' ') = '\0';
printf("\"%s\"\n", sentence);
everybody I have problem with string concatenation in C++, here is my code
map<double, string> fracs;
for(int d=1; d<=N; d++)
for(int n=0; n<=d; n++)
if(gcd(n, d)==1){
string s = n+"/"+d;// this does not work in C++ but works in Java
fracs.insert(make_pair((double)(n/d), s));
}
How can I fix my code?
Try like this.
stringstream os;
os << n << "/" << d;
string s =os.str();
In C++ you have to convert an int to a string before you can concatenate it with another string using the + operator.
See Easiest way to convert int to string in C++.
Use streams, in your case, a stringstream:
#include <sstream>
...
std::stringstream ss;
ss << n << '/' << d;
Later, when done with your work, you can store it as an ordinary string:
const std::string s = ss.str();
Important (side-) note: Never do
const char *s = ss.str().c_str();
stringstream::str() produces a temporary std::string, and according to the standard, temporaries live until the end of the expression. Then, std::string::c_str() gives you a pointer to a null-terminated string, but according to The Holy Law, that C-style-string becomes invalid once the std::string (from which you receved it) changes.
It might work this time, and next time, and even on QA, but explodes right in the face of your most valuable customer.
The std::string must survive until the battle is over:
const std::string s = ss.str(); // must exist as long as sz is being used
const char *sz = s.c_str();
n and d are integers. Here is how you can convert integer to string:
std::string s;
std::stringstream out;
out << n << "/" << d;
s = out.str();
You could use a stringstream.
stringstream s;
s << n << "/" << d;
fracs.insert(make_pair((double)n/d, s.str()));
No one has suggested it yet but you can also take a look at boost::lexical_cast<>.
While this method is sometimes criticized because of performance issues, it might be ok in your situation, and it surely makes the code more readable.
Unlike in Java, in C++ there is no operator+ that explicitly converts a number to a string. What is usually done in C++ in cases like this is...
#include <sstream>
stringstream ss;
ss << n << '/' << d; // Just like you'd do with cout
string s = ss.str(); // Convert the stringstream to a string
I think sprintf(), which is a function used to send formatted data to strings, would be a much clearer way to do it. Just the way you would use printf, but with the c-style string type char* as a first(additional) argument:
char* temp;
sprint(temp, "%d/%d", n, d);
std::string g(temp);
You could check it out at http://www.cplusplus.com/reference/cstdio/sprintf/
I am trying to convert an integer to char array and I came across this piece of code
int i = 5;
std::string s;
std::stringstream out;
out << i;
s = out.str();
But when I try to print the value of s it still prints 5. I don't know if its supposed to do that or am I doing something wrong? Besides I would prefer if I could convert the same int to char array. But I would appreciate any help in the matter.
Thanks!
Code taken from: Alternative to itoa() for converting integer to string C++?
Yes, it's supposed to do that. You'd (primarily) notice the difference from just printing a number out directly if you do some other string-type manipulation on the result (e.g., concatenating it with other strings, searching for characters in the string).
Just for example:
std::cout << i+i; // should print "10"
std::cout << s+s; // should print "55"
Besides I would prefer if I could convert the same int to char array.
char *charPtr = new char[ s.length() + 1 ] ; // s is the string in the snippet posted
strcpy( charPtr, s.c_str() ) ;
// .......
delete[] charPtr ; // Should do this, else memory leak.
If you would like to stop worrying about issues like that you might be interested in boost/lexical_cast.hpp.
#include <boost/lexical_cast.hpp>
#include <string>
#include <iostream>
int main() {
const int i=5;
const char* s = boost::lexical_cast<std::string>(i).c_str();
std::cout << s << std::endl;
}