C++ Set value for a char** - c++

I'm trying to assign a value to a char** variable. In my foo.h I've defined a couple of variables such as
#define APIOCTET int
#define APILONG long
#define APICHAR char
#define APISTRING char*
Now in my foo.cpp I'm tryng to use a method where
APILONG apiInitialize(APISTRING filePath, APISTRING* outputString)
{
//open text file to where output will be printed
//do other stuff, etc..
//return result;
}
I'd like to assign a value to my APISTRING* outputString but I just can't figure out how to do so, I've tried many things which are basically a variation of the following code
APISTRING error = "error";
APISTRING other = "string";
APISTRING charArr[] = { error, other, error };
APISTRING *charArr2[] = { charArr };
errorString = *charArr2;
Also im not 100% clear on what exactly is APISTRING* outputString. When I try to compile it gives me an error message where it mentions it's a char**. Is it a 2D array?.. A pointer to an array of chars?.. But most importantly, how would I assign a value for this variable? Thanks in advance.

The APISTRING* is a pointer to a pointer to char. It holds an address which holds the address of the first character of the string in memory.
See this question for more info on double pointers in C/C++.
To assign to the string you would need to do *outputString = "string"

APISTRING* outputString will be pre-processed and replcaed at compile-time as char** outputstring. Hence, outputString will be double pointer hence, you need to do it like this (below code). I combined both .h and cpp together for simplicity.
#include<iostream>
using namespace std;
#define APIOCTET int
#define APILONG long
#define APICHAR char
#define APISTRING char*
APILONG apiInitialize(APISTRING filePath, APISTRING* outputString)
{
APISTRING getIt = *outputString;
cout<<" "<<getIt<<endl;
}
int main()
{
APISTRING str = "hello";
APISTRING* outputString = &str;
APILONG val = apiInitialize("world", outputString );
system("PAUSE");
return 0;
}
I would recommend to use std::string, it'll be easy to tweak with certain behaviors. Hope this helps.

Related

Return multiple strings from dll

we are having a discussion as what is a good way to return multiple strings from one dll function. Currently we have 8 strings, but there will be more. For simplicity I now consider all strings will have equal lengths.
extern "C" int DLLNAME_ _stdcall GetResult(TestResults* testResults);
where
struct TestResults
{
int stringLengths;
char* string1;
char* string2;
char* string3;
char* string4;
...
};
or second option: where
struct TestResults
{
int stringLengths;
char string1[64];
char string2[64];
char string3[64];
char string4[64];
...
};
third option:
extern "C" int DLLNAME_ _stdcall GetResult(int stringLengths, char* string1, char* string2, char* string3, ...);
The dll will communicate over a serial line and retrieve information that will be filled into the strings. Where the memory needs to be allocated is open for discussion and can be part of the answer.
The background is that we have a VB6 application team that prefers the second method and a C++/C# team that prefers the first method. Last method looks to suit both teams but looks a bit strange to me with so many parameters.
Maybe there are more options. What is common practice under Windows? Any examples from the Windows API or arguments to choose one over the other?
Edit: The strings have a meaning as in first name, last name, email. We currently have eight, but in the future we might add a couple for example for address. An array would not be the correct choice for this, but that was not clear from the original context.
The best way is probably using a safe array storing BSTR strings.
Both VB and C# understand safe arrays very well: in C#, a safe array of BSTR strings is automatically converted to a string[] array.
On the C++ side, you can use the ATL::CComSafeArray helper class to simplify safe array programming.
You will find interesting material in this MSDN Magazine article (in particular, take a look at the paragraph Producing a Safe Array of Strings).
From the aforementioned article: On the C++ side, you can implement a C-interface DLL, exporting a function like this:
extern "C" HRESULT MyDllGetStrings(/* [out] */ SAFEARRAY** ppsa)
{
try {
// Create a SAFEARRAY containing 'count' BSTR strings
CComSafeArray<BSTR> sa(count);
for (LONG i = 0; i < count; i++) {
// Use ATL::CComBSTR to safely wrap BSTR strings in C++
CComBSTR bstr = /* your string, may build from std::wstring or CString */ ;
// Move the the BSTR string into the safe array
HRESULT hr = sa.SetAt(i, bstr.Detach(), FALSE);
if (FAILED(hr)) {
// Error...
return hr;
}
}
// Return ("move") the safe array to the caller
// as an output parameter (SAFEARRAY **ppsa)
*ppsa = sa.Detach();
} catch (const CAtlException& e) {
// Convert ATL exceptions to HRESULTs
return e;
}
// All right
return S_OK;
}
On the C# side, you can use this PInvoke declaration:
[DllImport("MyDll.dll", PreserveSig = false)]
public static extern void MyDllGetStrings(
[Out, MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_BSTR)]
out string[] result);
As you declare your function as extern "C" I suppose that you cannot use std::vector<std::string> as return type.
Another possibility would be:
struct String
{
int size; /* size of string */
const char* str; /* actual string */
}
struct TestResults
{
int size; /* number of strings */
String* arr; /* pointer to an array of String */
};
and then the same as before:
extern "C" int DLLNAME_ _stdcall GetResult(TestResults* testResults);
With that you are flexible to return as much strings as you like. Also loop through your TestResults is easy.
Edit #1: As said in the comments: use BSTR. So your struct would look like:
struct TestResults
{
int size; /* number of strings */
BSTR* arr; /* pointer to an array of BSTR */
};
A BSTR will be allocated by: BSTR MyBstr = SysAllocString(L"I am a happy BSTR");. This allocation also sets the member which contain the length of the string. You have to free the allocated memory with: SysFreeString(MyBstr);. Also you need to allocate the whole array BSTR*.

