Objective-C Struct problems - objective-c

I have a student structure that provides the following code:
#import <Foundation/Foundation.h>
#import "Grades.m"
#import <stdio.h>
struct Student
{
NSString *myName;
struct Grades *myGrades;
};
void setName(struct Student *s, NSString *name);
void ssetGrades(struct Student *s, NSString *gradeList);
void setName(struct Student *s, NSString *name)
{
s->myName = name;
}
void ssetGrades(struct Student *s, NSString *gradeList)
{
printf("\n\nWorking\n\n");
setGrades(s->myGrades, gradeList);
printf("\n\nWorking");
}
I have a grades structure that provides the following:
#import <stdio.h>
#import <Foundation/Foundation.h>
#define null NULL
struct Grades
{
double sgrades[100];
int length;
};
void setGrades(struct Grades *grades, NSString *gradeList);
void setGrade(int spot, double grade, struct Grades *grades);
void setGrades(struct Grades *grades, NSString *gradeList)
{
NSString *a = [gradeList substringToIndex:1];
NSString *b = [gradeList substringWithRange:NSMakeRange(3, 19)];
int ln = [a integerValue];
grades->length = ln;
double grade;
int x = 1;
int prev = 1;
int y;
int z = 0;
for(y=0;y<ln;y++)
{
while(x < [b length] && [b characterAtIndex:x] != ' ')
{
z++;
x++;
}
NSString *sub = [b substringWithRange:NSMakeRange(prev, z)];
grade = [sub doubleValue];
printf("%d %d %d %lf\n", y, prev, z, grade);
prev += z+1;
x++;
z=0;
setGrade(y, grade, grades);
}
}
void setGrade(int spot, double grade, struct Grades *grades)
{
grades->sgrades[spot] = grade;
}
And finally, I have a main function with the following:
#import <Foundation/Foundation.h>
#import "Grades.m"
#import "Student.m"
#import <stdio.h>
int main (int argc, const char * argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
struct Grades test;
setGrades(&test, #"5 - 90 85 95.5 77.5 88");
toString(&test);
printf("\nsum = %lf", getSum(&test));
printf("\nnum grades = %d", getNumGrades(&test));
printf("\nlow grade = %lf", getLowGrade(&test));
printf("\nhigh grade = %lf", getHighGrade(&test));
struct Student stu;
setName(&stu, #"Billy Bob");
ssetGrades(&stu, #"5 - 90 85 95.5 77.5 88");
[pool release];
return 0;
}
Now whenever I get to the ssetGrades (&stu, #"5 - 90 85 95.5 77.5 88") line in the main, it freezes up and says that the program has stopped working. Any guesses why and if so, how can I fix this error?
NOTE: This is all done in Notepad++ on Windows 7

Your primary issue is your definition of your Student structure. Change the Grades reference so it isn't a pointer:
struct Student
{
NSString *myName;
struct Grades myGrades;
};
The problem with the pointer is that you never initialize the pointer. By removing the pointer the memory issues causing the crash will go away.
As a result of this change, you need to change a few other things. The call to setGrades needs to pass the address of myGrades:
setGrades(&(s->myGrades), gradeList);
Even better would be to replace all of this struct/function code with actual classes.

Related

Using NSUInteger Input to insertObject:___ atIndex:___

I'm trying to create a simple commandline tic-tac-toe game using an NSMutableArray.
Created a class called "Board" with the method "getPosition"
(I'm assuming this is the best way to get a user input)
I'm asking for position, then casting from int to NSUInteger)
#import "Board.h"
#implementation Board
-(void)getPosition;
{
int enteredPosition;
scanf("%i", &enteredPosition);
NSUInteger nsEnteredPosition = (NSUInteger ) enteredPosition;
NSLog(#"Position = %lu", (unsigned long)nsEnteredPosition);
}
#import <Foundation/Foundation.h>
#import "Board.h"
int main(int argc, const char * argv[])
{
#autoreleasepool {
NSString *currentPlayer;
NSMutableArray *gameBoard=[[NSMutableArray alloc] initWithCapacity:9];
for(int i; i<=2; i++)
{
if(i %2)
{
currentPlayer=#"X";
}
else
{
currentPlayer=#"O";
}
NSLog(#"Player %#, select an open spot 1 - 9 on the board", currentPlayer);
Board *currentPosition = [[Board alloc] init];
[currentPosition getPosition];
[gameBoard insertObject:currentPlayer atIndex:currentPosition]; //this is where i have a problem
}
As I understand it atIndex requires an NSUInteger parameter, but I'm receiving the error message:
"Incompatible pointer to integer conversion sending 'Board *_strong"
to parameter of type 'NSUInteger' (aka 'unassigned long')
You're using currentPosition as your index which is a Board object. Perhaps [currentPosition getPosition] is supposed to return an NSUInteger. If so, try rewriting the last portion of your code like this:
Board *theBoard = [[Board alloc] init];
NSUInteger currentPosition = [theBoard getPosition];
[gameBoard insertObject:currentPlayer atIndex:currentPosition]; //this is where i have a problem

Implementing a header in Objective C

I'm completely new to Objective C and I'm trying to use it to wrap a C-library. I have a main.m wrap.m and wrap.h files. From what I gather in the header file I included #interface and in the source file I will include #implementation However I'm not really understanding what to include in each of them. Right now my main file is:
int copy_data(struct archive *ar, struct archive *aw) {
for (;;) {
const void *buff;
size_t size;
off_t offset;
int r = archive_read_data_block(ar, &buff, &size, &offset);
if (r == ARCHIVE_EOF)
return (ARCHIVE_OK);
archive_write_data_block(aw, buff, size, offset);
}
}
int main(int argc, const char * argv[])
{
#autoreleasepool {
struct archive *a;
struct archive *ext;
struct archive_entry *entry;
int flags;
int r;
/* Select which attributes we want to restore. */
flags = ARCHIVE_EXTRACT_TIME;
flags |= ARCHIVE_EXTRACT_PERM;
flags |= ARCHIVE_EXTRACT_ACL;
flags |= ARCHIVE_EXTRACT_FFLAGS;
a = archive_read_new();
archive_read_support_format_all(a);
archive_read_support_compression_all(a);
ext = archive_write_disk_new();
archive_write_disk_set_options(ext, flags);
archive_write_disk_set_standard_lookup(ext);
r = archive_read_open_filename(a, argv[1], 10240);
for (;;) {
r = archive_read_next_header(a, &entry);
if (r == ARCHIVE_EOF)
break;
r = archive_write_header(ext, entry);
if (archive_entry_size(entry) > 0) {
copy_data(a, ext);
}
archive_write_finish_entry(ext);
}
archive_read_close(a);
archive_read_free(a);
archive_write_close(ext);
archive_write_free(ext);
NSLog(#"No Issues");
}
return 0;
}
So far what I'm getting in my wrap.h file is:
typedef struct{
int *a;
int *ext;
}archive;
#interface main : NSObject
#property int flags;
#property int r;
I don't know if that is close to what I need to do, and I'm getting errors on my ARCHIVE_EXTRACT saying they are undeclared identifiers which I assume also have to go into my wrap.h file but I'm not sure how to do that. Any help at all would be appreciated!
If you start your project in Xcode using the CommandLineTool template, you can select your language to be "C" or "C++", so you wouldn't have to mess with Objective-C at all.
As for the .h file that you currently have, don't do "#property" or "#interface" for "main". "main" is a C style function and not an Objective-C thing.
If you are actually interested in an objectivec solution, follow Michael Dautermann's instructions to start a new Command Line project but instead of Type C use the Foundation option. This will give you a working main (just a regular c function). Then select new->objective c class to create your wrap.h/wrap.m. In the wrap.h you will pretty much exclusively be declaring your own objectivec public wrapper methods. In the wrap.m, you'll be importing what you want to wrap, and defining your wrapper functions.
//
// main.m
//
#import <Foundation/Foundation.h>
#import "wrap.h"
int main(int argc, const char * argv[])
{
#autoreleasepool {
[wrap wrappedStuff];
}
return 0;
}
//
// wrap.h
//
----------
#import <Foundation/Foundation.h>
#interface wrap : NSObject
+ (void)wrappedStuff;
#end
//
// wrap.m
//
#import "wrap.h"
#include "WhatImWrapping.h"
#implementation wrap
int copy_data(struct archive *ar, struct archive *aw) {
for (;;) {
const void *buff;
size_t size;
off_t offset;
int r = archive_read_data_block(ar, &buff, &size, &offset);
if (r == ARCHIVE_EOF)
return (ARCHIVE_OK);
archive_write_data_block(aw, buff, size, offset);
}
}
+ (void)wrappedStuff
{
struct archive *a;
struct archive *ext;
struct archive_entry *entry;
int flags;
int r;
/* Select which attributes we want to restore. */
flags = ARCHIVE_EXTRACT_TIME;
flags |= ARCHIVE_EXTRACT_PERM;
flags |= ARCHIVE_EXTRACT_ACL;
flags |= ARCHIVE_EXTRACT_FFLAGS;
a = archive_read_new();
archive_read_support_format_all(a);
archive_read_support_compression_all(a);
ext = archive_write_disk_new();
archive_write_disk_set_options(ext, flags);
archive_write_disk_set_standard_lookup(ext);
r = archive_read_open_filename(a, argv[1], 10240);
for (;;) {
r = archive_read_next_header(a, &entry);
if (r == ARCHIVE_EOF)
break;
r = archive_write_header(ext, entry);
if (archive_entry_size(entry) > 0) {
copy_data(a, ext);
}
archive_write_finish_entry(ext);
}
archive_read_close(a);
archive_read_free(a);
archive_write_close(ext);
archive_write_free(ext);
NSLog(#"No Issues");
}
#end

Use of Undeclared Identifier 'calculateAge' [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
I am new to objective and just trying to understand simple concepts.
I have read Objective C for dummies and Cocoa Programming for Mac OSX (most of it).
I tried to make a simple small program on my own and realized I know very little.
I keep getting the "Use of Undeclared Identifier "calculateAge', did you mean 'Calculate' " error.
Can anyone please tell me what's wrong with my code below and why?
Thanks a bunch in advance.
#import <Foundation/Foundation.h>
#interface Calculate : NSObject
{
int myYear;
int nowYear;
}
- (int) calculateAge:(int)birthYear:(int)nowYear;
#end
#implementation Calculate
- (int) calculateAge:(int)birthYear:(int)nowYear// need myYear
{
NSLog(#"The birthYear is: %i\n", birthYear);
int myAge = nowYear - birthYear;
//NSLog(#"The nowYear is: %i\n", nowYear);
NSLog(#"The age is: %i\n", myAge);
return myAge;
}
int main(int argc, const char * argv[])
{
#autoreleasepool {
NSLog(#"Hello, World!");
int myY = 1963;
int nowY = 2012;
int myYear = 1963;
int nowYear = 2012;
//int myAge = calculateAge:(int) birthYear: (int) nowYear;
int myAge = calculateAge:(int) myY: (int) nowY;
NSLog(#"The nowYear is: %i\n", nowYear);
NSLog(#"The age is: %i\n", myAge);
}
return 0;
}
#end
You seem to be conflating the method name with the parameter list. A proper signature would look something like this:
- (int)calculateAgeFromBirthYear:(int)birthYear currentYear:(int)currentYear
This could then be implemented like this:
- (int)calculateAgeFromBirthYear:(int)birthYear currentYear:(int)currentYear
{
NSLog(#"The birthYear is: %i\n", birthYear);
int myAge = currentYear - birthYear;
//NSLog(#"The nowYear is: %i\n", currentYear);
NSLog(#"The age is: %i\n", myAge);
return myAge;
}
This could then be called like this:
Calculate *calculator = [[Calculate alloc] init];
int myAge = [calculator calculateAgeFromBirthYear:myY currentYear:nowY];
Don't implement main inside a class implementation; it belongs outside in the global namespace, preferably in its own file.
There is no need to declare the instance variables in the interface.
The last #end needs to be before the main function, it is not part of the class, it used the class.
The Calculate class needs to be instantiated and the call needs to be made to the instantiated class.
The calculateAge... method should be renamed to indicate each argument.
Variables should be given full names, abreviations generall end up making things less clear.
Here is an example:
#interface Calculate : NSObject
- (int) calculateAgeWithBirthYear:(int)birthYear nowYear:(int)nowYear;
#end
#implementation Calculate
- (int) calculateAgeWithBirthYear:(int)birthYear nowYear:(int)nowYear// need myYear
{
NSLog(#"The birthYear is: %i\n", birthYear);
int myAge = nowYear - birthYear;
NSLog(#"The age is: %i\n", myAge);
return myAge;
}
#end
int main(int argc, const char * argv[])
{
#autoreleasepool {
NSLog(#"Hello, World!");
int myBirthYear = 1963;
int nowYear = 2012;
Calculate *calculator = [[Calculate alloc] init];
int myAge = [calculator calculateAgeWithBirthYear:myBirthYear nowYear:nowYear];
NSLog(#"The nowYear is: %i\n", nowYear);
NSLog(#"The age is: %i\n", myAge);
}
return 0;
}
NSLog output:
Hello, World!
The birthYear is: 1963
The age is: 49
The nowYear is: 2012
The age is: 49
Using instance variables created by `#property~ statements:
#interface Calculate : NSObject
#property int myYear;
#property int nowYear;
- (int) calculateAge;
#end
#implementation Calculate
- (int) calculateAge // need myYear
{
NSLog(#"The birthYear is: %i\n", self.myYear);
int myAge = self.nowYear - self.myYear;
NSLog(#"The age is: %i\n", myAge);
return myAge;
}
#end
int main(int argc, const char * argv[])
{
#autoreleasepool {
NSLog(#"Hello, World!");
Calculate *calculator = [[Calculate alloc] init];
calculator.myYear = 1963;
calculator.nowYear = 2012;
int myAge = [calculator calculateAge];
NSLog(#"The nowYear is: %i\n", calculator.nowYear);
NSLog(#"The age is: %i\n", myAge);
}
return 0;
}

"Programming in objective-c" 3rd Kochan exercise 4.2

Exercise:
Write a program that converts 27° from degrees Fahrenheit (F) to degrees Celsius
(C) using the following formula:
C = (F - 32) / 1.8
Note that you don’t need to define a class to perform this calculation. Simply evaluating
the expression will suffice.
Here is my code:
#import <Foundation/Foundation.h>
int main (int argc, const char *argv[])
{
NSAutoreleasePool *pool=[[NSAutoreleasePool alloc] init];
float C;
float F;
F = 27;
C=(F-32)/1.8;
NSLog (#"27 degrees Fahrenheit is %f degrees Celsius." , C);
[drain pool];
return 0;
}
"Build failed"
On official forum there is a suggestion to write it this way :
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
double C, F;
F=27;
C=(F-32)/1.8;
int c=C;
NSLog(#"%g degrees Fahrenheit equals %i centigrades!", F, c);
[pool drain];
return 0;
}
But it also gives me "Failed" message.
What is not correct?
Update
Problem resolved.
I didn't set up initial settings of my project properly.
I was working inside other "C" programming language project.
I had to just create new project-> OS X -> Command line tool (type: Foundation) unmark "Use Automatic Reference Counting"
But the best part- i was rewarded with successfully compiled program:
2012-08-09 00:20:29.214 4.2[19452:403] 27 degrees Fahrenheit is -2.777778 degrees Celsius.
Thank you #trojanfoe , #john.k.doe , #drewk , #hol
This works:
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[])
{
#autoreleasepool {
float C;
float F;
F = 27.0;
C=(F-32.0)/1.8;
NSLog (#"27 degrees Fahrenheit is %f degrees Celsius." , C);
}
return 0;
}
So does this:
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[]) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
double F=27.2;
double C=(F-32.0)/1.8;
NSLog(#"%g degrees Fahrenheit equals %g centigrade!", F, C);
[pool drain];
return 0;
}
As you are not using objects even this will do it. Plain C.
int main(int argc, const char * argv[])
{
double C, F;
F=27;
C=(F-32)/1.8;
int c=C;
printf("%g degrees Fahrenheit equals %i centigrades!", F, c);
return 0;
}
Do you need to parse the arguments and calculate based on those?

Objective-C EXEC_BAD_ACCESS when using flexible length arrays

I have done some testing on some behavior I have found, and I was wondering if someone can help me understand what is going on.
I have a struct, called myStruct, that looks like this:
typedef struct {
int size;
float floats[];
} myStruct;
And I run this code on it:
int main () {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSArray *a = [[NSArray alloc] initWithObjects:#"0.2", #"0.5", #"0.5", nil];
NSLog(#"%#", a);
myStruct my;
my.size = a.count;
my.floats[0] = [[a objectAtIndex:0] floatValue];
my.floats[1] = [[a objectAtIndex:1] floatValue];
my.floats[2] = [[a objectAtIndex:2] floatValue];
NSLog(#"{ %lf, %lf, %lf }", my.floats[0], my.floats[1], my.floats[2]);
[a release];
[pool drain];
return 0;
}
It works fine. However, when I change the struct declaration to this:
typedef struct {
float myVar;
int size;
float floats[];
} myStruct;
I get EXEC_BAD_ACCESS when I call the line [a release].
Can anyone help me understand what is going on here?
You have to actually allocate space for your flexible array member! This line:
myStruct my;
Only makes enough stack space for size (or myVar and size from your second example). It appears that in your failing case you're overwriting a on the stack, but really both cases are wrong. To fix your problem, you need to allocate space for the floats[] member of the structure:
myStruct *my = malloc(sizeof(myStruct) + a.count * sizeof(float));
Don't forget to free() it when you're done!
A quick example - this program:
#include <stdio.h>
typedef struct {
float myVar;
int size;
float floats[];
} myStruct;
int main(int argc, char **argv)
{
printf("%zu\n", sizeof(myStruct));
return 0;
}
and its output:
$ make testapp
cc testapp.c -o testapp
$ ./testapp
8
You're not allocating any memory for your floats - I'm surprised it's not crashing sooner!
Do you need to malloc some memory for the floats[] pointer?
After a quick test I get EXC_BAD_ACCESS for both definitions of myStruct :)