How to define an array of strings in C++/CLI? - visual-studio-2010

What's wrong in this:
i'm getting these errors for all the 5 definitions:
error C3698: 'System::String ^' : cannot use this type as argument of 'gcnew'
error C2512: 'System::String::String' : no appropriate default constructor available
array<String^>^ arr = gcnew array<String^>
{
gcnew String^ "Madam I'm Adam.",
gcnew String^ "Don't cry for me,Marge and Tina.", //error C2143: syntax error : missing '}' before 'string' AND error C2143: syntax error : missing ';' before 'string'
gcnew String^ "Lid off a daffodil.",
gcnew String^ "Red lost Soldier.",
gcnew String^ "Cigar? Toss it in a can. It is so tragic."
}

You should not use gcnew inside the array initializer:
array<String^>^ arr = gcnew array<String^> {
"Madam I'm Adam.",
"Don't cry for me,Marge and Tina.",
"Lid off a daffodil.",
"Red lost Soldier.",
"Cigar? Toss it in a can. It is so tragic."
};

The other answerer has the correct syntax, but it's not because you're in an array initializer.
There's two errors with your string initialization.
When using gcnew, you don't need to include the ^. You're
constructing a new object, not a new reference.
You need parentheses when calling the constructor.
So the proper constructor syntax would be to call gcnew String("Madam I'm Adam.").
However, as other answerer noted, you don't need to do that. The string literal is already a String object, so you can remove the call to the constructor and just use the string literal directly. This is the same as calling new String("Madam I'm Adam.") in C#: It's already a string object, calling new String is redundant.

Related

Explicit unique Handle Modern c++

I am following along a course about modern C++. I get an error with explicit unique_handle function. It says m_value is unknown override specifier? I listed the value above it shows still be in variable space.
explicit unique_handle(pointer value = Traits::invalid()) throw()
m_value { value }
{
}
https://pastebin.com/MA4vnWR3
You are missing a colon ':' before m_value, which denotes the start of the inializer list:
explicit unique_handle(pointer value = Traits::invalid()) throw()
: m_value { value }
{
}

unable to use optional int "possibleNumber" in optional binding

