+ 2

Code coach

Hey , I solved this but is there an easy way or different way or maybe less lines ? AND Will practicing help me to reach that level ? https://code.sololearn.com/cVmtX7jp5Ssj/?ref=app

15th Dec 2022, 5:18 PM
Shimaa
Shimaa - avatar
38 Answers
+ 5
Dark this can be done without a two-dimensional array by moving the input inside the loop: char order[15]; for(int i =0;i<4;i++){ scanf("%s", order); if (strcmp(order,"Pizza")==0) price+=6; else if (strcmp(order,"Water")==0) price+=4; else if (strcmp(order,"Nachos")==0) price+=6; else if (strcmp(order,"Coke")==0) price+=5; else if (strcmp(order,"Cheeseburger")==0) price+=10; else price+=5; }
15th Dec 2022, 9:34 PM
Brian
Brian - avatar
+ 5
Dark as you develop a solution, and it starts getting complicated, take a step back and start pondering another approach to simplify it. Pretty often in my first draft of a program I discover all the wrong assumptions I made. Then I throw it away and write a better one. My version of the code is less flexible for future upgrades. Suppose the full original order would be needed later to print a receipt, for example. Then an array of strings would be useful. The data storage needs to accommodate the requirements.
15th Dec 2022, 11:41 PM
Brian
Brian - avatar
+ 4
A couple of ideas: You can read the input directly into your order array: scanf("%s%s%s%s", order[0], order[1], order[2], order[3]); This way you can already get rid of your 4 initial variables and the strcpy operations too. You could use a switch statement on the first letter of the string, because in this task actually every ingredient begins with a unique letter. Remove the price argument from your print statement, to get rid of the "wrong type" warning. printf("%.2f\n", t_price);
15th Dec 2022, 5:53 PM
Tibor Santa
Tibor Santa - avatar
+ 4
switch (order[i][0]) { case 'P': ...; break; ... }
15th Dec 2022, 8:44 PM
Tibor Santa
Tibor Santa - avatar
+ 3
Dark The cases in switch will be replaced by an integer value. that value is defined previously. like "case pizz:" is: case ('P'|('i'......... : price +=6; break; or: case pizz is "case 2054842704:" That value comes from making the int from ascii values of P,i,z,z and shifting and ORing the characters. int is 4 bytes so if you look at each byte, it is: zziP it's made in these steps: 000'P' 'P' | 'i'<<8 ('P' is the lowest byte of four, 'i' has moved 8 bits left and ORed with 'P' so now it is: 00iP then z 16 bits 0ziP finally another z shifted 24 bits left zziP of course you have to read that as a number that is their ascii code in each byte: 122 122 105 80 z z i P but if you read those 4 bytes as a whole (an int) that will be 2054842705 hopefully!
16th Dec 2022, 9:27 PM
Tina
Tina - avatar
+ 3
Brian why 8 bytes comparison (if you mean the switch) ? sizeof *(int *)char[] is 4 (unless size of pizz be 8)? but then again It doesn't guarantee to pass differ Cheeseburger from Cheesebuxxxxx. and the second version is even more dangerous as there's only 8 bytes but scanf will write more than 8 bytes there. am I right?
16th Dec 2022, 9:53 PM
Tina
Tina - avatar
+ 3
Tina 🕊🇺🇦🇮🇷 you are absolutely right about the danger of overflow. I upgraded it to use long long. Now it is just like the original by allowing 15 characters of input plus one more for a terminating null. And it compares the whole 16-byte char array as a number. This is why C is so much faster than other languages. It is the way that an assembly language programmer would implement it.
16th Dec 2022, 9:59 PM
Brian
Brian - avatar
+ 3
Tina 🕊🇺🇦🇮🇷 I tested my code some more and I was disappointed to find that (long long) is not twice as many bytes as (long) as I had thought. Both are 8 bytes according to sizeof. I made a few adjustments to compensate. Order is now an array of 2 to double its size. Since "Cheeseburger" is longer than 8 bytes, I added a second comparison to check the last 4 characters.
17th Dec 2022, 10:28 AM
Brian
Brian - avatar
+ 3
Brian well you know long double is 16 bytes, and with null you'll have 3 extra bytes. but don't bother yourself with it (at least in this case). I think just the strcmp is the safest and most reliable way. And what will happen to your code on an i686? or a 16 bit platform? or what if it was a wchar_t? so on... I just shortened my code using the ternary operator. it works fine (with a known bug). no speed improvements comparing to if/else/if but just shorter. https://code.sololearn.com/cE5Lpj5gLysi/?ref=app
17th Dec 2022, 5:50 PM
Tina
Tina - avatar
+ 3
Dark your approach was correct, I polished it. note that when editing sometimes code, write what you wanted to achive, fix, improve,... Also 0 and '0' and "0" are different, character 0 has ascii value of 48. when you need to null a string assign the first element null like string[0]='\0' , but char str[nnn]="0" is {48,0,0,....} Also when the array has defined char string[n]; later, string[n] = x; is out of boundary. it's [0..n-1] https://code.sololearn.com/cibxtd1OC4oj/?ref=app
19th Dec 2022, 9:27 AM
Tina
Tina - avatar
+ 3
Dark sure it's not! it is NULL. not Null, NUll, NuLL, null... and it's a "void *" type and is 8 bytes in size like other pointers. so in this case you can cast it like: (char) NULL. '\0' is integer representation of what you expected by "0" which is a string, like "1". You can also trim strings, like char[] a="abcdefgh"; a[3]=0; a[3]='\0'; a[3]=(char) NULL; all will result in "abc". how it works, yes, !0 is true and can be of any value. it's only false when it's 0.
20th Dec 2022, 2:39 AM
Tina
Tina - avatar
+ 2
Tibor Santa and that's how you fail, mixing up Cheeseburger and Coke! don't do that! 😁 Dark there's no unique character until order[i][2]. even then there might be something else on the list to interfere with order[i][n]
15th Dec 2022, 10:01 PM
Tina
Tina - avatar
+ 2
Tina 🕊🇺🇦🇮🇷 lol I am sorry I missed there are two C's 😅 You are perfectly right, I was throwing in an idea that I did not confirm myself. It was my mistake.
16th Dec 2022, 10:22 AM
Tibor Santa
Tibor Santa - avatar
+ 2
Tibor Santa allow me to redeem your switch/case idea. By casting the input string as an integer, a unique int value is in the first four bytes of the items: // Created by Dark // revamped by Brian #include <stdio.h> #include<string.h> int main (){ int price=0; float t_price=0; char order[15]; #define pizz ('P'|('i'<<8)|('z'<<16)|('z'<<24)) //2054842704 #define wate ('W'|('a'<<8)|('t'<<16)|('e'<<24)) //1702125911 #define nach ('N'|('a'<<8)|('c'<<16)|('h'<<24)) //1751343438 #define coke ('C'|('o'<<8)|('k'<<16)|('e'<<24)) //1701539651 #define chee ('C'|('h'<<8)|('e'<<16)|('e'<<24)) //1701144643 for(int i =0;i<4;i++){ scanf("%s", order); switch(*(int*)order) { case pizz: price += 6; break; case wate: price += 4; break; case nach: price += 6; break; case coke: price += 5; break; case chee: price += 10; break; default: price += 5; } } t_price=price+(price*.07); printf("%.2f\n",t_price ); return 0; } https://code.sololearn.com/ch6OHXo8n7Pg/?ref=app
16th Dec 2022, 5:42 PM
Brian
Brian - avatar
+ 2
Brian such a brilliant idea! but unfortunately it still fails 😔 anyways... it's a gem! 😁 there must be something like Pizzapie,waterwaste,cheesecake or cokenmary in test case 5 😂 Dark Brian is such a talented and experienced coder! helped me a lot.
16th Dec 2022, 6:50 PM
Tina
Tina - avatar
+ 2
Tina 🕊🇺🇦🇮🇷 thank you for testing my code. The code passes all tests if I double the number of test characters by using long instead of int. Before, it compared only the first four characters as an int. Now it compares up to eight characters at once as a long. In my testing it revealed a bug that I had to fix. I realized that the comparison always compares 8 bytes, even if the input string is shorter than 8 bytes. I needed to clear the first 8 bytes of order every time through the loop so as to ensure it was not comparing old characters past the terminating null that were left over from the previous input. https://code.sololearn.com/cYE15zeARbWM/?ref=app Next, I realized that I could replace the char array altogether with a long long. It passes the tests. Maybe this is easier to read. (The trick is to cast order as a string pointer in scanf). https://code.sololearn.com/ca1EY71g0379/?ref=app
16th Dec 2022, 9:06 PM
Brian
Brian - avatar
+ 2
Brian That's right! I was thinking the same about asm. but me being skeptical, would use the first code (surprisingly that was how I had written it long ago except I had used a single float price += price*0.07 and with no length limit mentioned in the problem I used char[200]) Overall brilliant code, but no need to rush unless there were like xxMegs of compares. Again, bravo! 👍
16th Dec 2022, 10:18 PM
Tina
Tina - avatar
+ 2
Tina 🕊🇺🇦🇮🇷 I considered float types, and even privately wrote an if/else version, but I wanted to make it work with Tibor Santa's idea of switch/case, so it had to be integer. It is unfortunate that historically C has no standard for int sizes, so my approach is not fully portable. I always admire portable code that is concise, yet easy to read and maintain. Your bp.2 program meets all those qualifications!
17th Dec 2022, 8:54 PM
Brian
Brian - avatar
+ 1
Brian I spent 4 hrs to actually figure out how to input , process and out put the values 😅😅 I always find it hard to whether I need to storage the data then processing it , or i just need to read the input and process at the same time as I won't need it again. When i saw ur code i felt like wow this easy why u took so long 😂😂😂😅😅
15th Dec 2022, 9:41 PM
Shimaa
Shimaa - avatar
+ 1
#define statement is called a template or macro, before compilation it replaces the name with the value inside the code. It works like a search&replace. So it puts all those conditions inside the switch statement. How the actual matching works here, is still not clear to me 😅 Somehow the expression is using bitwise operations on characters...
16th Dec 2022, 8:54 PM
Tibor Santa
Tibor Santa - avatar