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.
Related
I compiled .cc file whith g++ on linux ubuntu, I want to use srtcmp() function to compare two strings. the strings are not constant. user will give both of them, but I get this error:
error: invalid conversion from ‘char’ to ‘const char*’ [-fpermissive]
and this is my code:
if (!strcmp(a[i].personalNo,pcode)){
#some code
}
which function can I use instead of strcmp() to compare two strings?
The problem isn't on the function but on the way that you're using it.
int strcmp ( const char * str1, const char * str2 );
strcmp takes two const char * arguments.
The error tells you that you are giving the function a char so the problem is on the types of personalNo and/or pcode. Your mistake is probably on the declaration of the type of those two variables. You would want to change their type to char * as char only stores one character while char * is an array of characters.
Also, an another way to compare two strings in C++ is to use std::string. Then you can just do the following (provided that both personalNo and pcode are std::string:
if (a[i].personalNo != pcode){
#some code
}
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.
I'm using a function to download a file.
void downloadFile(const char* url, const char* fname) {
//..
}
This is called like :
downloadFile("http://servera.com/file.txt", "/user/tmp/file.txt");
This working fine.
But I want to change the URL to be a value from an array. The array stores encrypted values which when decrypted are strings, so I get the issue error: cannot convert ‘std::basic_string<char>’ to ‘const char*’
I've tried:
string test = decode(foo[5]);
const char* t1= test.c_str();
downloadFile(t1 "filename.txt", "/user/tmp/file.txt");
downloadFile(t1 + "filename.txt", "/user/tmp/file.txt");
and
downloadFile((decode(foo[5]).c_str()) + "filename.txt", "/user/tmp/file.txt");
which gives:
error: invalid operands of types ‘const char*’ and ‘const char [17]’ to binary ‘operator+’
What am I doing wrong ?
Thanks
C-strings can't be concatenated with +.
Use std::string::+ instead:
downloadFile((test + "filename.txt").c_str(), "/user/tmp/file.txt");
Note that c_str only returns a pointer to the std::string's internal character array, so it's valid only during the execution of the downloadFile function.
Try this:
downloadFile((decode(foo[5]) + "filename.txt").c_str(), "/user/tmp/file.txt");
The operator+ is not defined for char arrays.
The main problem in your code is that you are trying to use operator+ to concatenate raw C strings (i.e. raw const char* pointers, or raw char [] arrays), which doesn't work.
In C, you should use proper library functions (like strncat or safer variants) to do that; but since you are using C++, you can do better, and write easier code: just use a C++ string class, like std::string.
In fact, the C++ standard library offers convenient overloads for operator+ that work with std::string, so you can concatenate C++ strings in an easy, intuitive and safe way; for example:
// Build your URL string
std::string test = decode(foo[5]);
std::string url = test + "filename.txt";
// Use std::string::c_str() to convert from C++ string
// to C raw string pointer const char*
downloadFile(url.c_str(), "/user/tmp/file.txt");
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
I get the following error when this code is run:
syslog(LOG_ERR | LOG_USER, "%s",errorString);
cannot convert ‘const string {aka const std::basic_string}’ to ‘const char*’ for >argument ‘2’ to ‘void syslog(int, const char*, ...)’ inServer.cpp /PeCounter
line 478 C/C++ Problem
I am daemonizing the program and the errorString value prints just fine when outputted to stdio using cout, but it will not print when using a syslog call.
Any way to get std::basic_string(char) into the form of 'const char'.
I found that std::basic_string has an item access method c_str() which seems to fix the compiling issue.
Here is a site with more information: http://en.cppreference.com/w/cpp/string/basic_string
The c_str() or data() member function provides a pointer to the first element of an array of char_type which contains your string. It's valid as long as the string object itself remains valid and unchanged (but beware that operations that may cause reallocations may invalidate the pointer -- best not to store it).