MoveFileA() doesn't like my arguments [duplicate] - c++

This question already has answers here:
How to convert std::string to LPCSTR?
(9 answers)
Closed 8 years ago.
I have a list of file names in a .txt document, and I would like to move each of these files from one folder to another.
Using MoveFileA() I am getting the error, "no suitable conversion between std::string and LCPSTR".
Here is my code, after opening up my .txt file:
while (std::getline(myfile, line))
{
std::string oldLocation = "C:\\Users\\name\\Desktop\\docs\\folder1\\" + line;
std::string newLocation = "C:\\Users\\name\\Desktop\\docs\\folder2\\" + line;
MoveFileA(oldLocation, newLocation);
}
If I type in the full path as arguments for MoveFileA, instead of sending it a variable, it works but I am unable to iterate over .txt file this way.
Any suggestions on how I might fix this?

LCPSTR means long constant pointer to a string, which means it's a null terminated c string.
std::string is an object. It is something different. But it luckily provides a convenience method c_str the provides a pointer to a constant c style string. So as the comment says you should go by:
MoveFileA(oldLocation.c_str(), newLocation.c_str());
It is worth of explicitly noting, that you can't drop it in every place instead of char*, but only when the string won't be modified. It returns const char*. This is where the C in LCPSTR gets important.

Related

Defining a character array in header file in C++

I am working on a project where a question is displayed in a game window.
Since this question will need to change a lot, I figure it would be easier to have 5 defined lines of text (1 for question, 4 for MC answers) that are simply edited every time the question changes.
I have tried this in the header file:
struct tagQuestion{
int x, y;
const char* qLine[150];
char ansA[150];
char ansB[150];
char ansC[150];
char ansD[150];
}question[1];
then in my main.cpp
question.qLine[150] = "TEST PHRASE";
but it is returning the error "qLine" in "question", which is of non-class type "tagQuestion[1]"
I have tried both char and const char* to no success.
I am trying to follow an example in my textbook and I think I'm misunderstanding it.
Once I declare the character array in the header file, can't I edit its contents in the main file?
That [1] after question doesn't seem to be making any sense. Remove it.
Your answers are arrays of char, but your question is an array of char pointers. I am pretty sure you don't want your question to consist of 150 char pointers.
If you want to change qLine, don't make it const.
qLine[150] = ... This assigns a value to the 151st element of an array with 150 elements. Neither what you want, nor legal code. You probably want qLine =, but that doesn't work with an array, instead you need to use a function like strcpy that writes data into the array, but I highly advise against that. (see next point)
Don't do C in C++. Use std::string, not arrays of char.
If you have strings that regularly change, create a file where your strings are stored, load them into a map, and pull them from the map wherever and whenever you need them, instead of putting hardcoded strings in your code. That way you don't need to change any code, when you change text.
I suggest something like this:
struct Question {
std::string text;
std::vector<std::string> answers;
};
std::map<std::string, Question> questions;
And then something like this:
ifstream questionsFile("questions.txt");
if (questionsFile.is_open())
{
std::string line;
while (std::getline(questionsFile, line))
{
// Split line into some id, text and answers, how exactly depends on the format you chose
std::string id = ...;
Question question;
question.text = ...;
question.answers.push_back(...);
questions[id] = question;
}
questionsFile.close();
}
else
{
// Handle error
}
And wherever in your code:
// Print question with id "q1":
std::cout << questions["q1"].text << std::endl;
// Print answer #2 for question with id "q1":
std::cout << questions["q1"].answers[1] << std::endl;
Even better would be to make Question a class that hides its internals and has accessor methods and a constructor or static method to create new instances from valid lines with proper error handling.

C++: Safe reading from file with std::string (&str[0]) as a buffer? [duplicate]

This question already has an answer here:
Is writing to &str[0] buffer (of a std:string) well-defined behaviour in C++11?
(1 answer)
Closed 7 years ago.
I have a binary file that I'm reading from. In the file at one point, there is a known number of bytes which make up a simple ASCII string (possibly with newlines). Right now I have:
void doSomething(istream &in) {
vector<char> buf(length + 1, '\0');
in.read(&buf[0], length);
string str(&buf[0]);
}
But I realized that it would probably be faster to do
void doSomething(istream &in) {
string str(length + 1, '\0'); // +1 needed?
in.read(&str[0], length);
}
I tried looking in the standard to see if string allocation is always sequential or if it's safe doing something like this. Safe meaning, no accidental reading into (writing to) memory not part of the string. Does anyone know?
std::string allocation is always sequential, at least as of C++11. I believe prior to that it wasn't clearly defined so, but no implementations used non-sequential storage.
You do not need to explicitly add space for a null terminator in std::string.

Converting char* to int and converting back to the same char array [duplicate]

