invalid conversions, unspecified behaviour and char arrays? - c++

I am trying to do http://www.spoj.com/problems/SHLIGHTS/, for which I have designed a solution. I am very new to C++(about 14 days), and I am facing a lot of problems. Earlier I used Python, and there was nothing of these errors, anyways, I wrote this..
#include <iostream>
#include <string>
#include <cstdio>
using namespace std;
//example is GBGBBB
//t=0, GBGBBB then t=1,BGBGBB then t=2 BBGBGB, then t=3 BBBGBG
//search for GB and replace it with BG
//we need a function that replaces things
string swapSEQ(string SEQ)
{
unsigned int sizeSEQ=SEQ.size();
unsigned int curr(0);
while (curr<sizeSEQ-1)
{
if (SEQ[curr]=="G" and SEQ[curr+1]=="B")
{
SEQ[curr]="B";SEQ[curr+1]="G";curr+=2;
}
else {++curr;}
}
return SEQ;
}
int main()
{
unsigned int numCases;
scanf("%d",&numCases);
// cin>>numCases;
for (unsigned int currentCase=0;currentCase<numCases;++currentCase)
{
string SEQ;
//scanf("%s",&SEQ);
cin>>SEQ;
string swapped=swapSEQ(SEQ);
unsigned long long t=0;
while (swapped!=SEQ)
{
swapped=swapSEQ(SEQ);++t;
}
printf("%lld\n",t);
}
return 0;
}
I know that's a lot of details, but that's it. SPOJ shows blank lines after inputs and outputs, but after reading the description, I understand we have to do things in single lines. Here's what I get with my g++4.7 compiler(LINUX)
SHLIGHTS.cpp: In function ‘std::string swapSEQ(std::string)’:
SHLIGHTS.cpp:17:18: error: comparison with string literal results in unspecified behaviour [-Werror=address]
SHLIGHTS.cpp:17:18: error: ISO C++ forbids comparison between pointer and integer [-fpermissive]
SHLIGHTS.cpp:17:37: error: comparison with string literal results in unspecified behaviour [-Werror=address]
SHLIGHTS.cpp:17:37: error: ISO C++ forbids comparison between pointer and integer [-fpermissive]
SHLIGHTS.cpp:17:52: error: invalid conversion from ‘const char*’ to ‘char’ [-fpermissive]
SHLIGHTS.cpp:17:66: error: invalid conversion from ‘const char*’ to ‘char’ [-fpermissive]
cc1plus: all warnings being treated as errors
*What is happening? There's something about pointers, const char and unspecified behaviour.
**I know pointers are sort of variables that point to memory locations, nothing more.
**I've used scanf at some places and cin at others(if I replace scanf by cin, I get the same errors)
**Is it something about the fact that I returned a string that took as argument?
**Where did I use a pointer?
**Am I wrong about this- strings in c++ are char arrays? If no, then where is the invalid conversion?
Thanks in advance, and apologies for anything wrong. If it's too long, please answer any of the doubts.

