Please give me some feedback on how to make my code better or more efficient. It should convert a decimal integer to binary.
#include <stdio.h>
binarydigits(int div, int dis)
{
int numit;
numit=0;
do
{
++numit;
div /= dis;
}
while (div!=1);
++numit;
return numit;
}
main()
{
int x, nb, i;
printf("\n Input an decimal integer number to be converted: ");
scanf("%d", &x);
fflush(stdin);
if (x==0 || x==1)
{
printf("\n\n %d in binary : %d", x, x);
}
else
{
printf("\n\n %d in binary : ", x);
nb = binarydigits(x, 2);
// the function 'binarydigits' returns how many binary digits are needed to represent 'x'
int remind[nb];
// an array of 'nb' elements is declared. Each element of this array will hold a binary digit
for(i=(nb-1) ; i>=0 ; --i, x/=2)
{
remind[i] = x%2;
}
//this 'for' structure saves the remainder of 'x/2' (x%2) in an element of the 'remind[nb]' array
for (i=nb ; i>0 ; --i)
{
printf("%d", remind[nb-i]);
}
//this 'for' structure prints the elements of the 'remind[nb]' array in increasing order
}
getch();
return 0;
}
Any tips on how to make this better would be nice.
Firstly, binarydigits should have a return type int. This is because you return an integer variable numit at the end of this function. Change your function header to:
int binarydigits(int div, int dis)
Secondly, the main() function needs to have a return type int by definition in C, and C++ for that matter. Without it, your compiler will produce a warning, something similar to:
main.c:18:1: warning: return type defaults to 'int' [-Wimplicit-int]
main()
^~~~
Here is a snippet from the the C11 standard (ISO/IEC 9899:2011) on the definition of the main() function:
The function called at program startup is named main. The implementation declares no prototype for this function. It shall be defined with a return type of int and with no parameters: - Return Type of main()
int main(void) { /* ... */ }
Thirdly, you should remove fflush(stdin) because using the fflush() for stdint is undefined behavior as it is not a part of standard C. From C11 7.21.5.2, fflush works only with output/update stream, not input stream:
If stream points to an output stream or an update stream in which the most recent operation was not input, the fflush function causes any unwritten data for that stream to be delivered to the host environment to be written to the file; otherwise, the behavior is undefined. - fflush(stdin)
How to make my code better or more efficient?
My advice to you is to stop trying to learn C by trial-and-error method. You should obtain a good book and study it first. It is impossible to create a fast and efficient C program without mastering pointers, bitwise operators and memory manipulations.
Simply, to make your code fast, you should completelly delete your code (I am not going to list all of your bad-practice things here) and start understanding my example:
int main(void){
char *s = (char*)malloc(33);
char *t = s;
int a;
s += 33;
*s = 0;
printf("Enter a number: ");
scanf("%d", &a);
printf("That number in binary: ");
while(a){
*(--s) = a & 1 ? '1' : '0';
a >>= 1;
}
printf("%s\n", s);
free(t);
return 0;
}
Explanation: we have pointer (if you don't know pointers, well you should probably first learn them) s which points to the end of a string. While number from input (number a) is nonzero, we put its last binary digit in the string, decrease pointer and divide a integrally by 2 (this is a >>= 1 instruction). When a is 0, just print the string.
Related
I'm trying to create a complete C program to read ten alphabets and display them on the screen. I shall also have to find the number of a certain element and print it on the screen.
#include <stdio.h>
#include <conio.h>
void listAlpha( char ch)
{
printf(" %c", ch);
}
int readAlpha(){
char arr[10];
int count = 1, iterator = 0;
for(int iterator=0; iterator<10; iterator++){
printf("\nAlphabet %d:", count);
scanf(" %c", &arr[iterator]);
count++;
}
printf("-----------------------------------------");
printf("List of alphabets: ");
for (int x=0; x<10; x++)
{
/* I’m passing each element one by one using subscript*/
listAlpha(arr[x]);
}
printf("%c",arr);
return 0;
}
int findTotal(){
}
int main(){
readAlpha();
}
The code should be added in the findTotal() element. The output is expected as below.
Output:
List of alphabets : C C C A B C B A C C //I've worked out this part.
Total alphabet A: 2
Total alphabet B: 2
Total alphabet C: 6
Alphabet with highest hit is C
I use an array to count the number of the existence of each character,
I did this code but the display of number of each character is repeated in the loop
int main()
{
char arr[100];
printf("Give a text :");
gets(arr);
int k=strlen(arr);
for(int iterator=0; iterator<k; iterator++)
{
printf("[%c]",arr[iterator]);
}
int T[k];
for(int i=0;i<k;i++)
{
T[i]=arr[i];
}
int cpt1=0;
char d;
for(int i=0;i<k;i++)
{int cpt=0;
for(int j=0;j<k;j++)
{
if(T[i]==T[j])
{
cpt++;
}
}
if(cpt>cpt1)
{
cpt1=cpt;
d=T[i];
}
printf("\nTotal alphabet %c : %d \n",T[i],cpt);
}
printf("\nAlphabet with highest hit is : %c\n",d,cpt1);
}
There is no way to get the number of elements You write in an array.
Array in C is just a space in the memory.
C does not know what elements are actual data.
But there are common ways to solve this problem in C:
as mentioned above, create an array with one extra element and, fill the element after the last actual element with zero ('\0'). Zero means the end of the actual data. It is right if you do not wish to use '\0' among characters to be processed. It is similar to null-terminated strings in C.
add the variable to store the number of elements in an array. It is similar to Pascal-strings.
#include <stdio.h>
#include <string.h>
#define ARRAY_SIZE 10
char array[ARRAY_SIZE + 1];
int array_len(char * inp_arr) {
int ret_val = 0;
while (inp_arr[ret_val] != '\0')
++ret_val;
return ret_val;
}
float array_with_level[ARRAY_SIZE];
int array_with_level_level;
int main() {
array[0] = '\0';
memcpy(array, "hello!\0", 7); // 7'th element is 0
printf("array with 0 at the end\n");
printf("%s, length is %d\n", array, array_len(array));
array_with_level_level = 0;
const int fill_level = 5;
int iter;
for (iter = 0; iter < fill_level; ++iter) {
array_with_level[iter] = iter*iter/2.0;
}
array_with_level_level = iter;
printf("array with length in the dedicated variable\n");
for (int i1 = 0; i1 < array_with_level_level; ++i1)
printf("%02d:%02.2f ", i1, array_with_level[i1]);
printf(", length is %d", array_with_level_level);
return 0;
}
<conio.h> is a non-standard header. I assume you're using Turbo C/C++ because it's part of your course. Turbo C/C++ is a terrible implementation (in 2020) and the only known reason to use it is because your lecturer made you!
However everything you actually use here is standard. I believe you can remove it.
printf("%c",arr); doesn't make sense. arr will be passed as a pointer (to the first character in the array) but %c expects a character value. I'm not sure what you want that line to do but it doesn't look useful - you've listed the array in the for-loop.
I suggest you remove it. If you do don't worry about a \0. You only need that if you want to treat arr as a string but in the code you're handling it quite validly as an array of 10 characters without calling any functions that expect a string. That's when it needs to contain a 0 terminator.
Also add return 0; to the end of main(). It means 'execution successful' and is required to be conformant.
With those 3 changes an input of ABCDEFGHIJ produces:
Alphabet 1:
Alphabet 2:
Alphabet 3:
Alphabet 4:
Alphabet 5:
Alphabet 6:
Alphabet 7:
Alphabet 8:
Alphabet 9:
Alphabet 10:-----------------------------------------List of alphabets: A B C D E F G H I J
It's not pretty but that's what you asked for and it at least shows you've successfully read in the letters. You may want to tidy it up...
Remove printf("\nAlphabet %d:", count); and insert printf("\nAlphabet %d: %c", count,arr[iterator]); after scanf(" %c", &arr[iterator]);.
Put a newline before and after the line of minus signs (printf("\n-----------------------------------------\n"); and it looks better to me.
But that's just cosmetics. It's up to you.
There's a number of ways to find the most frequent character. But at this level I recommend a simple nested loop.
Here's a function that finds the most common character (rather than the count of the most common character) and if there's a tie (two characters with the same count) it returns the one that appears first.
char findCommonest(const char* arr){
char commonest='#'; //Arbitrary Bad value!
int high_count=0;
for(int ch=0;ch<10;++ch){
const char counting=arr[ch];
int count=0;
for(int c=0;c<10;++c){
if(arr[c]==counting){
++count;
}
}
if(count>high_count){
high_count=count;
commonest=counting;
}
}
return commonest;
}
It's not very efficient and you might like to put some printfs in to see why!
But I think it's at your level of expertise to understand. Eventually.
Here's a version that unit-tests that function. Never write code without a unit test battery of some kind. It might look like chore but it'll help debug your code.
https://ideone.com/DVy7Cn
Footnote: I've made minimal changes to your code. There's comments with some good advice that you shouldn't hardcode the array size as 10 and certainly not litter the code with that value (e.g. #define ALPHABET_LIST_SIZE (10) at the top).
I have used const but that may be something you haven't yet met. If you don't understand it and don't want to learn it, remove it.
The terms of your course will forbid plagiarism. You may not cut and paste my code into yours. You are obliged to understand the ideas and implement it yourself. My code is very inefficient. You might want to do something about that!
The only run-time problem I see in your code is this statement:
printf("%c",arr);
Is wrong. At this point in your program, arr is an array of char, not a single char as expected by the format specifier %c. For this to work, the printf() needs to be expanded to:
printf("%c%c%c%c%c%c%c%c%c%c\n",
arr[0],arr[1],arr[2],arr[3],arr[4],
arr[5],arr[6],arr[7],arr[8],arr[9]);
Or: treat arr as a string rather than just a char array. Declare arr as `char arr[11] = {0};//extra space for null termination
printf("%s\n", arr);//to print the string
Regarding this part of your stated objective:
"I shall also have to find the number of a certain element and print it on the screen. I'm new to this. Please help me out."
The steps below are offered to modify the following work
int findTotal(){
}
Change prototype to:
int FindTotal(char *arr);
count each occurrence of unique element in array (How to reference)
Adapt above reference to use printf and formatting to match your stated output. (How to reference)
Why is this code not running after printing of array if I take value of n>=9?
#include <stdio.h>
#include <math.h>
float mean_function(float array[],int n);
int main() {
int i,n;
float array[n],mean,sum=0,s2,summation,deno,C[i],elements;
printf("Enter No of Elements\n");
scanf("%d",&n);
printf("Enter Elements\n");
for(i=0;i<n;i++){
scanf("%f",&array[i]);
printf("%f",array[i]);
}
printf("sample variance(s2) : (sum((x-mean)*(x-mean)))/(n-1) /n");
printf("population variance(sigma2) : (sum((x-u)*(x-u))/n");
mean_function(array,n);
for(i=0;i<n;i++) {
deno=((array[i]-mean)*(array[i]-mean));
C[i]=deno;
summation=summation+C[i];
}
s2=((summation)/(n-1));
printf("s2=%f \n",s2);
}
float mean_function(float array[],int n) {
int i;
float sum=0,mean;
for(i=0;i<n;i++){ sum=sum+array[i]; }
mean=(sum/n);
return mean;
}
Why is this code not running after printing of array if I take value
of n>=9?
Some thoughts about your code (and about building programs in steps):
Arrays in C don't change in size once defined. VLAs are out for a variety of reasons. malloc() is in.
Use double, unless there is a specific reason to use floats.
Define and initialize one variable per line. Uninit vars can only result in an error as mentioned by #Jens.
Function declarations at the top (which you have done)
During development, there is no need to complicate things with a scanf (at least initially). It only adds an unwarranted layer of complexity. If you are testing statistical functions (mean, variance), put numbers in a pre-defined static array and verify functionality first.
C[i] as been declared with uninitialized i.
For this initial phase of building this program, I include a basic program.
I am not a fan of zero space between tokens (but ignore that)
Consider calling your array something other than 'array'.
Calculating the size of the samples array allows you to change the number of elements without changing anything else in code; which adds another layer of complexity to an already difficult phase.
#include <stdio.h>
#include <math.h>
double sample_mean(double* p, int n);
int main()
{
double samples[] = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 16.5, 2.3};
double mean = 0.0;
int size_samples = sizeof samples/sizeof(double);
printf("size_samples = %d\n", size_samples);
mean = sample_mean(samples, size_samples);
printf("Mean = %.2lf", mean);
}
// -------------------------------
double sample_mean(double* p, int n)
{
double mean = 0.0;
double total = 0.0;
for(int i = 0; i < n; i++)
total += *p++;
mean = total/n;
return mean;
}
Once this functionality is present (saved), you can start working on other stat functions. This way you can work step by step to get closer to the desired outcome.
Next up you can define sample_variance(double* p, int n) and work on that knowing that additional(new errors) are not coming from your code written so far.
Output:
size_samples = 8
Mean = 5.24
I hope it helps.
The code is likely not running because array[n] is declared with an uninitialized n. At the time you read n with scanf(), the array does not automatically "grow into the right size". You should either declare array big enough, or if you really want it to be user-defined, use malloc to allocate it (read the comp.lang.c FAQ) and all Stackoverflow questions tagged array...)
In addition, the scanf at some point fails. Note that when you enter numbers, you also have the "Enter" as a newline ('\n') in the input stream. You never read the newline so the next scanf fails.
This becomes obvious when you actually check the return value from scanf with code like this:
if (scanf("%f", &array[i]) == 1) {
/* successfully converted 1 item */
}
else {
/* scanf failed */
}
Usually what you want is to skip whitespace in the input. You do this by placing a space in the scanf format. Note that a single space tells scanf to skip any amount of white-space.
if (scanf(" %f", &array[i]) == 1) {
I am trying to make a C program for converting a given number in say base x, to base y. I chose to narrow it down upto base 20 (i.e. Base 2 to 20). When it comes to scanning a hexadecimal number (includes ABCDEF too, right?) for example, I am stuck. Please look at my program below:
/* NOTE: This program uses two step approach to convert a given number in any base (except base 10, in which case we will use only "toany()") to any other base*/
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
int inum,ibase, obase;
int todec(); //function to convert to decimal from any base
int toany(int); //function to convert from decimal to any base
int exp(int,int); //used in other function
void main()
{
int num,choice;
char strr[100];
enum{A=10,B,C,D,E,F,G,H,I,J};
here:
printf("Enter the base (RADIX) of your number: ");
scanf("%d",&ibase);
printf("Enter the number in base %d: ",ibase);
scanf("%s",strr);
printf("Enter the base in which you want the output: ");
scanf("%d",&obase);
inum=atoi(strr);
switch(obase)
{
case 10:
num=todec();
printf("Output in base 10: %d\n",num);
break;
default:
if(ibase==10)
num=toany(inum);
else
num=toany(todec());
printf("Output in base %d: %d\n",obase,num);
break;
}
printf("WANNA DO IT AGAIN? If yes, Press 1 else press 0:");
scanf("%d",&choice);
if(choice==1)
goto here;
else
exit(0);
getch();
}
int exp(int p, int q)
{
int i,result=1;
for(i=1;i<=q;i++)
{
result=result*p;
}
return(result);
}
int todec()
{
int inumarr[100],dupnum=inum,i=0,counter,decnum=0;
while(dupnum!=0)
{
inumarr[i]=dupnum%10;
dupnum/=10;
i++;
}
for(counter=0;counter<i;counter++)
{
decnum=decnum+inumarr[counter]*exp(ibase, counter);
}
return(decnum);
}
int toany(int num)
{
int outnumarr[100],i=0,q,result=0;
while(num!=0)
{
outnumarr[i]=num%obase;
num=num/obase;
i++;
}
for(q=0;q<i;q++)
{
result=result+outnumarr[q]*exp(10,q);
}
return(result);
}
Thanks for reading! Now, I know it's definitely a mess where I tried to scan as a string and then applied atoi function on a string that might contain alphabets (like "19E" in base 16...which is 414 in base 10). So, I am looking for a decent solution which will allow the user of this program to enter any number like "19E" and my program will interpret that 'E' as 14 (AS DEFINED IN MY ENUM) and also a decent way to show an output of numbers like "19E" would be great.
Disclaimer: The code I've put into this answer is untested. I'm currently on a mobile device, so even compiling it is less convenient than usual. I will strive to include enough details for you to find your way past any (possible) errors, please point them out though... On another day I'll polish this post off by adding more checks (described at the end) and explain serialisation as well as deserialisation. As it stands, however, it seems you're just asking about deserialisation, so without further adeau:
Build a lookup table of some description containing each character from your base. For characters then you can (usually) get away with using string operations. For example:
unsigned char hex_digit[] = "00112233445566778899AaBbCcDdEeFf";
If you use strchr and some pointer arithmetic you can now find the offset of a character, divide by two to reduce it to a value within 0 .. 15, or modulo by two to discriminate between lowercase and uppercase.
You can devise any base like this, with a generic loop parsing the input to facilitate larger values...
size_t to_native_uimax(char *str, unsigned char *base, uintmax_t *value) {
size_t x, base_size = strlen(str);
uintmax_t v = 0;
for (x = 0; str[x]; x++) {
unsigned char *c = strchr(base, str[x]);
if (!c) break;
v *= base_size / 2;
v += (c - base) / 2;
}
*value = v;
return x;
}
Signage is a bit trickier to handle, but because we only need to handle the sign at the start of the string we can reuse the code above.
size_t to_native_imax(unsigned char *str, unsigned char *base, intmax_t *value) {
uintmax_t v = 0;
size_t x = to_native_uimax(str + !!strchr("-+", *str), base, &v);
*value = *str == '-' ? -(intmax_t)v : v;
return x;
}
Also note that this code isn't strictly portable; if it's possible that this might be deployed to a system that has negative zeros or signals on overflow more checks should precede the (intmax_t) conversion.
I am trying to write a simple program. I am a begineer and i am not getting a value to total. When i am trying to print . I am getting a address as output . Can anyone explain me what is the mistake and correct my program .
#include<stdio.h>
void main()
{
int first,second,total;
printf("enter the value for the first");
scanf("%d",&first);
printf("enter the value for the second");
scanf("%d",&second);
total=power(first,second);
printf("The value for power is %d",power);
}
int power(int doom1,int doom2)
{
int temp=doom1;
int i;
for(i=1;i<=doom2;i++)
{
temp=temp*doom1;
}
return temp;
}
You are printing the wrong variable:
total=power(first,second); //here you are getting return value in variable total
printf("The value for power is %d",power); // power is the function name not variable
Replace this line with:
printf("The value for power is %d",total); // you need to print `total`
Also you have to declare your function prototype before main():
int power(int ,int);
and you should use int main():
int main()
{
// your code
return 0;
}
In addition to passing total to printf instead of power, as you are just starting, make a point to always give your variables an initial value (initialize them). This prevents an attempt to read from uninitialized space which is the bane of new C programmers. (it will save you a lot of headaches). Attempting to read from an uninitialized variable is Undefined Behavior. That can result in anything from slipping by unnoticed, to causing your program to crash. It is to be avoided.
Also, as I explained in the comment, in C, the function main() is type int and it returns a value to its caller (usually the shell, or another program). When using main without arguments, the proper form is:
int main (void)
When accepting arguments, the proper form is:
int main (int argc, char **argv)
In either case, it should return a positive value upon completion. A return 0; at the end is all that is required. exit (0); is another function you can use to return a value. You will also see the form of main with arguments written as:
int main (int argc, char *argv[])
The first and second forms are the practical equivalents of each other, the first recognizing that an array passed to a function in C will decay to a pointer. But for now, just understand that they are equivalent.
You also have an error in your my_power calculation. int temp = doom1; should be int temp = 1; Your calculation was returning a value twice the actual product.
Your style of syntax is up to you, but I would suggest that expanding your syntax a little by using discretionary spaces and lines will make your code much more readable and make finding errors a bit easier. Here is an example regarding all of these points:
#include <stdio.h>
int my_power (int doom1, int doom2);
int main (void)
{
int first = 0; /* Always initialize your variable to prevent */
int second = 0; /* an inadvertant read from an unitialized */
int total = 0; /* value which is Undefined Behavior (bad). */
printf ("\n enter the value for the first : ");
scanf ("%d",&first);
printf (" enter the value for the second: ");
scanf ("%d",&second);
total = my_power (first,second);
printf ("\n The value for my_power is: %d\n\n", total);
return 0;
}
int my_power (int doom1, int doom2)
{
int temp = 1;
int i = 0;
for (i = 1; i <= doom2; i++)
temp = doom1 * temp;
return temp;
}
Output
$ ./bin/simple_function
enter the value for the first : 2
enter the value for the second: 7
The value for my_power is: 128
you are trying to print "power" without parameter
printf("The value for power is %d",power);
you should do
printf("The value for power is %d",total);
or
printf("The value for power is %d",power(first,second));
I want to add numbers to an array using scanf
What did i do wrong? it says expected an expression on the first bracket { in front of i inside the scanf...
void addScores(int a[],int *counter){
int i=0;
printf("please enter your score..");
scanf_s("%i", a[*c] = {i});
}//end add scores
I suggest:
void addScores(int *a, int count){
int i;
for(i = 0; i < count; i++) {
printf("please enter your score..");
scanf("%d", a+i);
}
}
Usage:
int main() {
int scores[6];
addScores(scores, 6);
}
a+i is not friendly to newcomer.
I suggest
scanf("%d", &a[i]);
Your code suggests that you expect that your array will be dynamically resized; but that's not what happens in C. You have to create an array of the right size upfront. Assuming that you allocated enough memory in your array for all the scores you might want to collect, the following would work:
#include <stdio.h>
int addScores(int *a, int *count) {
return scanf("%d", &a[(*count)++]);
}
int main(void) {
int scores[100];
int sCount = 0;
int sumScore = 0;
printf("enter scores followed by <return>. To finish, type Q\n");
while(addScores(scores, &sCount)>0 && sCount < 100);
printf("total number of scores entered: %d\n", --sCount);
while(sCount >= 0) sumScore += scores[sCount--];
printf("The total score is %d\n", sumScore);
}
A few things to note:
The function addScores doesn't keep track of the total count: that variable is kept in the main program
A simple mechanism for end-of-input: if a letter is entered, scanf will not find a number and return a value of 0
Simple prompts to tell the user what to do are always an essential part of any program - even a simple five-liner.
There are more compact ways of writing certain expressions in the above - but in my experience, clarity ALWAYS trumps cleverness - and the compiler will typically optimize out any apparent redundancy. Thus - don't be afraid of extra parentheses to make sure you will get what you intended.
If you do need to dynamically increase the size of your array, look at realloc. It can be used in conjunction with malloc to create arrays of variable size. But it won't work if your initial array is declared as in the above code snippet.
Testing for a return value (of addScores, and thus effectively of scanf) >0 rather than !=0 catches the case where someone types ctrl-D ("EOF") to terminate input. Thanks #chux for the suggestion!