c++ error: assigning to 'char *' from incompatible type 'const char *'

I am having trouble with a programming assignment for my c++ class and I am not sure how I should be doing this to not get an error. I am pretty new to programming, so this will probably be really easy.
In my instructions, we have to create a class to work with other code that is given to us with some guidelines. I have three files: program.h, program.cpp, and main.cpp.
program.h
//program.h
#include <iostream>
#include <stdint.h>\\This program uses type uint32_t so had to include this
#include <cstdlib>
class Program
{
public:
Program(); //was told to create a default constructor to initiate values if none are given
Program(char *, uint32_t, float); //was told to create an overloaded default constructor to change variables in program
void SetName ( const char* ); //given by the professor
//other function prototypes are here but they are working fine.
private:
char * name_; //given by professor
uint32_t code_;//given by professor
float cost_;//given by professor
};
program.cpp
//program.cpp
//other functions from class are in this file, just not giving any issues
Program::Program(char * name,uint32_t code, float cost) : name_(name), code_(code), cost_(cost)
{
}
Program::Program() : name_(NULL), code_(0x00000000), cost_(0.0)
{
}
void Program::SetName(const char* name)
{
name_= name; //where the issue appears to occur since name is a const char *
}
currently trying to compile program.o using makefile and program.h program.cpp so the main.cpp does not matter. When i try to compile, i receive the following error:
clang++ -oprogram.h program.cpp
program.cpp:17:9: error: assigning to 'char *' from incompatible type 'const char *'
name_ = name;
Since the function was void SetName (const char*); was given by the professor and has to be used. I am not sure how to fix this error since the variable char * name_; was also given to us by the professor. Pointers still confuse me some, but any help would be greatly appreciated. I always thought that constant data can be passed to nonconstant data but not vise versa.
Important point just to get this out of the way:
char * name_;
Defines a pointer to a character. This just makes a pointer. It does not make a character. You will need to provide the character that is pointed at later. This pointer can be used to change the memory at which it points.
const char* name
Defines a pointer to a character that cannot be changed.
A value that cannot be changed is fundamentally different from a value that can be changed. You can copy the unchangeable value into the changable, but you cannot do the reverse because that would require changing the unchangeable value.
A pointer that can be used to change a value cannot be pointed at an unchangeable value to prevent the obvious problem of using the pointer to attempt to change the value.
What you need to do is copy.
But first, you need to allocate storage to hold the copy. This should be covered by your text, leaving one problem: How much storage is needed?
First, you have to know what a string is and how they are represented in C. Not C++, but C. C++ does it a little bit differently and your professor will get to that eventually. I hope. God, I really hope. In the meantime, the professor has you working with C-style strings.
strlen solves the how much storage problem, mostly. strlen will tell you the length of a properly formatted string of characters. What it doesn't tell you is implied by the definition of a character string. Hope you read the link.
Now that you know how much storage you need, you allocate the storage with new.
Now that you have a name_ pointing to enough storage, you can copy from the constant memory at name into it. strcpy should be helpful here.
This is wonderful, but leave you with a small problem: what if there already was storage at _name? Shucks. We just overwrote the pointer to it. This is called a memory leak and is no small part of why C++ does strings differently.
OK, so before allocating storage for name_and copying the storage at name into it, first you need to test to make sure name_ is empty. Couple of ways to do this:
Set a canary value. A canary is an impossible value; something that you will never see. Typically for pointers we use NULL, a glorified 0. There is nothing at address zero by convention, so if you see a pointer pointing to zero something is up. If in the constructor you make sure that name_ is NULL, you will have an easy way to know if name_ isn't pointing at data yet.
Keep a length value and set it to zero in the constructor. If the length is zero, there's nothing there. As an added bonus since this allow you to know the length of your storage, you can compare it to the amount of storage needed by the new string. If the new string is the same size or smaller, you can write over the old string.
If you need to replace name_'s storage, delete[] the old storage before allocating new storage.
Putting it all together, and using option 2 because it's better, you get:
int len = strlen(name)
if len > length_
delete name_
name_ = new storage
strcpy(name_, name)
Note there are a few pieces missing you'll have to fill out.
And just to be an ass, this is what all that would look like with C++ strings:
name_ = name;
Look familiar? Aren't you glad your professor decided to teach you to program in C++ the worst, hardest way first?
There may be some typos. You have space in
#include < iostream >
Remove the space
#include <iostream>
Change char to
const char * name_;
Add semicolon after the last } in the Program class definition.
Example on the code:
main.cpp
#include <iostream>
#include "program.h"
using namespace std;
int main(int argc, char const *argv[]) {
cout << "Hello, World!" << endl;
char const * name = "Claus";
uint32_t code = 1967;
float cost (3.14f);
Program p (name, code, cost);
cout << "getName(): " << p.getName() << endl;
return 0;
}
program.cpp
#include "program.h"
Program::Program() {};
Program::~Program() {};
Program::Program(char const * name,uint32_t code, float cost) : name_(name), code_(code), cost_(cost) {}
void Program::SetName(const char* name) {
name_= name; //where the issue appears to occur since name is a const char *
}
char const* Program::getName() {
return name_;
}
program.h
#ifndef PROGRAM_H
#define PROGRAM_H
#include <stdint.h>
class Program {
public:
Program(); //was told to create a default constructor to initiate values if none are given
~Program();
Program(const char * , uint32_t, float); //was told to create an overloaded default constructor to change variables in program
void SetName (const char* );
const char* getName();
private:
const char * name_;
unsigned int code_;
float cost_;
};
#endif // PROGRAM_H
On my mac I compile it with
clang++ -std=c++11 -Wall -o main main.cpp program.cpp
I get warning about unused variables but that's OK.
I was inspired by user4581301's response to learn a bit C. C++ does alleviate it alot.
In program.cpp
Program::Program(char * name, uint32_t code, float cost) {
unsigned int len = strlen(name);
name_ = new char[len];
strcpy(name_, name);
code_ = code;
cost_ = cost;
}
void Program::SetName(const char* name) {
unsigned int len = strlen(name);
delete name_;
name_ = new char[len];
strcpy(name_, name);
}
This link helped me as well: how to initialize a char pointer in a class?
regards
Claus