You need to compare SEQ[curr] with 'G' not "G" since it's a char and not a string.
You should use operator && instead of and.
Something with your logic is worng. At one index of a string you can have only 1 char. So writing if (SEQ[curr] == 'G' && SEQ[curr] == 'B' is same as writing if (false).
It is not an error, but please don't abuse your code by writing more than one commend at a line.
If you writing is C++ please use cin , not scanf.
Why are you creating sizeSEQ if you never use it? Don't!

you should use 'G' instead of "G" and so on. When you access a char array (e.g. arr[5]) you obtain a char, which you can compare with a char literal (being: 'G') and not with a cstring (e.g. "G" or "Google").
The compiler is your friend, it points out that the problem is:
comparison with string literal

Related

printing a set containing strings on graphics.h in c++

I am trying to print the elements of a set containing strings on graphics.h console using outtext() function,but i get this error:
cannot convert 'std::string {aka std::basic_string}' to 'char*' for argument '1' to 'void outtext(char*)'|
this the piece of code that gives error:
for(i=0;i<20;i++){
for(j=0;j<20;j++){
outtext(str[i][j]);
}
}
the template for the outtext function in the graphics.h header is like this:
void outtext(char *textstring);
i have used c_str() like this:
for(i=0;i<20;i++){
for(j=0;j<20;j++){
outtext(str[i][j].c_str());
}
}
but this time it gives this error:
error: invalid conversion from 'const char*' to 'char*' [-fpermissive]|
You can try this one as well:
char *cstr = new char[21]; // just in case string length is maxed at 20, leave 1 character for '\0'
for (int i = 0; i<20; i++) {
for (int j = 0; j<20; j++) {
strcpy_s(cstr, str[i][j].length() + 1, str[i][j].c_str());
outtext(cstr);
}
}
delete[] cstr;
Just added a char* string to temporarily hold the converted std::string value. The tricky part is that char* strings normally have the terminating character \0 which std::string don't have, so you have to add 1 more character to the size of each "row" of str.
I take it this question is about the 30 years old BGI graphics library and Borland C++. The root of the problem is that this library was poorly written, as it didn't implement const correctness.
The Turbo C++ compiler did not follow anything remotely close to any C++ standard, so you are mostly out of luck. If you had a proper C++ compiler you could use const_cast, but I very much doubt this is available to you.
The only solution left is the dirty, bad way:
outtext((char*)str[i][j].c_str()); // bad practice
You should never cast away const like this in neither C nor C++.
If you can change the prototype of the output function then it is better to change void outtext(char *textstring); to void outtext(const char *textstring); because there is no need for the output function to modifiy the string. Otherwise you could use const_cast before passing to the function like outtext(const_cast<char*>(str[i][j].c_str())) or copy the string to another char* and passed the copied value.

C++ invalid conversion from ‘char’ to ‘const char*’ [-fpermissive]

WARNING: Extremely limited knowledge of C++ and coding in general. Please refrain from advanced terminology.
for ( i = 0; i < answer.size(); ++i) {
if (guess == answer.at(i)) { //to display correct letters in answerDisplay
answerDisplay.replace( (2 * i), 1, answer.at(i) );
correctGuesses += 1;
}
Given: answerDisplay and answer are strings.
When I run my program there is a compile-time error at the third line of what I've posted saying:
invalid conversion from ‘char’ to ‘const char*’ [-fpermissive]
What's the problem? How can I fix it? All other posts with this error talked about pointer characters but I don't know what those are.
Pointer characters are they way plain strings are implemented in C and C++. In C++ you have the nice class std::string, but string literals are still array of characters. And arrays in C and C++ can be seen as pointers.
For example, "hello" is of type const char[6] (5 characters plus the ending NUL), but it can be trivially converted to const char *, and that in turn can be converted to std::string.
In line 3, the only relevant code is a call to the member function std::string::replace(). There are a lot of overrides of this function (different sets of parameters to be used), but the one the compiler is trying to use is this one:
string& replace (size_t pos, size_t len, const char* s);
As you can see, it takes two numbers and a const char * (an old-string/char-array). But you are passing as third parameter answer.at(i) that is of type char. Hence the error:
invalid conversion from ‘char’ to ‘const char*’
Solution? You can build a string from that char:
answerDisplay.replace( (2 * i), 1, std::string(1, answer.at(i))
Or you can get a substring of the original string instead of a plain character.
answerDisplay.replace( (2 * i), 1, answer.substr(i, 1))

copy data from txt file to char pointer in c++

I am trying to get fingerprint data (which I created and stored as a text file in another code) which I have to compare with a new fingerprint in this code. The problem is that the fingerprint API requires the fingerprint data to be passed as char pointer. I'm using the following code :
std::ifstream infile("timestamp.txt");
char* text_stream;
std::string line;
if (infile.is_open()){
while ( getline (infile,line)){
if(text_stream){
*text_stream = malloc (1 + strlen (line));
strcpy(text_stream,line);
}
else{
fprintf (stderr, "malloc failure!");
}
}
infile.close();
}
I have also tried using other codes for the same purpose but I'm getting this kind of compilation error everytime:
verifiy.cpp: In function ‘int main()’:
verifiy.cpp:29:47: error: cannot convert ‘std::string {aka std::basic_string<char>}’ to ‘const char*’ for argument ‘1’ to ‘size_t strlen(const char*)’
*text_stream = malloc (1 + strlen (line));
^
verifiy.cpp:30:31: error: cannot convert ‘std::string {aka std::basic_string<char>}’ to ‘const char*’ for argument ‘2’ to ‘char* strcpy(char*, const char*)’
strcpy(text_stream,line);
^
BTW, if you are just reading the whole file, you can write something like this:
#include <string>
#include <fstream>
#include <streambuf>
std::ifstream t("timestamp.txt");
std::string str((std::istreambuf_iterator<char>(t)),
std::istreambuf_iterator<char>());
(If you care about the efficiency of the code above, there is a more efficient version here: Read whole ASCII file into C++ std::string)
That way, you don't need to create an explicit string buffer yourself. After that, you can just use str.c_str() to get a "const char*".
While using that, please beware that the resulting pointer can be invalid if you keep editing the string. In that case, you might need to make another copy of the string. If your function needs a "char*" instead of a "const char*", you might need to do that too. More information can be found here: How to convert string to char array in C++?
You actually have two errors in the code, first the one you show in your question (it's the same error in two different places), the second error is worse and will lead to undefined behavior.
The first error is that std::string is not a char*, so you can't use the old C functions with it. Reading this reference should help you a little.
The second problem is that text_stream is a pointer to char, meaning *text_stream will give you what text_stream points to, i.e. a single char, or text_stream[0]. This is problematic because of two reasons: The first because text_stream is uninitialized, its contents is indeterminate and dereferencing will not give you a valid pointer leading to undefined behavior. The second problem with that is that *text_stream is not a pointer, assigning to *text_stream will not change text_stream so text_stream will still be uninitialized while you overwrite some random memory. If the compiler doesn't shout warnings at you for this assignment, then you need to enable more warnings. Warnings from the compiler are just as important as compiler errors, and they often indicate places you do something which is not technically wrong but will lead to other problems when running the program.
The solution to both these problems is to stop using C function in C++. Use std::string exclusively, and when you need to call a function which needs a const char * argument, just use std::string::c_str to get such a pointer.

atoi and string array

I have a string array and an integer array. I want to convert the elements of string array to integer and then store them in the integer array. I wrote this code :
string yuzy[360];
int yuza[360];
for(int x = 0;x<360;x++)
{
if(yuzy[x].empty() == false)
{
yuza[x]=atoi(yuzy[x]);
cout<<yuza[x]<<endl;
}
else
continue;
}
this piece of code gives this error:
error: cannot convert 'std::string {aka std::basic_string}' to 'const char*' for argument '1' to 'int atoi(const char*)'
When I write the content of the string (-75dbm) in atoi function it works fine. But when I write (yuzy[x]), I get the error. How can I make atoi works well with string array?
Thanks.
atoi() takes C strings (char pointers) and not C++ string objects. Use
atoi(yuzy[x].c_str());
instead.
As an alternative to atoi, you could use std::stoi and related functions, if you have C++11 support.
yuza[x] = std::stoi(yuzy[x]);
atoi accept a c-style string as parametter, so, you could use atoi(yuzy[x].c_str());

what does skip procedure do?

i am trying to determine what does this code?
#include <cstdlib>
#include <iostream>
#include<string.h>
using namespace std;
char *skip(char *p,int n)
{
for (;n>0;p++)
if (*p==0) n--;
return p;
}
int main(int argc, char *argv[])
{
char *p="dedamiwa";
int n=4;
cout<<skip(p,n)<<endl;
}
When I run it om dev c++,it wrotes
`basic_string::copy`
When i run it on ideone.com,it wrotes
prog.cpp: In function ‘int main(int, char**)’:
prog.cpp:15: warning: deprecated conversion from string constant to ‘char*’
prog.cpp:18: warning: ignoring return value of ‘int system(const char*)’, declared with attribute warn_unused_result
It searches for a certain number of \0 (n number of \0). It is undefined behaviour because it goes after the end of the string.
For the const part, string literals are const in c++. In c they aren't but still they mustn't be modified otherwise you get an undefined behavior (often a crash) (so even in c it's normally better to declare them as const and live happy)
The reason of the result of basic_string::copy is that in your (compiler/implementation specific, but quite common) compiled program there is an area where all the constant strings are saved "together". So if you go after the end of one, you go to the beginning of another. So someplace in your executable there is something like:
dedamiwa\0something\0somethingelse\0somethingelseelse\0basic_string::copy
It interpret the first parameter as a pointer to an array of character containing at least n null characters, and return a pointer after the n-th such null-character. Per se, there is no undefined behavior if you pass correct input to it.
Since you pass a simple null terminated string, it has undefined behavior, as there is only one such null-character in its input. It will access memory after the end of the string.
Concerning the compilation errors, in C++ a constant string is of type const char*, not char*, and you should check the return of the system function for error.
It skips n characters of the char array.
It interpret the first parameter as a pointer to an array of character
containing at least n null characters, and return a pointer after the
n-th such null-character. Per se, there is no undefined behavior if
you pass correct input to it.
Since you pass a simple null terminated string, it has undefined
behavior, as there is only one such null-character in its input. It
will access memory after the end of the string.
Concerning the compilation errors, in C++ a constant string is of type
const char*, not char*, and you should check the return of the system
function for error. by -- Sylvain Defresne
A version of the code with explicit braces is maybe a little bit
more readable for you:
using namespace std;
char *skip(char *p,int n){
for (;n>0;p++)
if (*p==0) {
n--;
}
return p;
}
To get rid of the error:
int main(int argc, char *argv[])
{
// cast the string which is of the type const char* to the
// type of the defined variable(char*) will remove your warning.
char *p= (char*) "dedamiwa";
int n=4;
cout<<skip(p,n)<<endl;
}
The skip procedure is asking for a segfault.
Basically, it increments p until the next '\0' is found, and repeats that n times.
In the best case, nothing will be printed because '\0...' is an empty string for std::cout(std::ostream&, const char *).
In the worst case, there be nasal dragons, to quote comp.lang.c.