So this is in german, but I have to write a function in C but it does not work out. Can you tell me where my mistake is?
The task is the one Iam writing down now.
Write a function "time_converter( )" which converts the time from one unit to another. The function is passed the case (i.e. which conversion is to be performed) and the number to be converted in exactly this order.
The case is given a number between 1 and 6 and the number to be converted is given as a natural number. The result of the conversion is to be returned to 2 digits exactly at the end of the function.
The following cases are to be implemented:
from second to minute
from second to hour
from minute to hour
from hour to minute
from hour to second
from minute to second
int zeit_umrechner(float z, char e, char ee ){
if (e==sekunde && ee==minute)
{return z/60;}
if (e==sekunde && ee== stunde)
{return z/3600;}
if (e==minute && ee== stunde)
{return z/60;}
if (e==stunde && ee== minute)
{return z*60;}
if (e==stunde && ee== sekunde)
{return z*3600;}
if (e==minute && ee== sekunde)
{return z*60;}
return 0;
}
I tried, but it does not work out.
There seems to be bits missing from the example, but taking into account of what you appear to be attempting to create a time conversion function, and noting the comments that regarding your function signature that should not have a definition of 'stdin' in it, I filled in some missing pieces to devise a code snippet that should provide the functionality that you are after.
#include <stdio.h>
#include <stdlib.h>
char sekunde = 's'; /* Not in your example - but they would need to be defined as globale somewhere in order to work in the function */
char minute = 'm';
char stunde = 'h';
int zeit_umrechner(float z, char e, char ee ){
if (e==sekunde && ee==minute)
{return z/60;}
if (e==sekunde && ee== stunde)
{return z/3600;}
if (e==minute && ee== stunde)
{return z/60;}
if (e==stunde && ee== minute)
{return z*60;}
if (e==stunde && ee== sekunde)
{return z*3600;}
if (e==minute && ee== sekunde)
{return z*60;}
return 0;
}
int main()
{
float entry;
char from_unit, to_unit;
printf("Enter time value: ");
scanf("%f", &entry);
printf("Enter current unit s/m/h: ");
scanf(" %c", &from_unit);
printf("Enter unit to convert to: ");
scanf(" %c", &to_unit);
printf("Time conversion is: %d\n", zeit_umrechner(entry, from_unit, to_unit));
return 0;
}
The bits to note here.
Since the character values in your function are not defined within your function, they would need to be defined as global variables or within "#define" statements, which was added to the snippet.
The function signature was cleaned up to provide the most likely scenario for parameter passing.
A sample setup of input and a call was added to the main function to test out the function.
With that, following is some sample output.
#Dev:~/C_Programs/Console/TimeConvert/bin/Release$ ./TimeConvert
Enter time value: 3600
Enter current unit s/m/h: s
Enter unit to convert to: h
Time conversion is: 1
This is only one possible ways to do this, but give it a try and see if it meets the spirit of your project.
This is a function to convert time from one unit to another. For example, seconds to minutes.
It takes the time as a float, for example 1.23, and then the from/to units (e and ee) as strings. The string type in C is char *. Since you don't plan on modifying the strings, we'll use const char * to tell the compiler they are constant and to warn us if we change them.
Furthermore, sekunde and minute are also strings. Without quotes they are considered variables. They should be in quotes, "sekunde" and "minute".
You can't compare strings with ==. That only works on numbers. You need to use strcmp ("STRing CoMPare"). This returns 0 on match.
Finally, I've taken the liberty of using a more standard style.
int zeit_umrechner(float z, const char *e, const char *ee ) {
if (strcmp(e, "sekunde") == 0 && strcmp(ee, "minute") == 0) {
return z/60;
}
if( strcmp(e, "sekunde") == 0 && strcmp(ee, "stunde") == 0 ) {
return z/3600;
}
//and so on
}
You can make this a bit more compact by using nested if statements.
int zeit_umrechner(float z, const char *e, const char *ee ) {
if (strcmp(e, "sekunde") == 0) {
if(strcmp(ee, "minute") == 0) {
return z/60;
}
else if(strcmp(ee, "stunde") == 0) {
return z/3600;
}
}
// and so on
}
Note that because you're returning an int you will only get whole numbers back. For example, zeit_umrechner(90, "sekunde", "minute") will return 1 because 90/60 is 1.5 which is truncated to 1.
Related
The following is the code that I wrote. I feel like I have missed something with the pointer or might have made mistake in the calculation. But as for as I see, everything seems good for me but when I enter, for example: hello or anything else, it gives me 0.00 as output.
The below is correct
Enter a number:
6
Your number is: 6.00
But this why?
Enter a number:
h
Your number is: 0.00
Following is the complete code:
#include <stdio.h>
#include <stdlib.h>
#define SIZE 250
float myAtof(char *string, char *error);
int main() {
char string[SIZE]; // Array declaration.
float fnum1;
char errorState=0;
printf("Enter a number:\n");
gets(string);
fnum1=myAtof(string,&errorState);
if (errorState == 0) {
printf("Your number is: %.2f \n", fnum1);
} else if (errorState == 1) {
printf("Error has been occurred due to inappropriate input!\n");
}
return 0;
}
float myAtof(char* string, char* error) {
*error != '1';
float num= 0;
float decimalFlag = 1;
int decimalNumberFound = 0;
for (int i = 0; string[i]!= '\0'; i++) {
char ch = string[i];
if (ch != '.' && (ch < '0' || ch >'9')) {
error ='1';
return 0;
}
if (decimalNumberFound == 1 && ch == '.') {
error = '1';
return 0;
} else {
num = num* 10 + (ch - '0');
if (decimalNumberFound == 1)
decimalFlag *= 10;
}
}
num = num / decimalFlag;
return num;
}
Since your myAtof routine has a parameter for reporting an error and your main routine tests the error-reporting variable, errorState, presumably you expect the program to print an error message when you enter “h” or other non-numerals, and your question is why it prints “0.00” rather than the error message.
In the function declared with float myAtof(char* string, char* error), error is a pointer, and *error is the thing it points to. So, when the code executes error = '1';, that attempts to set the pointer to '1'. It does not change the thing it points to.
When you compiled this, the compiler issued a warning message, something like “warning: incompatible integer to pointer conversion assigning to 'char *' from 'int'”. You should not have ignored that message.
The function also contains the statement *error != '1';. That statement does nothing. It says to compare the value of *error to '1' to see if they are unequal. The result of the != operator is 1 or 0 indicating whether the values are unequal or not. But the statement does nothing with that result. It is just discarded, so the statement has no effect.
Nothing in your function changes the value of *error, so the thing it points to, errorState in main, is never changed. So main does not see that an error has occurred. It evaluates errorState==0 as true and executes printf("Your number is: %.2f \n", fnum1);.
To fix this, delete the statement *error != '1'; and change the two error = '1'; statements to *error = '1';.
Additionally, change '1' to 1. Setting *error to '1' sets it to the code for the character “1”. It does not set it to the value 1, which is what errorState == 1 tests for. Typically, an error status would be either 0 or 1, not 0 or '1'.
Also change else if (errorState == 1) to else. When you have an if and else that are intended to completely select between some condition X and its alternative, you do not need a second test. With your code if (X) { … } else if (Y) { … }, the first { … } is executed if X is true, the second { … } is executed if X is false and Y is true, and neither is executed if X is false and Y is false. But it should never be the case that X is false and Y is false—you want the program always to either have a number or have an error status. There should be only two possibilities, not three. So use just else, not else if.
(Conceptually, it is a bug for the program to have errorState be something other than 0 or 1, so the program would never have both X false and Y false if it were working, and the else if would be okay. But you did have a bug, and that would cause neither { … } to be executed. Designing the code to use else instead of an unnecessary else if makes it a little more resistant to misbehaving when there is a bug. Designing programs to be robust in this way is useful.)
Also pay attention to warning messages from your compiler. Preferably, tell the compiler to treat all warnings as errors, so that your program will not compile while warning messages remain. If you are using GCC or Clang, use the -Werror switch. If you are using Microsoft Visual C++, use /WX.
I am working on a homework assignment focusing on strings for an Intro to C class. I am having trouble using the strcmp() function within an if statement, within a user-defined function.
The assignment requires us to use a user-defined function (mine is Check()) to check whether two strings are the same (comparing a user-inputted string to a string from a file). For some reason, my professor wants Check() to return a 1 if the strings match and a 2 if the strings don't match, even though to my knowledge strcmp() already returns 0 if the strings match and some other value if they don't.
Once my Check() function returns a value (x=1 for match, x=2 for no match), I run that x value through another if statement within my main function that should print "You are correct" for x=1, and "You are incorrect" for x=2.
The problem I am having is that no matter whether the strings match or not, my conditional within my main function always tells the user they are correct, i.e. the strings match. I assume the issue lies within my Check() function and my use of strcmp(), as I am not entirely familiar with how strcmp() works.
I have already tried modifying my conditional within Check() so that I have if(strcmp(solution, guess)==0) followed by else if(strcmp(solution, guess)!=0), and that did not fix my problem.
My user defined function:
int Check(char solution[], char guess[])
{
if (strcmp(solution, guess) == 0)
{
int x = 1;
return x;
}
else
{
int x = 2;
return x;
}
}
This is fed to my main function as:
Check(solution, guess);
if (x == 1)
{
printf("Congratulations, you guessed correctly");
}
else if (x == 2)
{
printf("You guessed incorrectly");
}
When solution = "FLORIDA" and guess = "FORLIDA", "You guessed incorrectly" should be printed, but "Congratulations, you guessed correctly" is instead.
You are not assigning the return value to any variable.
Write
x = Check(solution, guess);
before the if statement.
if (x == 1)
{
printf("Congratulations, you guessed correctly");
}
else if (x == 2)
{
printf("You guessed incorrectly");
}
in fact instead of else if you can write just else because there are only two possibilities.
So without the variable x the if statement may be rewritten like
if ( Check(solution, guess) == 1 )
{
printf("Congratulations, you guessed correctly");
}
else
{
printf("You guessed incorrectly");
}
Take into account that the function can be defined simpler
int Check( const char solution[], const char guess[] )
{
return strcmp( solution, guess ) == 0 ? 1 : 2;
}
I am trying to write a program which calculates and prints the GC content of a string of DNA(which is input through a txt file). That is, the percentage of G's and C's in a string of DNA. Here is my function for the GC percentage:
void updateGCCount(char s[], int *gc, int *at) {
char c[MAXLENGTH];
int i,GCcount,ATcount;
float len,GCpercentage;
GCcount=0;
ATcount=0;
for(i=0;c[i]!='\0';++i)
{
if(c[i]=='G' || c[i]=='C')
{
++GCcount;
*gc=GCcount;
}
if(c[i]=='A' || c[i]=='T')
{
++ATcount;
*at=ATcount;
}
}
strcpy(c,s);
len=strlen(c);
GCpercentage=*gc/len;
printf("GC-content: %.2f\n",GCpercentage);
}
This is my function definition, and the part which is supposed to correctly print the GC percentage is what I am not sure about. Below is my main program which utilizes the input text file.
#include "genomics.h"
int main(){
char s[MAXLENGTH];
int gc, at;
scanf("%s",s);
printf("Sequence : %s\n",s);
updateGCCount(s, &gc, &at);
return 0;
}
Any help or advice on why I am not getting a correct value for the GCpercentage would be great. Thank you in advance
You're doing your tests on char array "c":
char c[MAXLENGTH];
...
for(i=0;c[i]!='\0';++i)
{
if(c[i]=='G' || c[i]=='C')
{
++GCcount;
*gc=GCcount;
}
if(c[i]=='A' || c[i]=='T')
{
++ATcount;
*at=ATcount;
}
}
If should be on s, the array that you passed in. The c array is probably superflous, you should be able to get the length from s as well
c is not initialize, so *gc and *at are not updated at all and they contain garbage..
here you should use s instead of c
for(i=0;c[i]!='\0';++i)
{
if(c[i]=='G' || c[i]=='C')
{
++GCcount;
*gc=GCcount;
}
if(c[i]=='A' || c[i]=='T')
{
++ATcount;
*at=ATcount;
}
}
That's a strongly un-idiomatic program. Consider the following.
#include <stdio.h>
#include <stdlib.h> /* for exit(3) */
float count_gc(const char* s)
{
You have no need to pass information back via variables passed in by reference. Functions return values -- typically 'the answer'.
You're simply scanning the content of the argument string s, so there's no need to copy it anywhere.
As others have pointed out, you were scanning the contents of the array c[] before you copied anything in to it -- you were counting 'G' and 'C' in a (probably large) random block of memory. Keeping things simple avoids mistakes like that.
int nvalid = 0;
int gccount = 0;
float result;
for (; *s != '\0'; s++) {
Although the for loop you wrote isn't wrong, it's somewhat un-idiomatic. Here, we examine the character pointed to by the pointer s, and then increment the pointer, until we find ourselves pointing at the \0 that terminates the string. Yes, this means we 'lose' the initial value of the argument, but we don't need it after the loop, so that doesn't matter.
switch (*s) {
A switch is a more natural construction here. You're looking for a small set of possible values that *s (that is, the character the pointer is currently pointing at) may have.
case 'G':
case 'C':
nvalid++;
gccount++;
break;
case 'A':
case 'T':
nvalid++;
break;
default:
/* unexpected character -- ignore it */
break;
Every switch statement should have a default clause -- one should always think of what's supposed to happen if none of the case clauses match. In this case, we just ignore this character.
}
}
if (nvalid == 0) {
fprintf(stderr, "No valid letters found!\n");
result = 0.0;
} else {
/* Multiply by 1.0 to convert integer gccount to a float */
result = 1.0*gccount / nvalid;
}
return result;
We return the result to the caller rather than printing it out inside the function. Functions shouldn't 'chatter', but leave all of the I/O in one place, typically leaving the main function (or something higher up) to look after that.
}
int main(int argc, char** argv)
{
if (argc != 2) {
/* Give the user a hint on how to call the program */
fprintf(stderr, "Usage: gcat <string>\n");
exit(1);
}
printf("Sequence GC-content = %g\n", count_gc(argv[1]));
}
I run that with:
% cc -o gcat gcat.c
% ./gcat "GCAT ATx foo"
Sequence GC-content = 0.333333
%
With C, it's very easy to tie yourself in knots, very quickly. Aim for simplicity always.
I have a function that should be passed a string with two numbers (as a regex: /-?[0-9]+ -?[0-9]+/) and return the second.
I've decided that the program should do error checking. First, it should test if the string is actually of the desired form; second, it should ensure that the first numbers (the ones that are not returned) are sequential.
Now I've been programming for a long time and this is not a difficult task. (It's made slightly more difficult by the fact that the numbers need not fit into a machine word.) But my question is about how I should do this rather than how I can. All of the solutions I've come up with are somewhat ugly.
I could use a global variable to keep the values in and compare them (or just leave the value there if it's NULL); this seems like The Wrong Thing.
I could pass one or both of the return value and the last/current line's first number by reference and modify them
I could use the return value to give a bool for there was/was not an error
etc.
So any thoughts relating to the proper way to deal with error-checking of this sort in C would be welcome.
This is related to a much more theoretical question I asked on cstheory. For reference, here is the function:
char*
scanInput(char* line)
{
int start = 0;
while (line[start] == ' ' || line[start] == '\t')
start++;
if (line[start] == '#')
return NULL; // Comment
if (line[start] == '-')
start++;
while (line[start] >= '0' && line[start] <= '9')
start++;
while (line[start] == ' ' || line[start] == '\t')
start++;
int end = start;
if (line[end] == '-')
end++;
while (line[end] >= '0' && line[end] <= '9')
end++;
if (start == end)
return NULL; // Blank line, or no numbers found
line[end] = '\0';
return line + start;
}
and it is called like so:
while(fgets(line, MAX_LINELEN, f) != NULL) {
if (strlen(line) > MAX_LINELEN - 5)
throw_error(talker, "Maximum line length exceeded; file probably not valid");
char* kept = scanInput(line);
if (kept == NULL)
continue;
BIGNUM value = strtobignum(kept);
if (++i > MAX_VECLEN) {
warning("only %d terms used; file has unread terms", MAX_VECLEN);
break;
}
// values are used here
}
The traditional solution in C is to use pass by reference (pointers) to return the values your function computes and use the return value for error handling, just like how scanf does this.
int scanInput(char **line_p int *number){
char * line = *line_p;
...
if(something bad happens){
return 1;
}
...
*linep = line + start;
*number = ...;
return 0; //success
}
int main(){
char word[100]; strcpy(word, "10 17");
char *line = word;
int number;
switch(scanInput(&line, &number)){
case 1:
default:
}
}
Extra points:
It might be a good idea to use some enum to give a meaning to the error codes.
If you can use C++ (or similar) exceptions are often the best solution for error handling, since you don't have to fill your code with ifs anymore
Global variables are generaly evil. If you are tempted to use them, consider instead encapsulating the state you need in a struct and passing a pointer to it around. Treat it as a "this" pointer, in the OO sense.
Ultimately, you are going to need to isolate and convert both big numbers in each line. To check that the first number on the line is the one that follows the previous, you will have to keep a record of the last such number found. So, you will probably need a structure such as:
BIGNUM old_value = 0; // See notes below
while (fgets(line, sizeof(line), f) != 0)
{
BIGNUM value1;
BIGNUM value2;
if (ScanDoubleBigNum(line, &value1, &value2) != 0)
...handle line format error...
if (old_value == 0 || are_consecutive(old_value, value1))
{
// OK - valid information found
// Release old_value
old_value = value1;
process(value2);
// Release value2
}
else
...handle non-consecutive error...
}
The are_consecutive() function determines whether its second argument is one greater than its first. The process() function does whatever you need to do with the second value. The ScanDoubleBigNum() function is related to your ScanInput() but it reads two values. The actual code will call another function (call it ScanBigNum()) containing about half of ScanInput() (since that contains essentially the same code twice), plus the conversion that currently occurs in your loop. The code in ScanDoubleBigNum() will call ScanBigNum() twice. Note that ScanBigNum() will need to identify where the scan finishes so that the second call can continue where the first stopped.
I'm taking the liberty of assuming that a BIGNUM is an allocated structure identified by a pointer, so the initialization BIGNUM old_value = 0; is a way of indicating there is no value yet. There is presumably a function to release a BIGNUM. If this is incorrect, then you need to adapt the proposed code to accommodate the actual behaviour of the BIGNUM type. (Is this based on OpenSSL or SSLeay code?)
My assignment is to fix the code. I have my edited code below and the original code below that. I figure I still have a few errors in here. My error checking doesnt seem to work, and I am not sure if my getchar() function is written or working properly.
Please assume I know nothing becasue that is fairly accurate.
The code compiles, but the answer is always 2. I am about 4 hours into this piece of code with 3 more to work after this.
My code
#include <stdio.h>
double get_number(double num);
main () {
double n1,n2,n3;
double average;
printf("\nCompute the average of 3 integers\n");
printf("--------------------------------\n");
n1 = get_number(1);
n2 = get_number(2);
n3 = get_number(3);
average = (n1 + n2 + n3)/3;
printf("The average is %0.2f\n",average);
}
double get_number(double num) {
double value = 0;
char c;
int i;
printf("Please input number %d: ", num);
while (c = getchar != '\n') {
if ( (c>9) || (c<0) ) {
printf("Incorrect character entered as a number - %c\n",c);
return(0);
}
else {
value = num;
}
}
return(value);
}
Original code
#include <stdio.h>
main () {
double n1,n2,n3;
double average;
printf("\nCompute the average of 3 integers\n");
printf("--------------------------------\n");
n1 = get_number(1);
n2 = get_number(2);
n3 = get_number(3);
average = (n1 + n2 + n3)/3;
printf("The average is %0.2f\n",average);
}
double get_number(int num) {
double value = 0;
char c;
printf("Please input number %d: ", num);
while (c = getchar() != '\n') {
if ( (c<=9) && (c>=0) ) {
printf("Incorrect character entered as a number - %c\n",c);
exit(-1);
}
else {
value = 10*value + c - '0';
}
}
return(value);
}
A few issues:
1. You should be using '9' and '0', since you want the ASCII values for digit '9' (0x39) and '0' (0x30), not 0x9 and 0x0.
if ( (c>'9') || (c<'0') ) {
2. != has higher precedence than =, so you need parens. Learn operator precedence, and if you're in doubt, use parens:
3. getchar is a function not a variable.
while ((c = getchar()) != '\n') {
4. You use the wrong conversion. num is a double, so you would need %f. Or, you could make num a int.
printf("Please input number %f: ", num);
5. You never actually use c in any way (except error checking). You always return 0 or num (see your else clause), which makes no sense. The else body of the original is correct.
You got the floating point parsing all wrong and shouldn't be doing it yourself. There's an easier way:
double get_number(double num) {
double value = 0.0;
printf("Please input number %lf: ", num);
scanf("%lf", &value);
return(value);
}
The issues with the original program are:
getchar() returns an ASCII code, and the condition was wrong. When checking for boundaries, use ((c<'0') || (c>'9')).
For the exit function you need to include "stdlib.h".
For the main function to understand what is get_number, you need to either move the function to be before the main function, or you can use a forward declaration.
The assignment operator (=) has lower precedence than the inequality operator (!=), so you need to use parenthesis, like: ((c = getchar()) != '\n')
You have actually created several more issues, so I wouldn't rely on your code.
In any case, in general - it is advised you study how to use a debugger. Once your code is compiling (and for that you'll need to get accustomed to the compilation error messages), you need to start debugging your code. I suggest you take some time to learn how to set breakpoints, set watches, and go step by step into your code. That skill is absolutely essential for a good developer.
Here's how I'd go about correcting the code ...
http://ideone.com/a0UMm -- compilation errors
http://ideone.com/ljUg1 -- warnings, but it works now
http://ideone.com/Qd0gp -- no errors, no warnings, test run ok
For 1. I used the "original code" as posted by you.
For 2. I used int main(void), declared the function get_number before defining main, added parenthesis in line 20, and added #include <stdlib.h>
For 3. I added return 0; before the final } of main. I also removed the extra output that messed up the ideone interface (it looks better on an interactive interface)
Edit more tests needed to complete the task of correcting the original code