I'm new to Objective-C so I'm using a book to get to grips with it. I'm at a bit where it's explaining structs and I can't for the life of me get them to work.
I have the following code:
int main (int argc, char *argv[])
{
struct node
{
int nodeID;
int x;
int y;
BOOL isActive;
};
typedef struct node myNode;
myNode.nodeID = 1;
}
and I'm getting the error written in the title. Every time I search for this error online I found different variations such as 'before '>' token' or 'before '}' token' but i can't find anything with the '.' token and it's really frustrating and I assume it's somethings ridiculously trivial and basic. Any help would be appreciated.
I believe you're trying to modify the actual type itself. nodeA is now the type of that struct, much like int. You need to do something like nodeA myNode, then you would be able to perform myNode.nodeID = 1 without error.
I've got it sorted now, I used the following and it seems to be fixed now:
int main (int argc, char *argv[])
{
struct node
{
int nodeID;
int x;
int y;
BOOL isActive;
};
struct node myNode;
myNode.nodeID = 1;
myNode.x = 100;
myNode.y = 200;
myNode.isActive = TRUE;
}
Thanks for all your help Darth! :)
I think the problem with the original code was, it was trying to make myNode a type name using typedef. Thus, myNode is NOT a variable that assignment can happen to. Rather, it was another alias for struct node.
Related
I'd like a step by step explanation on how to parse the arguments of a variadic function
so that when calling va_arg(ap, TYPE); I pass the correct data TYPE of the argument being passed.
Currently I'm trying to code printf.
I am only looking for an explanation preferably with simple examples but not the solution to printf since I want to solve it myself.
Here are three examples which look like what I am looking for:
https://stackoverflow.com/a/1689228/3206885
https://stackoverflow.com/a/5551632/3206885
https://stackoverflow.com/a/1722238/3206885
I know the basics of what typedef, struct, enum and union do but can't figure out some practical application cases like the examples in the links.
What do they really mean? I can't wrap my brain around how they work.
How can I pass the data type from a union to va_arg like in the links examples? How does it match?
with a modifier like %d, %i ... or the data type of a parameter?
Here's what I've got so far:
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include "my.h"
typedef struct s_flist
{
char c;
(*f)();
} t_flist;
int my_printf(char *format, ...)
{
va_list ap;
int i;
int j;
int result;
int arg_count;
char *cur_arg = format;
char *types;
t_flist flist[] =
{
{ 's', &my_putstr },
{ 'i', &my_put_nbr },
{ 'd', &my_put_nbr }
};
i = 0;
result = 0;
types = (char*)malloc( sizeof(*format) * (my_strlen(format) / 2 + 1) );
fparser(types, format);
arg_count = my_strlen(types);
while (format[i])
{
if (format[i] == '%' && format[i + 1])
{
i++;
if (format[i] == '%')
result += my_putchar(format[i]);
else
{
j = 0;
va_start(ap, format);
while (flist[j].c)
{
if (format[i] == flist[j].c)
result += flist[i].f(va_arg(ap, flist[i].DATA_TYPE??));
j++;
}
}
}
result += my_putchar(format[i]);
i++;
}
va_end(ap);
return (result);
}
char *fparser(char *types, char *str)
{
int i;
int j;
i = 0;
j = 0;
while (str[i])
{
if (str[i] == '%' && str[i + 1] &&
str[i + 1] != '%' && str[i + 1] != ' ')
{
i++;
types[j] = str[i];
j++;
}
i++;
}
types[j] = '\0';
return (types);
}
You can't get actual type information from va_list. You can get what you're looking for from format. What it seems you're not expecting is: none of the arguments know what the actual types are, but format represents the caller's idea of what the types should be. (Perhaps a further hint: what would the actual printf do if a caller gave it format specifiers that didn't match the varargs passed in? Would it notice?)
Your code would have to parse the format string for "%" format specifiers, and use those specifiers to branch into reading the va_list with specific hardcoded types. For example, (pseudocode) if (fspec was "%s") { char* str = va_arg(ap, char*); print out str; }. Not giving more detail because you explicitly said you didn't want a complete solution.
You will never have a type as a piece of runtime data that you can pass to va_arg as a value. The second argument to va_arg must be a literal, hardcoded specification referring to a known type at compile time. (Note that va_arg is a macro that gets expanded at compile time, not a function that gets executed at runtime - you couldn't have a function taking a type as an argument.)
A couple of your links suggest keeping track of types via an enum, but this is only for the benefit of your own code being able to branch based on that information; it is still not something that can be passed to va_arg. You have to have separate pieces of code saying literally va_arg(ap, int) and va_arg(ap, char*) so there's no way to avoid a switch or a chain of ifs.
The solution you want to make, using the unions and structs, would start from something like this:
typedef union {
int i;
char *s;
} PRINTABLE_THING;
int print_integer(PRINTABLE_THING pt) {
// format and print pt.i
}
int print_string(PRINTABLE_THING pt) {
// format and print pt.s
}
The two specialized functions would work fine on their own by taking explicit int or char* params; the reason we make the union is to enable the functions to formally take the same type of parameter, so that they have the same signature, so that we can define a single type that means pointer to that kind of function:
typedef int (*print_printable_thing)(PRINTABLE_THING);
Now your code can have an array of function pointers of type print_printable_thing, or an array of structs that have print_printable_thing as one of the structs' fields:
typedef struct {
char format_char;
print_printable_thing printing_function;
} FORMAT_CHAR_AND_PRINTING_FUNCTION_PAIRING;
FORMAT_CHAR_AND_PRINTING_FUNCTION_PAIRING formatters[] = {
{ 'd', print_integer },
{ 's', print_string }
};
int formatter_count = sizeof(formatters) / sizeof(FORMAT_CHAR_AND_PRINTING_FUNCTION_PAIRING);
(Yes, the names are all intentionally super verbose. You'd probably want shorter ones in the real program, or even anonymous types where appropriate.)
Now you can use that array to select the correct formatter at runtime:
for (int i = 0; i < formatter_count; i++)
if (current_format_char == formatters[i].format_char)
result += formatters[i].printing_function(current_printable_thing);
But the process of getting the correct thing into current_printable_thing is still going to involve branching to get to a va_arg(ap, ...) with the correct hardcoded type. Once you've written it, you may find yourself deciding that you didn't actually need the union nor the array of structs.
In every example I saw that tries to use a dynamic size for an array in a struct uses global constants at some point. What I am trying to do is pass an integer variable that is decided by the user to a structure that I create storing an array of that size, thus dynamic. Obviously the code below doesn't work, but it gives you an idea of what I plan on accomplishing
struct Node {
char input;
int playingBoard[size];
Node* pNext;
};
int main(){
cout<<"enter board size"<<endl;
cin>>size;
int playingBoard[size];
}
struct Node
{
int countr;
int playingBoard[];
};
int countr;
...
struct Node *p = malloc(offsetof(Node, playingBoard) +
countr* sizeof *p->playingBoard);
p->countr= countr;
...
or an independent dynamically-allocated array
struct Node
{
int countr;
int *playingBoard;
};
Node holder;
...
holder.playingBoard =
malloc(holder.countr * sizeof *holder.playingBoard);
like the topic, I have no idea where to start with coding the sprintf_s method.
I tried to solve it with switch-case, but again, I have no idea where to start.
Thanks for helping!
Here's where you start:
Documentation
int sprintf_s(
char *buffer,
size_t sizeOfBuffer,
const char *format, ...)
{
int ret_val = 0;
[...Fill stuff in here...]
return ret_val;
}
(Objective C Code)
int i=5;
{
int i=i;
NSLog(#"Inside Scope: %i",i);
}
NSLog(#"Outside Scope: %i",i);
Prints:
3385904 (Garbage)
5
replacing int i = i; with int i= 10; prints correctly... (Inside the scope's i)
Such as:
10
5
And (This code alone)
int i=i;
Compiles, but segfaults immediately.
How are any of these syntax's valid? What use are they, or are they compiler bugs that should have been caught earlier?
Is there any situation where it is necessary for using the same variable names inside a new scope under a new type, and how would you differentiate?
My only thoughts is could be the for() loop, as the compiler would be upset you're redefining int i; twice if you have two loops.
Because you're redefining i, you're setting i to the value for itself that hasn't been set yet.
Simply turning this:
int i=5;
{
int i=i;
}
into this:
int i = i;
//int i=5;
//{
//int i=i;
//}
will give you the same varied results. This problem has nothing to do with scope.
I've written a C++/CLI wrapper for a C++-DLL to use this DLL in a C# programm.
However, when I call a function, which takes a char* I get a AccessViolation
int Wrapper::Net_methodX(int a, String^ key, long v)
{
IntPtr ptr = Marshal::StringToHGlobalAnsi(key);
pin_ptr<char> cKey = static_cast<char*>(ptr.ToPointer());
int val = methodX(a,cKey, v); // AccessViolation here
Marshal::FreeHGlobal(ptr);
return val;
}
The signature of the C++-function is
int methodX(int a, char *Key, long v);
EDIT 1
Just to "pin" like the following didn't work either:
int Wrapper::Net_methodX(int a, String^ key, long v)
{
IntPtr ptr = Marshal::StringToHGlobalAnsi(key);
char* cKey = static_cast<char*>(ptr.ToPointer());
pin_ptr<char> pinned = cKey;
int val = methodX(a,cKey, v);
Marshal::FreeHGlobal(ptr);
return val;
}
EDIT 1 END
EDIT 2
I tried also PtrToStringChars the following way (Thanks Matt, found also some doc here):
int Wrapper::Net_methodX(int a, String^ key, long v)
{
pin_ptr<const wchar_t> wkey = PtrToStringChars(key);
size_t convertedChars = 0;
size_t sizeInBytes = ((key->Length + 1) * 2);
errno_t err = 0;
char * ckey = (char * ) malloc(sizeInBytes);
err = wcstombs_s(&convertedChars, ckey, sizeInBytes, wkey, sizeInBytes);
int val = methodX(A_Symbol_Table,ckey, Value);
return val;
}
AccessViolation still occurs, maybe it's an error in methodX() (which is a Third-party-DLL).
EDIT 2 END
I have read some related questions here, but did not find a solution yet.
Any hints?
Thank you.
I know this is an old question, but for anyone who stumble upon this question looking for an answer, here are some simpler solutions.
Simply use sprintf to do the conversion like this: sprintf(cStr, "%s", clrString);. See my answer to this question for a complete example.
Read KB311259 as suggested by Matt Smith. If you are using VS 2008 or higher, use marshal_as<> (Method #4 in the KB). It's much simpler than the other methods in that document.
Simon,
I tried out your example and I do not get an Access Violation. Here's my code:
using namespace System;
using namespace System::Runtime::InteropServices;
ref class Wrapper
{
public:
static int Net_methodX(int a, String^ key, long v);
};
int methodX(int a, char * pKey, long v)
{
IntPtr ptr = static_cast<IntPtr>(pKey);
String ^ pString = Marshal::PtrToStringAnsi(ptr);
System::Console::WriteLine(pString);
return a;
}
int Wrapper::Net_methodX(int a, String^ pKey, long v)
{
IntPtr ptr = Marshal::StringToHGlobalAnsi(pKey);
pin_ptr<char> cKey = static_cast<char*>(ptr.ToPointer());
int val = methodX(a,cKey, v); // AccessViolation here
Marshal::FreeHGlobal(ptr);
return val;
}
void main()
{
Wrapper wrapper;
String ^ p = gcnew String("Hello");
wrapper.Net_methodX(0, p, 0);
}
Also, I have a few comments:
Read here: http://support.microsoft.com/kb/311259
You are using a pin_ptr to native memory. The StringToHGlobalAnsi method returns native memory, so I don't think using a pin_ptr makes sense here. A pin_ptr would make sense if you were using a method that gives you back a pointer to managed memory (like PtrToStringChars). Unless you are modifying the string, you probably want to go with the PtrToStringChars approach anyways--to avoid unnecessary allocation and copying.
Would you post an example version of methodX that causes the problem? If I can reproduce the issue, I might be able to be more helpful.
Simon
I think there is a problem with the following code
pin_ptr<char> cKey = static_cast<char*>(ptr.ToPointer());
You might want to read this http://social.msdn.microsoft.com/forums/en-US/vclanguage/thread/0bd049fe-844a-4cb6-b9f6-c8f5107bc957
Let me know if it helped you.
Sujay