I'm trying to get the gateway ip address of the wifi I'm connected to. I'm using the answer in this question but I'm getting an error on the codes.
When I use this in my project
- (NSString *)getGatewayIP {
NSString *ipString = nil;
struct in_addr gatewayaddr;
int r = getdefaultgateway(&(gatewayaddr.s_addr));
if(r >= 0) {
ipString = [NSString stringWithFormat: #"%s",inet_ntoa(gatewayaddr)];
NSLog(#"default gateway : %#", ipString );
} else {
NSLog(#"getdefaultgateway() failed");
}
return ipString;
}
I get this error when I try to build my project:
Undefined symbols for architecture arm64: "getdefaultgateway(unsigned int*)"
Here is the getgateway.c
int getdefaultgateway(in_addr_t * addr)
{
int mib[] = {CTL_NET, PF_ROUTE, 0, AF_INET,
NET_RT_FLAGS, RTF_GATEWAY};
size_t l;
char * buf, * p;
struct rt_msghdr * rt;
struct sockaddr * sa;
struct sockaddr * sa_tab[RTAX_MAX];
int i;
int r = -1;
if(sysctl(mib, sizeof(mib)/sizeof(int), 0, &l, 0, 0) < 0) {
return -1;
}
if(l>0) {
buf = malloc(l);
if(sysctl(mib, sizeof(mib)/sizeof(int), buf, &l, 0, 0) < 0) {
return -1;
}
for(p=buf; p<buf+l; p+=rt->rtm_msglen) {
rt = (struct rt_msghdr *)p;
sa = (struct sockaddr *)(rt + 1);
for(i=0; i<RTAX_MAX; i++) {
if(rt->rtm_addrs & (1 << i)) {
sa_tab[i] = sa;
sa = (struct sockaddr *)((char *)sa + ROUNDUP(sa->sa_len));
} else {
sa_tab[i] = NULL;
}
}
if( ((rt->rtm_addrs & (RTA_DST|RTA_GATEWAY)) == (RTA_DST|RTA_GATEWAY))
&& sa_tab[RTAX_DST]->sa_family == AF_INET
&& sa_tab[RTAX_GATEWAY]->sa_family == AF_INET) {
if(((struct sockaddr_in *)sa_tab[RTAX_DST])->sin_addr.s_addr == 0) {
char ifName[128];
if_indextoname(rt->rtm_index,ifName);
if(strcmp("en0",ifName)==0){
*addr = ((struct sockaddr_in *)(sa_tab[RTAX_GATEWAY]))->sin_addr.s_addr;
r = 0;
}
}
}
}
free(buf);
}
return r;
}
Do I need to add frameworks? I've got no idea how to make it work.
Yes. .mm was my next question to you.
You're running into C++ name mangling issues.
In whichever .h file where you define and ultimately include/import the getdefaultgateway function, add this before:
#ifdef __cplusplus
extern "C" {
#endif
and after:
#ifdef __cplusplus
}
#endif
I am trying to return a pointer from a function and use the return in a different function but I am getting memory leak.
The test code which I wrote and detected with memory leak by CPPCheck.
########################################################################
# include < stdio.h >
# include < malloc.h >
# include < string.h >
char* replace ( char* st, char* word, char *replaceWith );
int main ( void )
{
char str[] = "Hello how are ## and what are ## doing ?";
char word[]="##";
char replaceWith[]="you";
printf("%s",replace(str,word,replaceWith));
getchar();
return 0;
}
char* replace(char* st,char* word,char *replaceWith)
{
int i = 0;
char *sr,*s,*ret;
int oldlen;
int count = 0;
int newlen;
int stlen;
s=(char *)malloc(strlen(st) + 1);
strcpy(s, st);
oldlen=strlen(word);
newlen=strlen(replaceWith);
for (i = 0; s[i]! = '\0'; )
{
if( memcmp( &s[i], word, oldlen ) == 0)
{
count++;
i+=oldlen;
}
else
{
i++;
}
}
sr= (char *) malloc (i+1+count*(newlen-oldlen));
ret = (char *) malloc (i+1+count*(newlen-oldlen));
ret=sr;
while(*s)
{
if(memcmp( s, word, oldlen) == 0)
{
memcpy(sr, replaceWith, newlen);
s+ = oldlen;
sr+ = newlen;
}
else
{
*sr++ = *s++;
}
}
*sr = '\0';
return ret;
}
Try this
#include<stdio.h>
#include<malloc.h>
#include<string.h>
char* replace ( char* st, char* word, char *replaceWith );
int main ( void )
{
char str[] = "Hello how are ## and what are ## doing ?";
char word[]="##";
char replaceWith[]="you";
char * ret = replace(str,word,replaceWith);
printf("%s",ret);
free(ret); //freeing the allocated memory
getchar();
return 0;
}
char* replace(char* st,char* word,char *replaceWith)
{
int i = 0;
char *sr,*s,*ret, *temps;
int oldlen;
int count = 0;
int newlen;
int stlen;
s=(char *)malloc(strlen(st) + 1);
temps = s; // storing the address of s in a temp location
strcpy(s, st);
oldlen=strlen(word);
newlen=strlen(replaceWith);
for (i = 0; s[i]!= '\0';)
{
if( memcmp( &s[i], word, oldlen ) == 0)
{
count++;
i+=oldlen;
}
else
{
i++;
}
}
sr= (char *) malloc (i+1+count*(newlen-oldlen));
ret=sr;
while(*s)
{
if(memcmp( s, word, oldlen) == 0)
{
memcpy(sr, replaceWith, newlen);
s += oldlen;
sr += newlen;
}
else
{
*sr++ = *s++;
}
}
*sr = '\0';
free(temps); // freeing the memory allocated for s
return ret;
}
Always free same count with malloc.
free s, sr at end of replace,
use return value of replace instead of direct use on printf
and free return value (return of ret from replace) when not needed.
I have doing lots of experimenting with the memory leak and meanwhile I wrote the following code. Please comment about the pros and cons side of it.
#include <stdio.h>
#include <string.h>
#include <malloc.h>
// Prototype declaration of replaceAll function
static char* replaceAll(char *pSource, char *pWord, char*pWith);
/////////////////////////////////////////////////////////////////////////////
//
// NAME : main
//
// DESCRIPTION : Implementation of main which invokes the replaceAll
// function and displays the output
//
// PARAMETERS : void
//
// RETURNED VALUE : int
//
/////////////////////////////////////////////////////////////////////////////
int main( void )
{
char *finalString = NULL; // To save the base returned address
char srcString[] = "Hello how r you"; // Actual String
char pWord[] = "r"; // Word to be replaced
char pWith[] = "are"; // Word to be replaced with
printf("\n Before Calling the replaceAll function:");
printf("%s",srcString);
printf("\n");
finalString = replaceAll(srcString, pWord, pWith); //calling the replaceAll function
printf("\n After Calling the replaceAll function:");
// Checking if NULL is returned
if( finalString != NULL )
{
//printing the string
printf("%s", finalString);
}
else
{
printf("\n Error: Blank String returned ");
}
return 0;
}
/////////////////////////////////////////////////////////////////////////////
//
// NAME : replaceAll
//
// DESCRIPTION : Implementation of replaceAll function which replaces
// a word in given string with another word
//
// PARAMETERS : char *
//
// RETURNED VALUE : char *
//
/////////////////////////////////////////////////////////////////////////////
static char* replaceAll(char *pSource, char *pWord, char*pWith)
{
char *pSt = NULL; // Pointer to the source String to avoid modifying the pSource
char *pTarget = NULL; // Target pointer to be malloced
char *pTg = NULL; // Pointer to the target string
int count; // Counter
int nWord = strlen (pWord); // length of the word which needs to be replaced
int nWith = strlen (pWith); // length of the word with which the word needs to be replaced
static const char nullP = '\0'; // null character
int szTarget = 0;
// Assigning the base address of the pSource to a temporary and iterate through
for ( pSt = pSource, count = 0; *pSt != nullP; pSt++ )
{
// Count number of occurances of the Word in the String to calculate the length of the final string
if( memcmp( pSt, pWord, nWord ) == 0)
{
count++;
pSt += nWord-1;
}
}
// Calculate the required target Size
szTarget = strlen (pSource) + count * (nWith - nWord) + sizeof (nullP);
// Allocate memory for the target string
pTarget = (char *)malloc(szTarget);
// Check if the malloc function returns sucessfully
if ( pTarget != NULL)
{
// Copying the string with replacement
for (pTg = pTarget, pSt = pSource; *pSt != nullP; )
{
if( memcmp (pSt, pWord, nWord) == 0)
{
memcpy (pTg,pWith,nWith);
pSt += nWord;
pTg += nWith;
}
else
{
*pTg++ = *pSt++;
}
}
// Assigning NULL Character to the target string after copying
*pTg = '\0';
}
return pTarget;
}
I have following non-ARC code
int sortMidiEvent(void* v1, void* v2) {
MidiEvent **ev1 = (MidiEvent**)v1;
MidiEvent **ev2 = (MidiEvent**)v2;
MidiEvent *event1 = *ev1;
MidiEvent *event2 = *ev2;
if (event1.startTime == event2.startTime) {
return event1.eventFlag - event2.eventFlag;
}
else {
return event1.startTime - event2.startTime;
}
}
I want to convert it to ARC. What should I do?
Can I change to the following?
int sortMidiEvent(void* v1, void* v2) {
MidiEvent *event1 = (__bridge MidiEvent *) v1;
MidiEvent *event2 = (__bridge MidiEvent *) v2;
if (event1.startTime == event2.startTime) {
return event1.eventFlag - event2.eventFlag;
}
else {
return event1.startTime - event2.startTime;
}
}
I do not understand why we need pointer to pointer in non-ARC?
string getFilename(string s) {
char sep = '/';
char sepExt='.';
#ifdef _WIN32
sep = '\\';
#endif
size_t i = s.rfind(sep, s.length( ));
if (i != string::npos) {
string fn= (s.substr(i+1, s.length( ) - i));
size_t j = fn.rfind(sepExt, fn.length( ));
if (i != string::npos) {
return fn.substr(0,j);
}else{
return fn;
}
}else{
return "";
}
}
a=getFilename(filename); // filename is an image
It looks like It extracts file's name without it's extension and a path to it:
"/home/user/Documents/someimage.jpg" -> "someimage"
size_t i = s.rfind(sep, s.length( )); // find location of the "/"
if (i != string::npos) {
string fn= (s.substr(i+1, s.length( ) - i)); // extract filename with extension -> "someimage.jpg"
size_t j = fn.rfind(sepExt, fn.length( )); // find location of the extension by looking for "."
if (i != string::npos) {
return fn.substr(0,j); // extract filename -> "someimage"
}else{
return fn;
}
}else{
return "";
}
I got a function which should return an intvalue.
- (int)function:(NSString *)input
{
if (input == #"test1")
{
return 0;
}
if (input == #"test2")
{
return 1;
}
if (input == #"test3")
{
return 2;
}
else
{
return 3;
}
}
Here I call the function:
[self function:self.detailItem.type]
The debugger shows input __NSCFString * 0x6b9a0b0 and returns any 29938idontknowvalue.
If I call [self function:#"test1"] everything works fine.
The detailItemis type of TVwhich is a NSManagedObjectwith the attribute type defined as string. Should be a problem with the string-types?
Thank you!
You should compare NSString like this :
if ([input isEqualToString:#"test1"])
{
// Some code here
}
Check that self.detailItem.type is an NSString:
if ([self.detailItem.type isKindOfClass:[NSString class]])
before calling
[self function:self.detailItem.type]
and compare strings like this
[input isEqualToString:#"test1"];
you are currently comparing memory addresses, which in this case will be always different, you should be comparing the strings they contain.