This question already has answers here:
Why do I get a segmentation fault when writing to a "char *s" initialized with a string literal, but not "char s[]"?
(19 answers)
Why can't I write to a string literal while I *can* write to a string object?
(4 answers)
Is it possible to modify a string of char in C?
(9 answers)
Closed 8 years ago.
Basically, I am trying to increment the int value of port. This should be easy but I am a little stuck.
It compile fine, but I got this error when I run it:
Access violation writing location 0x001f5834
#include "stdafx.h"
#include "iostream"
using namespace std;
#define TESTING "5002"
int main()
{
char* port = TESTING;
int portint;
sscanf ( port, "%d", &portint );
portint++;
cout << portint << endl; // it works fine up to here, it prints 5003
sprintf ( port, "%d", portint);
return 0;
}
By default, compiler treats string literals as immutable, and an attempt to modify the contents of one results in an access violation error at run time because these strings are put into code segment, and it's read only. In your case, TESTING is a string literal, you can't not change its values. Try:
char port[] = "5002";
Meanwhile, the compiler should have warning on this: when you assign a const char* type to a char* type.
MS C++ compiler has a compiler option regards this: Zc:strictStrings.
You are trying to write "5003" back into "5002". "5002" is a string literal and cannot be written to.
I'll try to find a good duplicate for this question, because it has been asked in many ways, many times.
In your usage, "5002" becomes a static array of characters and as such can not be modified. I believe K&R address this, but I don't have the book in front of me right now. Behavior would be different if you had declared an array.

convert integer to string for function parameter [duplicate]

This question already has answers here:
Easiest way to convert int to string in C++
(30 answers)
How to convert a number to string and vice versa in C++
(5 answers)
Closed 10 years ago.
I have a function which accept a string parameter and I have an integer variable then I should convert it to string and then pass it to that function I used this code but as ostringstream is for I/O it doesn't work.
ostringstream ostr;
while (.....)
{
regnum++;
ostr<<regnum;
grph.addlastname(ostr.str());
}
for example it pass 12345 to function instead of 5,what should I do?
It's true - there are a lot of similar questions which solve "What's the best way to do this?" but I think that there's something to learn for the OP in the answer to the question of "Why does this not work?"
Therefore:
Your stringstream has an internal state, and during your loop you always append a new digit - but the previous ones are still in the stream! You can fix this by making the stringstream scope-local to the loop, i.e. declaring it inside the loop rather than outside of it.
(std::to_string is still the better solution for this particular problem, though.)
Everything is fine except one thing,
see:
ostringstream ostr;
while (.....)
{
regnum++;
ostr<<regnum;
grph.addlastname(ostr.str());
}
Your declaring your ostr outside the while, the first time that while runs, it adds '1' to the ostr, the second time, because it's the same "ostringstream" variable, it adds '2', so your string will be '12' now...
Solution: Declare ostringstream ostr, inside your while, use std::to_string, or do a ostr.clear() every time that the while ends. (The best way si declaring your ostr inside your while)

SWIG Python and C++ std::string null-termination problem [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How Python can get binary data(char*) from C++ by SWIG?
I have a SWIG based C++ interface that can called from Python. There is a function in it, that has one std::string argument. It looks like this:
WrapperGet(const std::string& key);
If it is called from Python with a string argument that contains NUL character (e.g. binary data), then the std::string is truncated at the NUL character, and that is my problem, because it makes impossible to handle binary data.
What makes it interesting is that other way works perfectly:
std::string WrapperResult();
The string returned here can contain binary data without truncation. Has anybody any idea what has to be done?
UPDATE: I debugged the SWIG generated code and it turned out that the error was in the wrapper code on the C++ size: it used the c_str() member function of the std::string to get the string value.
Thanks for everybody's ideas and time!
I've had to deal with this in the past, and I just grabbed the std::string conversion template from SWIG and tailored it a bit to use PyString_FromStringAndSize when creating a Python string from a std::string and the std::string constructor that accepts a size argument when going the other way.
That was with a really old version of SWIG, though - I thought the builtin conversion template in newer versions had been updated to do that automatically. Is it possible the problem is on the C++ side? (e.g. as in Mark Tolonen's examples, where the first example is truncated due to the embedded NULL in the constructor call without a size argument).
It is probably how the strings are constructed. Consider:
string blah(const string& x)
{
string y("abc\x00def");
return x + y;
}
string blah2(const string& x)
{
string y("abc\x00def",7);
return x + y;
}
Calling these from Python:
>>> import x
>>> x.blah('abc\x00def')
'abc\x00defabc'
>>> x.blah2('abc\x00def')
'abc\x00defabc\x00xyz'
The constructor for std::string(const char*) stops at the NULL, but clearly SWIG can pass in and return strings with a NULL in them.