storing system time to a variable in cpp

I want to save the local time to a char variable. here is the code i have used. but it is saying
"cannot convert char * to char"
Here is my code:
#include <stdio.h>
#include <time.h>
struct tme
{
char intime;
}e;
void main( )
{
char timeStr [9];
_strtime( timeStr );
e.intime=timeStr;
printf( "The current time is %s \n", timeStr);
}
Thanx in advance.
That's simple, you have a char array timeStr of length 9 and trying to assign it to a char intime. There's type incompatibility. Think of it as char[] is never equal to char.
You could solve this as follows (but I don't know what you want to achieve):
struct tme
{
char* intime;
}e;
PS: MSDN states that (_strtime):
// Note: _strtime is deprecated; consider using _strtime_s instead
e.intime=timeStr;
timeStr is of type char [9]. It decays to a pointer pointing to first element during assignments or in a function call used as a parameter.
e.intime is of type char. char and char* aren't type compatible and the compiler is complaining you that. Instead you can do -
struct tme
{
char intime[10]; // +1 for the termination character to play safe
}e;
Now, strcpy can be used to copy the time to the member variable.
strcpy(e.intime, timeStr);
If it is C++, use std::string instead of raw arrays.
Some stages of refinement:
Stage 1: Fix your code.
struct tme {
char * intime; // You had a type mismatch
} e;
int main () { // Don't use void main()
char timeStr [9];
_strtime( timeStr );
e.intime=timeStr;
printf( "The current time is %s \n", timeStr);
}
There's a problem here: Your struct tme is relying on the external world to do everything for it, and to do so correctly. What if we want to reuse timeStr in main? What if you use this structure in a function other than main and set e.intime to a variable that goes out of scope?
Refinement: struct tme should own the time buffer.
struct tme {
char intime[9]; // Put the buffer here, not in main.
} e;
int main () {
_strtime( e.intime );
printf( "The current time is %s \n", e.intime);
}
We still have a problem here. That buffer can be modified by anyone, and the structure is just a passive receptacle.
Refinement: Hide the data and make the object active.
struct tme {
const char * set_time () { _strtime (intime); return intime; }
const char * get_time () const { return intime; }
private:
char intime[9];
};
int main () {
printf( "The current time is %s \n", e.set_time());
}

C++: Define simple constant for use?

In C++ I wanted to define a constant that I can use in another function, A short answer on how to do this will be fine..
Lets say at the beginning of my code I want to define this constant:
//After #includes
bool OS = 1; //1 = linux
if (OS) {
const ??? = "clear";
} else {
const ??? = "cls";
}
I don't know what type to use to define the "clear" string... I'm so confused.
Later on I want to use it within a function:
int foo() {
system(::cls); //:: for global
return 0;
}
How would I define the string up top, and use the string down below? I heard char only had one character and things... I'm not sure how to use , since it says it's converting string into const char or something.
char* isn't quite a char. char* is basically a string (it's what strings were before C++ came along).
For illustration:
int array[N]; // An array of N ints.
char str[N]; // An array of N chars, which is also (loosely) called a string.
char[] degrades to char*, so you'll often see functions take a char*.
To convert std::string to const char*, you can simply call:
std::string s;
s.c_str()
In this case, it's common to use the preprocessor to define your OS. This way you can use the compiler to do the platform specific stuff:
#ifdef OS_LINUX
const char cls[] = "clear";
#elif OS_WIN
const char cls[] = "cls";
#endif
One thing you may want to consider is making it a function. This avoids nasty dependencies of global construction order.
string GetClearCommand() {
if (OS == "LINUX") {
return "clear";
} else if (OS == "WIN") {
return "cls";
}
FAIL("No OS specified?");
return "";
}
What it looks like you're trying to do is this:
#include <iostream>
using namespace std;
#ifdef LINUX
const char cls[] = "LINUX_CLEAR";
#elif WIN
const char cls[] = "WIN_CLEAR";
#else
const char cls[] = "OTHER_CLEAR";
#endif
void fake_system(const char* arg) {
std::cout << "fake_system: " << arg << std::endl;
}
int main(int argc, char** argv) {
fake_system(cls);
return 0;
}
// Then build the program passing your OS parameter.
$ g++ -DLINUX clear.cc -o clear
$ ./clear
fake_system: LINUX_CLEAR
Here's the problem, you're suffering from going out of scope with the variables. If I declare something within brackets, it only exists within the brackets.
if( foo ){
const char* blah = "blah";
}
Once we leave the if statement, the variable blah disappears. You'll need to instantiate it non-locally to whatever brackets you write. Hence:
void Bar(){
const char* blah = "blah";
if( foo ){
//blah exists within here
}
}
However, blah will not exist outside of Bar. Get it?
Yet another option is to create a class with a bunch of static methods. Create a new method for each command. Something like:
// in sys-commands.h
class SystemCommands {
public:
static char const* clear();
static char const* remove();
};
This gives you a few nice options for the implementation. The nicest one is to have a separate implementation file for each platform that you select during compile time.
// in sys-commands-win32.cpp
#include "sys-commands.h"
char const* SystemCommands::clear() { return "cls"; }
char const* SystemCommands::remove() { return "erase /f/q"; }
// in sys-commands-macosx.cpp
#include "sys-commands.h"
char const* SystemCommands::clear() { return "/usr/bin/clear"; }
char const* SystemCommands::remove() { return "/bin/rm -fr"; }
Which file gets compiled will determine which command set will be used. Your application code will look like:
#include <cstdlib>
#include "sys-commands.h"
int main() {
std::system(SystemCommands::clear());
return 0;
}
Edit: I forgot to mention that I prefer static functions to global constants for a bunch of reasons. If nothing else, you can make them non-constant without changing their types - in other words, if you ever have to select the command set based on runtime settings, the user code does not have to change or even be aware that such a change occurred.
You can use a common header file and link to different modules depending on the systen:
// systemconstants.hpp
#ifndef SYSTEM_CONSTANTS_HPP_INCLUDED
#define SYSTEM_CONSTANTS_HPP_INCLUDED
namespace constants {
extern const char cls[]; // declaration of cls with incomplete type
}
#endif
In case of Linux, just compile and link to this one:
// linux/systemconstants.cpp
#include "systemconstants.hpp"
namespace constants {
extern const char cls[] = "clear";
}
In case of Windows, just compile and link to this one:
// windows/systemconstants.cpp
#include "systemconstants.hpp"
namespace constants {
extern const char cls[] = "cls";
}
System-specific translation units could be placed in specific subdirectories (linux/, windows/, etc) of which one could be automatically selected during the build process. This extends to many other things, not just string constants.

