need help debugging simple c program
Author |
Message |
Ryan Henness #1 / 2
|
 need help debugging simple c program
Ug... attachments... Nobody here likes downloading those. In future, please post your code *within* the body of your post. Here are your attachments for all to see: /* sender.c */ #include<stdio.h> int GetStr(char inputmsg[],int); void ConvertToBin(int asciivalue,int bin[]); void OutputBin(int bin[]); int main(void) { int bin[8],input=0; //setvbuf(stdout,NULL,_IONBF,0); //setvbuf(stdin,NULL,_IONBF,0); while(input!=EOF) { input=getchar(); if (input!=EOF) { ConvertToBin(input,bin); OutputBin(bin);} } return(0); Quote: }
void ConvertToBin(int asciivalue,int bin[]){ int index=0,emptybits=0,dividend,emptyindex; dividend=asciivalue; while (dividend>0) { bin[index]=dividend%2; dividend/=2; index=index+1;} emptybits=8-(index); for (emptyindex=0;emptyindex<emptybits;emptyindex+=1) { bin[index+emptyindex]=0;} return; Quote: }
void OutputBin(int bin[]) { int index,output,charout=0; for (index=7;(index>=0);index-=1) { output=bin[index]; if (output==1){ printf("%f ",5.0); printf("%f ",3400.0);} else { printf("%f ",5.0); printf("%f ",3000.0);} } return; Quote: }
/* receiv.c */ #include <stdio.h> int convert_to_ascii(int buf[]); void convert_voltage_and_frequency_to_binary(float,float,int bin[],int i); int main(void){ int index=0; int test=2; int bin[8]; float voltage,frequency=0; //setvbuf(stdout,NULL,_IONBF,0); //setvbuf(stdin,NULL,_IONBF,0); while (test==2){ for (index=0;(index<=7)&&(test==2);index++) { test=scanf("%f %f",&voltage,&frequency); if (test==2) convert_voltage_and_frequency_to_binary(voltage,frequenc y,bin,index); } if (test==2) convert_to_ascii(bin); } return(0); Quote: }
void convert_voltage_and_frequency_to_binary(float v,float f,int bin[],int i){ if (v<=6.0 && v>=4.0) { if (f<=3010.0 && f>=2990.0) bin[i]=0; else if (f<=3410.0 && f>=3390.0) bin[i]=1; else bin[i]=3;/*error bit*/ } else bin[i]=3; Quote: }
int convert_to_ascii(int buf[]){ int index=0,index2=0,multiplier=128; int ascii=0,error_flag=0; for (index=0;index<=7;index++){ if (buf[index]==3) error_flag=1; ascii+=buf[index]*multiplier; multiplier/=2;} if (error_flag==0) printf("%c",ascii); else printf("(E)"); return(ascii); Quote: }
|
Tue, 13 Jul 2004 02:55:24 GMT |
|
 |
Ryan Henness #2 / 2
|
 need help debugging simple c program