I'm new to Swift and is trying to learn the concept of optional binding. I have came up with the following code:
let possibleNumber = Int("123")
possibleNumber.dynamicType
if let actualNumber = Int(possibleNumber){
print("\(possibleNumber) has an integer value of \(actualNumber)")
} else {
print("\(possibleNumber) could not be converted to an int")
}
Xcode playground output error message:
value of optional type "int?" not unwrapped, did you mean to use "!" or "?"
However, when I added the "!" to if let actualNumber = Int(possibleNumber!){
let possibleNumber = Int("123")
possibleNumber.dynamicType
if let actualNumber = Int(possibleNumber!){
print("\(possibleNumber) has an integer value of \(actualNumber)")
} else {
print("\(possibleNumber) could not be converted to an int")
}
Xcode display another error message:
initialiser for conditional binding must have Optional type, not int
Why is this happening?
The result of
let possibleNumber = Int("123")
is an optional Int - Int?
Then you're trying to create another Int with
Int(possibleNumber)
which does not work because the initializer expects a non-optional type.
The error message is related to the initializer rather than to the optional binding.
Try this to get the same error message.
let possibleNumber = Int("123")
let x = Int(possibleNumber)
In your second example when you initialize an Int with an implicit unwrapped Int! argument you get a non-optional Int and the compiler complains about the missing optional.
In the if let construct
if let actualNumber = Int(possibleNumber!){
print("\(possibleNumber) has an integer value of \(actualNumber)")
}
you don't need to use the Int initializer. You simply need to write
if let actualNumber = possibleNumber {
print("\(possibleNumber) has an integer value of \(actualNumber)")
}
Now Swift will try to unwrap possibleNumber. If the operation does succeed the unwrapped value is put inside actualNumber and the THEN block executed.

How to detect snprintf failure?

I am using snprintf to format string using user-defined format (also given as string). The code looks like this:
void DataPoint::valueReceived( QVariant value ) {
// Get the formating QVariant, which is only considered valid if it's string
QVariant format = this->property("format");
if( format.isValid() && format.type()==QMetaType::QString && !format.isNull() ) {
// Convert QString to std string
const std::string formatStr = format.toString().toStdString();
LOGMTRTTIINFO(pointName<<"="<<value.toString().toUtf8().constData()<<"=>"<<formatStr<<"["<<formatStr.length()<<'\n');
// The attempt to catch exceptions caused by invalid formating string
try {
if( value.type() == QMetaType::QString ) {
// Treat value as string (values are allways ASCII)
const std::string array = value.toString().toStdString();
const char* data = (char*)array.c_str();
// Assume no more than 10 characters are added during formating.
char* result = (char*)calloc(array.length()+10, sizeof(char));
snprintf(result, array.length()+10, formatStr.c_str(), data);
value = result;
}
// If not string, then it's a number.
else {
double data = value.toDouble();
char* result = (char*)calloc(30, sizeof(char));
// Even 15 characters is already longer than largest number you can make any sense of
snprintf(result, 30, formatStr.c_str(), data);
LOGMTRTTIINFO(pointName<<"="<<data<<"=>"<<formatStr<<"["<<formatStr.length()<<"]=>"<<result<<'\n');
value = result;
}
} catch(...) {
LOGMTRTTIERR("Format error in "<<pointName<<'\n');
}
}
ui->value->setText(value.toString());
}
As you can see I assumed there will be some exception. But there's not, invalid formatting string results in gibberish. This is what I get if I try to format double using %s:
So is there a way to detect that invalid formatting option was selected, such as formatting number as string or vice-versa? And what if totally invalid formatting string is given?
You ask if it's possible to detect format/argument mismatch at run-time, right? Then the short and only answer is no.
To expand on that "no" it's because Variable-argument functions (functions using the ellipsis ...) have no kind of type-safety. The compiler will convert some types of arguments to others (e.g. char or short will be converted to int, float will be converted to double), and if you use a literal string for the format some compilers will be able to parse the string and check the arguments you pass.
However since you pass a variable string, that can change at run-time, the compiler have no possibility for any kind of compile-time checking, and the function must trust that the format string passed is using the correct formatting for the arguments passed. If it's not then you have undefined behavior.
It should be noted that snprintf might not actually fail when being passed mismatching format specifier and argument value.
For example if using the %d format to print an int value, but then passing a double value, the snprintf would happily extract sizeof(int) bytes from the double value, and interpret it as an int value. The value printed will be quite unexpected, but there won't be a "failure" as such. Only undefined behavior (as mentioned above).
Thus it's not really possible to detect such errors or problems at all. At least not through the code. This is something that needs proper testing and code-review to catch.
What happens when snprintf fails? When snprintf fails, POSIX requires that errno is set:
If an output error was encountered, these functions shall return a negative value and set errno to indicate the error.
Also you can find some relevant information regarding how to handle snprintf failures Here.

constructor input error in VC++

I create a constructor as follow
Form1(array<System::String ^> ^args) //HW5
{
InitializeComponent();
//
//TODO: Add the constructor code here
//
if (args->Length==0){
CregArray = gcnew array<CRegistration^>(100);
record_number = 0;
}
else {
}
}
After that I use a line of code to create the constructor. Basically, I want to use the case of length==0, but the compiler said there is an error. I don't understand what the compiler means.
Application::Run(gcnew Form1(""));
The error is "Error 1 error C2664: 'Project3::Form1::Form1(cli::array ^)' : cannot convert parameter 1 from 'const char [1]' to 'cli::array ^'
You are passing in a string where an array of strings is expected.
Also, String::Empty is better practice than using a literal empty string.
Try this:
array<System::String^>^ args = gcnew array<System::String^>(1);
args[0] = String::Empty;
Application::Run(gcnew Form1(args));

How to solve access violation writing location error?

I have a simple program and I get access violation at *(str + start). Why? I should be able to change it. Right?
void fn()
{
char *str = "Hello wordl!";
int end = strlen(str);
int start = 0;
end--;
while(start < end)
{
*(str + start) = *(str + end); <--- Access violation writing location *(str + Start).
end--;
start++;
}
}
char *str = "Hello World"; is a const string, and cannot be modified. The compiler is free to put it into a non-writable location, resulting in the crash you see.
Replacing the declaration with char str[] = "Hello World"; should do what you want, putting the string into a modifiable array on the stack.
No, you should not. "Hello world" is a constant string literal, you need to allocate memory using malloc() in C, or new in C++ if you want memory you are free to modify.
As others have pointed out, literal strings may be stored in a read-only area of memory. Are you compiling with warnings turned on? You should get a warning about discarding the constness of the string literal.
What you can do instead is:
char *str = strdup("Hello, world!");
// Modify the string however you want
free(str);
It's because you're writing to a string literal's storage, which may be in a protected area of memory.
In your example, Hello wordl! is constant string, any attempt to modify this constant string will result in an exception.
Instead, You can do this -
string s = "Hello wordl!";
char* ptr = &s[0];
and then play around with ptr.

Resources