using if statements with a string of letters and user input - objective-c

Helllo I am still new to programing and had a question about using if statements while using user input with the research I have conducted i can't seem to find what I am doing wrong?
Below is my posted simple multiplication calculator.
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[]) {
int a ;
int b ;
int c ;
printf("\n");
printf("\n");
printf("Welcome to calculator");
printf("\n");
printf("\n");
printf("what would you like to choose for first value?");
scanf("%d", &a);
printf("\n");
printf("What would you like to input for the second value?");
scanf("%d", &b);
c = a * b;
printf("\n");
printf("\n");
printf(" Here is your product");
printf("\n");
NSLog(#"a * b =%i", c);
char userinput ;
char yesvari = "yes" ;
char novari = "no";
printf("\n");
printf("\n");
printf("Would you like to do another calculation?");
scanf("%i", &userinput);
if (userinput == yesvari) {
NSLog(#" okay cool");
}
if (userinput == novari) {
NSLog(#"okay bye");
}
return 0;
}

You are scanning the character incorrectly with %i and you need to compare them using strcmp. If you are looking for a string from the user you need to use %s and you need a character buffer large enough to hold the input.
Try this
//Make sure userinput is large enough for 3 characters and null terminator
char userinput[4];
//%3s limits the string to 3 characters
scanf("%3s", userinput);
//Lower case the characteres
for(int i = 0; i < 3; i++)
userinput[i] = tolower(userinput[i]);
//compare against a lower case constant yes
if(strcmp("yes", userinput) == 0)
{
//Logic to repeat
printf("yes!\n");
}
else
{
//Lets just assume they meant no
printf("bye!\n");
}

I think you are reading a char using the wrong format %i: scanf("%i", &userinput);
And I think it is a better to use #NSString instead of simple char (I am not even sure what will happen in ObjC if you write char a = "asd", since you are giving a char a char[] value) . In that case, since strings are pointers, you cannot use == to compare them. You could use isEqualToString or isEqualTo instead. If you are interested in the difference between the two, look at this post would help.

In C, you can't compare strings using ==, so you would have to use a function like strcmp(), like this:
if ( !strcmp(userinput, yesvari) ) {
//etc.
}
The bang (!) is used because strcmp() actually returns 0 when the two strings match. Welcome to the wonderful world of C!

Related

How to use scanf in a Swift environment

I am practicing Objective C to get a better understanding of C and was using the newest Xcode, but using the terminal to write simple programs. In the the program below is can't seem to get the scanf function to work. Is there a different function that I can use to input data into the terminal to check the rest of syntax and coding?
#import <Foundation/Foundation.h>
int main (int argc, char *argv[])
{
int n, number, triangularNumber;
NSLog (#"What triangular number do you want?");
scanf ("%i", &number);
triangularNumber = 0;
for ( n = 1; n <= number; ++n )
triangularNumber += n;
NSLog (#"Triangular number %i is %i\n", number, triangularNumber);
return 0;
}
You can't have a space in between the scanf and (). The scanf function should turn purple when done correctly. Just take out the space and you should be fine.
You can try this (this is Swift, Objective C is the same):
let handle = NSFileHandle.fileHandleWithStandardInput()
let input = NSString(data: handle.availableData, encoding: NSUTF8StringEncoding)

Convert really large decimal string to hex?

I've got a really large decimal number in an NSString, which is too large to fit into any variable including NSDecimal. I was doing the math manually, but if I can't fit the number into a variable then I can't be dividing it. So what would be a good way to convert the string?
Example Input: 423723487924398723478243789243879243978234
Output: 4DD361F5A772159224CE9EB0C215D2915FA
I was looking at the first answer here, but it's in C# and I don't know it's objective C equivalent.
Does anyone have any ideas that don't involve using an external library?
If this is all you need, it's not too hard to implement, especially if you're willing to use Objective-C++. By using Objective-C++, you can use a vector to manage memory, which simplifies the code.
Here's the interface we'll implement:
// NSString+BigDecimalToHex.h
#interface NSString (BigDecimalToHex)
- (NSString *)hexStringFromDecimalString;
#end
To implement it, we'll represent an arbitrary-precision non-negative integer as a vector of base-65536 digits:
// NSString+BigDecimalToHex.mm
#import "NSString+BigDecimalToHex.h"
#import <vector>
// index 0 is the least significant digit
typedef std::vector<uint16_t> BigInt;
The "hard" part is to multiply a BigInt by 10 and add a single decimal digit to it. We can very easily implement this as long multiplication with a preloaded carry:
static void insertDecimalDigit(BigInt &b, uint16_t decimalDigit) {
uint32_t carry = decimalDigit;
for (size_t i = 0; i < b.size(); ++i) {
uint32_t product = b[i] * (uint32_t)10 + carry;
b[i] = (uint16_t)product;
carry = product >> 16;
}
if (carry > 0) {
b.push_back(carry);
}
}
With that helper method, we're ready to implement the interface. First, we need to convert the decimal digit string to a BigInt by calling the helper method once for each decimal digit:
- (NSString *)hexStringFromDecimalString {
NSUInteger length = self.length;
unichar decimalCharacters[length];
[self getCharacters:decimalCharacters range:NSMakeRange(0, length)];
BigInt b;
for (NSUInteger i = 0; i < length; ++i) {
insertDecimalDigit(b, decimalCharacters[i] - '0');
}
If the input string is empty, or all zeros, then b is empty. We need to check for that:
if (b.size() == 0) {
return #"0";
}
Now we need to convert b to a hex digit string. The most significant digit of b is at the highest index. To avoid leading zeros, we'll handle that digit specially:
NSMutableString *hexString = [NSMutableString stringWithFormat:#"%X", b.back()];
Then we convert each remaining base-65536 digit to four hex digits, in order from most significant to least significant:
for (ssize_t i = b.size() - 2; i >= 0; --i) {
[hexString appendFormat:#"%04X", b[i]];
}
And then we're done:
return hexString;
}
You can find my full test program (to run as a Mac command-line program) in this gist.

How to Get the First Different Character Between 2 Strings in Objective-C (for iOS)?

I know I can loop through each character of two NSString objects using characterAtIndex: and compare them, but this approach would be very expensive if I use this function frequently.
Is there anything built in for this, or a more efficient way to do it?
The quickest way i can think of is to get a C string from it, and then iterate through the strings.
Just a quick example (fix it to your liking):
const char* myCString = [myNSStringInstance UTF8String];
const char* string2 = [nsstring2 UTF8String];
// Assume same length. You can fix this
for(i = 0; i < strlen(myCString); i++) {
if(myCString[i] != string2[i]) {
// Do something here...
}
}
It's a litte hackish, but you could get the c-string for each and then use pointer indexing. Same basic algorithm as your mentioned idea, but theoretically as efficient as you could reasonably expect a solution to be (just looking at two memory addresses and comparing their contents.
Pseudo code:
char *stringA = [stringA cStringUsingEncoding:NSUTF8StringEncoding];
char *stringB = [stringB cStringUsingEncoding:NSUTF8StringEncoding];
int mismatchIndex = -1;
for(int i = 0; i<shorterStringLength; i++) {
if (stringA[i] != stringB[i]) {
mismatchIndex = i;
break;
}
}

How do I convert a Hexa-Tri-Decimal number into an int in objective c?

The Hexa-Tri-Decimal number is 0-9 and A-Z. I know I can covert from hex with a NSScanner but not sure how to go about converting Hexa-Tri-Decimal.
For example I have a NSString with "0XPM" the int value should be 43690, "1BLC" would be 61680.
Objective C is built on top of C, and luckily enough you can use the functions there to accomplish the conversion. What you're looking for is strtol or one of it's sibling functions. If I recall correctly strtol handles up to base36 (the hexa-tri-decimal you refer to).
http://www.cplusplus.com/reference/clibrary/cstdlib/strtol/
I can only think to do this using C strings, as they offer easier access to individual characters.
This seemed like an interesting problem to solve, so I had a go at writing it:
int parseBase36Number(NSString *input)
{
const char *inputCString = [[input lowercaseString] UTF8String];
size_t inputLength = [input length];
int orderOfMagnitudeMultiplier = 1;
int result = 0;
// iterate backward through the number
for (int i = inputLength - 1; i >= 0; i--)
{
char inputChar = inputCString[i];
int charNumericValue;
if (isdigit(inputChar))
{
charNumericValue = inputChar - '0';
}
else if (islower(inputChar))
{
charNumericValue = inputChar - 'a' + 10;
}
else
{
// unhanded character, throw error
}
result += charNumericValue * orderOfMagnitudeMultiplier;
orderOfMagnitudeMultiplier *= 36;
}
return result;
}
NOTE: I've not tested this at all, so take care and let me know how it goes!

obtaining objective c nsstring from c char[]

code below.
i'm tryind to obtain string answers like "a1", "c4"
this is what i'm having instead of "a1": "adresse finale: \340}00\214"
with this prinf:
printf("\nadresse finale: %s",[self convertCGPointToSquareAdress:self.frame.origin]);
the method is:
-(NSString *) convertCGPointToSquareAdress:(CGPoint ) point{
int x= point.x /PIECE_WIDTH;
int y=point.y/PIECE_WIDTH;
char lettreChiffre[2];
//char chiffre;
NSString *squareAdress;
//ascii a=97 , b=98... h=105
for (int i=97; i<105; i++) {
for (int j=8; j>0; j--) {
if(i-97==x && j-1==y ){
NSLog(#"enterrrrrrrrrred if convertCGPointToSquareAdress");
lettreChiffre[0]=i;
lettreChiffre[1]=(char) j;
printf(" lettreChiffre: %s ", lettreChiffre);
NSString *squareAdress=[NSString stringWithFormat:#"%s", lettreChiffre];
break;
}
}
}
return squareAdress;
}
can you please help me?
thanks in advance.
There are three problems I can see with your code:
1.
When you do
lettreChiffre[1]=(char) j;
remember j is a number between 1 and 8, so you're getting the ASCII character whose value is j, not the character 1...8. You should use
lettreChiffre[1]= '0' + j;
2.
lettreChiffre is a char array of length 2, which means there's no room for the terminal null character. This may work, but may give you gibberish. You should instead declare
char lettreChiffre[3];
lettreChiffre[2] = '\0';
3.
You're trying to use printf to print an NSString, which it can't do. Either use
NSLog(#"adresse finale: %#", mynsstring)
or convert the NSString back to a C-string:
printf("adresse finale: %s", [mynsstring UTF8String]);
Also, as noted by #dreamlax, you don't really need the loop. I assumed you were doing something else and ran into this trouble, so we're not really seeing the full code. But, if this is really the entirety of your code, then you can simply remove the loop as #dreamlax suggested.
What is the purpose of the loop? You have a loop that essentially brute forces a matrix to calculate the “square address”. Your method will also return an uninitialized pointer if x is greater than 8.
Your entire method could be made much simpler.
- (NSString *) convertCGPointToSquareAdress:(CGRect) point
{
unsigned int x = point.x / PIECE_WIDTH;
unsigned int y = point.y / PIECE_WIDTH;
// Do some range checking to ensure x and y are valid.
char lettreChiffre[3];
lettreChiffre[0] = 'a' + x;
lettreChiffre[1] = '1' + y;
lettreChiffre[2] = '\0';
return [NSString stringWithCString:letterChiffre encoding:NSASCIIStringEncoding];
}