Quote: > /* sender.c */ > #include<stdio.h> > int GetStr(char inputmsg[],int);
This function is declared but never defined. Remove it. Quote: > void ConvertToBin(int asciivalue,int bin[]); > void OutputBin(int bin[]); > int main(void) { > int bin[8],input=0;
Assuming 8 bits per character is safe in many cases, but not all. Better to include <limits.h> and use CHAR_BIT everyplace you use hard-coded 8, so your code will be portable. Quote: > //setvbuf(stdout,NULL,_IONBF,0); > //setvbuf(stdin,NULL,_IONBF,0);
While legal in C99, I wouldn't use this style of comment, as many compilers don't understand yet. Quote: > while(input!=EOF) { > input=getchar(); > if (input!=EOF) { > ConvertToBin(input,bin); > OutputBin(bin);} > }
Here you are checking that input isn't EOF twice. A better loop construct would be while ( (input = getchar()) ! = EOF) { ConvertToBin(input, bin); OutputBin(bin); } Quote: return is not a function, and the brackets are unnecessary. Quote: > void ConvertToBin(int asciivalue,int bin[]){ > int index=0,emptybits=0,dividend,emptyindex; > dividend=asciivalue; > while (dividend>0) { > bin[index]=dividend%2; > dividend/=2; > index=index+1;} > emptybits=8-(index); > for (emptyindex=0;emptyindex<emptybits;emptyindex+=1) { > bin[index+emptyindex]=0;} > return; > }
While this function *does* correctly turn an integer into a series of 1s and 0s, you are doing unnecessary busy-work. Remember, that integers are already stored in binary representation. All you therefore need to do is use conventional bitwise operations to test your integer's bits. Quote: > void OutputBin(int bin[]) > { > int index,output,charout=0; > for (index=7;(index>=0);index-=1) > {
Here you outputting bits in reverse order (from MSB to LSB). As long as the receiver expects bits in this order, fine, but the reverse order is more common. Quote: > output=bin[index]; > if (output==1){ > printf("%f ",5.0); > printf("%f ",3400.0);} > else { > printf("%f ",5.0); > printf("%f ",3000.0);} > } > return; > }
Rewriting your sender.c file in the simplest possible form would look something like this: /* ryans_sender.c */ #include <stdio.h> #include <limits.h> #define TEST_BIT(int, bit_no) (int & (1 << bit_no)) void OutputIntAsBin(int asciivalue) { int bit_no; /* Test each bit from MSB->LSB, outputting the correct "frequency" */ for (bit_no = CHAR_BIT - 1; bit_no >= 0; --bit_no) { printf("%f %f ", 5.0, TEST_BIT(asciivalue, bit_no) ? 3400.0 : 3000.0); } Quote: }
int main(void) { int input; while ( (input = getchar()) != EOF) { OutputIntAsBin(input); } return 0; Quote: }
/* end ryans_sender.c */ Quote: > /* receiv.c */ > #include <stdio.h> > int convert_to_ascii(int buf[]); > void convert_voltage_and_frequency_to_binary(float,float,int bin[],int i);
Same comments apply -- too much work for simple binary conversion. Quote: > int main(void){ > int index=0; > int test=2; > int bin[8]; > float voltage,frequency=0; > //setvbuf(stdout,NULL,_IONBF,0); > //setvbuf(stdin,NULL,_IONBF,0);
Again, I would prefer /* */ style comments, as they compile everywhere Quote: > while (test==2){ > for (index=0;(index<=7)&&(test==2);index++) { > test=scanf("%f %f",&voltage,&frequency); > if (test==2)
Very good. You happen to have found one of the only uses for scanf in a loop. Scanf() has the irritating behaviour of leaving bad input in the stream on error, meaning it ends up looping over the same garbage forever. However, since we know the input will be in the form of two floats, we also know that error cannot possibly occur. Quote: > convert_voltage_and_frequency_to_binary(voltage,frequenc > y,bin,index); > } > if (test==2) convert_to_ascii(bin); > } > return(0); > }
Here you check that "test == 2" far too many times. Reoganize the loop so that one is enough. Quote: > void convert_voltage_and_frequency_to_binary(float v,float f,int bin[],int i){ > if (v<=6.0 && v>=4.0) { > if (f<=3010.0 && f>=2990.0) > bin[i]=0; > else if (f<=3410.0 && f>=3390.0) > bin[i]=1; > else > bin[i]=3;/*error bit*/ > } > else > bin[i]=3; > }
Very good. You correctly understand that directly comparing floats for equality doesn't yield the results one would expect. But a simpler way would be to discard the fractional part and use integer comparisons, as in if ((int) frequency == 3400) Quote: > int convert_to_ascii(int buf[]){ > int index=0,index2=0,multiplier=128; > int ascii=0,error_flag=0; > for (index=0;index<=7;index++){ > if (buf[index]==3) > error_flag=1; > ascii+=buf[index]*multiplier; > multiplier/=2;} > if (error_flag==0) > printf("%c",ascii); > else > printf("(E)"); > return(ascii); > }
As mentioned above, alot of work for simple binary conversion. Here is how I would rewrite your receiver program. /* ryans_receiver.c */ #include <stdio.h> #include <limits.h> #define SET_BIT(int, bit_no) (int |= (1 << bit_no)) int main(void) { float voltage, frequency; int bit_no; int rc; int original_ascii_value = 0; /* get input forever */ while(1) { /* iterate over each bit in a character */ for (bit_no = CHAR_BIT - 1; bit_no >= 0; --bit_no) { /* get pairs of floats to convert into a single bit (at position bit_no) */ if ((rc = scanf("%f %f", &voltage, &frequency)) == 2) { if ((int)frequency == 3400) SET_BIT(original_ascii_value, bit_no); /* else it is already set to 0 properly */ } else if (rc == EOF) { /* normally we would test to see if EOF was reached, as opposed to an error */ return 0; } } /* now we have a complete character, so output it */ putchar(original_ascii_value); /* reset the character for the next iteration */ original_ascii_value = 0; } Quote: }
As for your question, "I can't figure out why the program is sending out before it has reached EOF?", here is the answer: Your "OutputBin" function is where you make your calls to "printf" (hence outputting). Notice the loop construct where you call OutputBin: while(input!=EOF) { input=getchar(); if (input!=EOF) { ConvertToBin(input,bin); OutputBin(bin);} } Notice how OutputBin gets called everytime "input" *is not* EOF. Everytime you successfully read a character, you immediately (perform some operations to it and then) output floats. Reading EOF causes your program to exit this loop (and return). Reading anything that isn't EOF causes output. Understand? Hope this helps, Ryan.
|
Tue, 13 Jul 2004 04:53:31 GMT |
|
|
|