[โ€“] [S] 2 points 6 months ago* (last edited 6 months ago) (3 children)

I've been at it for two days without researching and I can't figure out how to "hand over" the updates of the history array from within my "new pin" function to the main() function. I have to learn about scopes. Good fun!

  • source
  • parent
  • context
  • [โ€“] 2 points 6 months ago* (last edited 6 months ago) (5 children)

    The else is definitely not needed, you can delete it.

    As for the best way to climb out of a nested loop, this is one of the occasions that a goto is reasonable. The jump would be relatively short and localised, which is exactly what GOTO should be used for:

    What's with the getchars slapped everywhere? I think its an attempt to flush stdin, but I think you need to do it repeatedly until you hit a newline or EOF.

    I think your next step is to refactor the code into some functions, you have two nearly identical code sections for adding a new pin, you can make that a function and simplify it.

  • source
  • [โ€“] 6 points 6 months ago* (1 child)

    an " if ... else ... " always needs an else to be an "if ... else" statement ;)

    but you can just create an "if..... " statement So you can change

    		}  
    		if (choice == 'E') break;  
    		else;  
    	}  
    	printf("\nGoodbye!\n");  
    	return 0;  
    }  
    
    

    into

    		}  
    		if (choice == 'E') break;  
    	}  
    	printf("\nGoodbye!\n");  
    	return 0;  
    }  
    
    
  • source
  • [โ€“] [S] 2 points 6 months ago* (last edited 6 months ago)

    Ah, forgot about those. Thanks! On Linux, I read man pages all the time. Need adopt that same rutine.

    Regarding getchar() returning the ASCII code of the input, I commented this is the OP:

    getchar() will return the ASCII value of chars and ints if I use the format specifier %d.

  • source
  • parent
  • context
  • [โ€“] 3 points 6 months ago* (last edited 6 months ago) (1 child)

    man scanf:

    RETURN VALUE
           On success, these functions return the number of input items successfully  matched
           and  assigned;  this can be fewer than provided for, or even zero, in the event of
           an early matching failure.
    

    man getchar:

    RETURN VALUE
           fgetc() and getchar() return the character read as an unsigned char cast to an int
           or EOF on end of file or error.
    

    There are a lot of inconsistencies with C functions, so important to check the man pages so you can handle them correctly.

    Your call to getchar isn't quite correct either, pressing the 1 key would print out 49, which is the ASCII codepoint for the 1 char.

  • source
  • [โ€“] 3 points 6 months ago

    ah fun! have you checked out ben eater's ongoing youtube series of building a breadboard computer? he's selling kits that allow you to follow along from hardware through binary, assembly, to BASIC and C. well worth a look imo.

  • source
  • parent
  • context
  • [โ€“] [S] 2 points 6 months ago (1 child)

    Thanks! Ultimately, down the road, I want to try Assembly and then those languages that give CPUs instruction sets. I am interested in the borders where readable code turns into binary. I just chose C to begin with because I was influenced by Linux and a colleague who used to work with C many years ago.

  • source
  • parent
  • context
  • [โ€“] 3 points 6 months ago* (4 children)

    you can absolutely save history in an array, but depending on how you want to do it, it can get very complex for a beginner.

    the absolutely easiest way to go about it with how you've structured the program so far is making global arrays of just numbers, one for C->F conversions and one for the other way round. you also need to keep track of where in each array you are so you don't go out of bounds. this requires minimal changes.

    float c_to_f[5] ={0,0,0,0,0};
    int c_to_f_length = 5;
    int c_to_f_index = 0;
    

    and update your input handler:

    scanf("%d", &c_value);
    c_to_f[c_to_f_index] = c_value;
    c_to_f_index++;
    if (c_to_f_index >= c_to_f_length) c_to_f_index = 0;
    

    and then when you want to see the list results, you do

    for (int i = 0; i < c_to_f_length; i++) {
        printf("%d\n", c_to_f[i];
    }
    

    this will of course not be in order of insertion, and if you want to show more than just the numbers you need to do some tinkering.

    this is however a great jumping-off point to talk about many different concepts:

    • do you feel like you're just writing the same thing over and over? look into encapsulation and refactoring your program to minimise repetition.
    • do you want to store more information about each entry? time to learn about structs.
    • do you want to store as many entries as you want, without having to specify? go learn about linked lists.
    • do you want to be able to step back and forward through your history? check out the readline library, and learn how to do imports generally.

    sorry if my formatting is off, i did this on my phone...

  • source
  • [โ€“] 4 points 6 months ago* (2 children)

    For saving the history inside of one program run, an array is enough. For saving the history over multiple program runs (over closing by typing and invalid character or ctrl+c and restarting it), you would need to store it in a file.

    You can already print the last conversion by reading the value of f_value/c_value without writing to it (note that if no conversion of that type has happened before, you will get garbage, and that you will have to modify the if at the start of the loop to check for 'x' too):

    		if (choice == 'x') {  // x is the letter left of c, so i chose it as an easy example
    			// we want to print the previous conversion, so we don't want to read in a new value.
    			// printf("\nEnter the temperature in Celcius: ");  
    			// scanf("%d", &c_value);  
    			// you might need to comment this getchar() back in so your program skips over the enter after the x, but i am not sure.
    			// getchar();  
    			// no modification of the following line is needed, as the c_value of the last celcius conversion was never written too and as such still exists.
    			printf("\n%d degrees Celcius is %.1f degrees Fahrenheit.\n", c_value, toFahrenheit(c_value));  
    		}  
    

    For a longer history you need some extra places to store the numbers. if you use an array, you need to store the length of the history too, since c does not store how far into the array you have written.

    // at the start of your main function, where you also declare the other variables
    	// allocate the array with fixed length
    	int last_c_values[16];
    	// and store how many values you've written to it. Initialize it to zero so you don't do garbage with it later on.
    	int last_c_values_count = 0;
    
    // after printing the conversion from celsius to farenheit
    			if (last_c_values_count < 16) // we can't handle a history longer than that yet
    				// copy over the current value into the array, the first one will be at index 0
    				last_c_values[last_c_values_count] = c_value;
    				// increase the counter so the next value will be at the next place
    				last_c_values_count = last_c_values_count + 1;
    				// or shorter: last_c_values_count++;
    			}
    
    //and the new choice for printing the stuff
    		if (choice == 'x') {  // x is the letter left of c, so i chose it as an easy example
    			// start at 0, as long as i is below last_c_values_count, increment i by one at the end of each loop run
    			for (int i = 0; i < last_c_values_count; i++) {
    				// copy the value from last_c_values at index i into c_value
    				c_value = last_c_values[i]; 
    				// and do the same calculation as before again.
    				printf("\n%d degrees Celcius is %.1f degrees Fahrenheit.\n", c_value, toFahrenheit(c_value));  
    			}
    		}
    

    PS: the for loop in here is equivalent to the following while loop:

    			int i = 0;
    			while (i < last_c_values_count) {
    				// copy the value from last_c_values at index i into c_value
    				c_value = last_c_values[i]; 
    				// and do the same calculation as before again.
    				printf("\n%d degrees Celcius is %.1f degrees Fahrenheit.\n", c_value, toFahrenheit(c_value));  
    				i++;
    			}
    
  • source
  • [โ€“] [S] 1 point 8 months ago* (1 child)

    I am still interested and even found some new things. I completely agree with reading the source code to be the best way to learn.

    Here are some other resources I'd consider worth mentioning over here also for anyone reading this in the future:

    edit: fixed the links

  • source
  • parent
  • context
  • [โ€“] 2 points 8 months ago (2 children)

    If you're still interested, I've found tons of interesting techniques in open source projects, like CC and right now reading GLib source code, as I'm mostly interested in compile time guarantees and generic programming, I'd suggest starting with CC's source code.

  • source
  • [โ€“] 3 points 9 months ago* (last edited 9 months ago) (1 child)

    A free book is Modern C, Third Edition, which covers C23. You will want to use section 3 only as a reference. Because that last section covers advanced topics such as threading where you will probably choose another language rather than implement your program in C. But this book covers some essentials not in K&R, such as unicode.

  • source
  • view more: โ€น prev next โ€บ