C++ : error: invalid operands of types ‘String*’ and ‘const char [7]’ to binary ‘operator+’

I'm learning cpp and In my last assignment I am rewriting the std::string class.
so here is an outline of my code:
string class:
class String {
public:
String(const char* sInput) {
string = const_cast<char*> (sInput);
}
const String operator+(const char* str) {
//snip
print();
}
void print() {
cout<<string;
}
int search(char* str) {
}
private:
char* string;
int len;
};
Oh and I have to say I tried to declare the method as String* operator+(const char* str) and as const String& operator+(const char* str) with no change.
And here is how I run it:
int main(int argc, char* argv[]) {
String* testing = new String("Hello, "); //works
testing->print();//works
/*String* a = */testing+"World!";//Error here.
return 0;
}
The full error goes like such:
foobar.cc:13: error: invalid operands
of types ‘String*’ and ‘const char
[7]’ to binary ‘operator+’
I looked up on Google and in the book I am learning from with no success.
any one with suggestions? (I am pretty sure I am doing something foolish you will have to forgive me I am originally a PHP programmer) can any one point me to what am I missing?
You probably don't want to use a pointer to your String class. Try this code:
int main(int argc, char* argv[]) {
String testing = String("Hello, "); //works
testing.print();//works
String a = testing+"World!";
return 0;
}
When defining new operators for C++ types, you generally will work with the actual type directly, and not a pointer to your type. C++ objects allocated like the above (as String testing) are allocated on the stack (lives until the end of the "scope" or function) instead of the heap (lives until the end of your program).
If you really want to use pointers to your type, you would modify the last line like this:
String *a = new String(*testing + "World!");
However, following the example of std::string this is not how you would normally want to use such a string class.
Your operator+ is defined for String and const* char, not for String*. You should dereference testing before adding it, i.e.:
String a = (*testing) + "World";
Though in this case I don't see the point in making testing a pointer in the fist place.
Edit: Creating a string without pointers would look like this:
String testing = "Hello, ";
or
String testing("Hello, ");
(both are equivalent).