I am super new to programming and I am having a problem with one of the questions where i am supposed to write a C program to let the user enter some numbers and sort the entered elements and find the median of it. And it should stop getting inputs once the user presses enter.
this is my code and idk where it went wrong(btw sorry for asking such a simple question)
#include <stdio.h>
#include <stdlib.h>
int main()
{
int n;
int i = 0;
int j,k,m,num;
int arr[20];
while(i<20 )
{
printf("Enter a number: ");
scanf("%d",&num);
if(num == '\n') break;
arr[i] = num;
i++;
}
n = sizeof(arr)/sizeof(arr[0]);
for(i=0;i<n;i++)
{
for(j=i+1;j<n;j++)
{
if(arr[i] < arr[j])
{
k = arr[i];
arr[i] = arr[j];
arr[j] = k;
}
}
}
if(n%2 != 0)
{
printf("The median is %d", arr[n/2] ) ;
}
else printf("The median is %.2f", arr[(n-1)/2] + arr[n/2]/2.0);
return 0;
}
If you want to stop on empty line, you cannot use scanf. The reason is that scanf("%d", ...) skips all whitespace characters from user input while waiting for the use to enter a number. Here "whitespace" includes the new-line character '\n'. So the user cannot make scanf return by pressing Enter - only an end-of-file (Ctrl+D on linux) or bogus input (non-number) will make scanf return.
So you have to replace scanf by the combination fgets+sscanf. Consider the following code:
while (i < 20)
{
int num;
char str[15];
printf("Enter a number: ");
if (!fgets(str, sizeof str, stdin))
break;
if (sscanf(str, "%d", &num) != 1)
break;
arr[i] = num;
i++;
}
It uses fgets to input a line of input, and sscanf to parse that line. If there is nothing in the line, sscanf will fail (it returns 1 for success; any other value for failure).
Notes:
If input is too long, it will be split into two lines, which will be surprising for the user
If the user inputs more than one number on the line, extra numbers will be silently ignored
The condition of fgets's return value terminates user input also on end-of-file; this is good if you supply input to your program by redirecting it from a file
Input could be processed character by character until either twenty integers are stored or a newline is found.
As digits are read, accumulate them into a value, checking for overflow.
Upon reading whitespace or another character, store the values in the array.
#include <stdio.h>
#include <ctype.h>
#include <limits.h>
int main ( void) {
int ch = 0;
int value = 0;
int sign = 1;
int digits = 0;
int arr[20] = { 0};
int n = 0;
int i = 0;
int j = 0;
int k = 0;
while ( n < 20) {
while ( EOF != ( ch = fgetc ( stdin))) {//read a character
if ( isdigit ( ( unsigned char)ch)) {
ch -= '0';//character to int as '1' to 1
digits = 1;
if ( 1 == sign) {
if ( value < ( INT_MAX / 10) - ch) {
value *= 10;
value += ch;
}
else {
printf ( "overflow! reset to + and zero\n");
value = 0;
sign = 1;
digits = 0;
}
}
if ( -1 == sign) {
if ( value > ( INT_MIN / 10) + ch) {
value *= 10;
value -= ch;
}
else {
printf ( "overflow! reset to + and zero\n");
value = 0;
sign = 1;
digits = 0;
}
}
}
else if ( '-' == ch || '+' == ch) {
if ( digits) {
printf ( "invalid sign! reset to + and zero\n");
value = 0;
sign = 1;
digits = 0;
}
else {
sign = ( '-' == ch) ? -1 : 1;
}
}
else if ( digits) {
arr[n] = value;
value = 0;//reset to zero
sign = 1;//reset to +
++n;
digits = 0;
}
if ( '\n' == ch) {
break;
}
}
if ( '\n' == ch || EOF == ch) {
break;
}
}
for ( i = 0; i < n; i++) {
for ( j = i + 1; j < n; j++) {
if ( arr[i] < arr[j]) {
k = arr[i];
arr[i] = arr[j];
arr[j] = k;
}
}
}
for ( i = 0; i < n; i++) {
printf ( "arr[%d] = %d\n", i, arr[i]);
}
if ( n % 2 != 0) {
printf ( "The median is %d\n", arr[n/2]);
}
else {
printf ( "The median is %.2f\n", ( arr[( n - 1) / 2] + arr[n / 2] ) /2.0);
}
return 0;
}
Input and output:
9 1 82 0 3
arr[0] = 82
arr[1] = 9
arr[2] = 3
arr[3] = 1
arr[4] = 0
The median is 3
Related
I want to write a program that will take an input T. In the next T lines, each line will take a string as an input. The output would be how many ways the string can be reordered.
#include <stdio.h>
#include <stdlib.h>
int main() {
int T, i, l, count = 1, test = 0, word = 0, ans;
char line[200];
scanf("%d", &T);
for (i = 0; i < T; i++) {
scanf(" %[^\n]", line);
l = strlen(line);
for (int q = 0; q < l; q++) {
if (line[q] == ' ') {
word++;
}
}
ans = fact(word + 1);
word = 0;
for (int j = 0; j < l; j++) {
for (int k = j + 1; k < l; k++) {
if (line[k] == ' ' && line[k + 1] == line[j]) {
int m = j;
int n = k + 1;
for (;;) {
if (line[m] != line[n]) {
break;
} else
if (line[m] == ' ' && line[n] == ' ') {
test = 1;
break;
} else {
m++;
n++;
}
}
if (test == 1) {
count++;
ans = ans / fact(count);
count = 0;
test = 0;
}
}
}
}
printf("%d\n", ans);
}
}
int fact(int n) {
if (n == 1) {
return 1;
} else {
return n * fact(n - 1);
}
}
Now, in my program,
my output is like this:
2
no way no good
12
yes no yes yes no
120
if T = 2 and the 1st string is no way no good, it gives the right output that is 12 (4!/2!). That means, it has identified that there are two similar words.
But in the 2nd input, the string is yes no yes yes no. that means 3 yes and 2 nos. So the and should be 5!/(3!2!) = 10. But why is the answer 120? and why can't it recognize the similar words?
The main problem in your duplicate detector is you test the end of word with if (line[m] == ' ' && line[n] == ' ') but this test fails to identify a duplicate that occurs with the last word because line[n] is '\0', not ' '.
Note these further problems:
you do not handle words that occur more than twice correctly: you should perform ans = ans / fact(count); only after the outer loop finishes. For example, if a word is present 3 times, it will be detected as 3 pairs of duplicates, effectively causing ans to be divided by 23 = 8, instead of 3! = 6.
you should protect against buffer overflow and detect invalid input with:
if (scanf(" %199[^\n]", line) != 1)
break;
the range of type int for ans is too small for a moderately large number of words: 13! is 6227020800, larger than INT_MAX on most systems.
The code is difficult to follow. You should consider parsing the line into an array of words and using a more conventional way of counting duplicates.
Here is a modified version using this approach:
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static int cmpstr(const void *p1, const void *p2) {
char * const *pp1 = p1;
char * const *pp2 = p2;
return strcmp(*pp1, *pp2);
}
unsigned long long factorial(int n) {
unsigned long long res = 1;
while (n > 1)
res *= n--;
return res;
}
int main() {
int T, i, n, begin, count;
unsigned long long ans;
char line[200];
char *words[100];
if (!fgets(line, sizeof line, stdin) || sscanf(line, "%d", &T) != 1)
return 1;
while (T --> 0) {
if (!fgets(line, sizeof line, stdin))
break;
n = 0;
begin = 1;
for (char *p = line; *p; p++) {
if (isspace((unsigned char)*p)) {
*p = '\0';
begin = 1;
} else {
if (begin) {
words[n++] = p;
begin = 0;
}
}
}
qsort(words, n, sizeof(*words), cmpstr);
ans = factorial(n);
for (i = 0; i < n; i += count) {
for (count = 1; i + count < n && !strcmp(words[i], words[i + count]); count++)
continue;
ans /= factorial(count);
}
printf("%llu\n", ans);
}
return 0;
}
Is there more elegant way to do this task?
Program asks user for integer and repeats if non-digital characters are entered.
To exit loop two conditions expected:
a) all entered characters are digits
b) last character is '\n'
Short solutions like scanf don’t work properly, other approaches require lots of variables loops and if else conditions. User input is common task and I would like to have proper reusable template.
Subjective opinions are appreciated. Way to simplify this function or advice on another solution. Improve formatting. Reading for more systematic understanding.
#include <stdio.h>
int getIntOnly();
int main() {
int x = 0;
x = getIntOnly();
printf("\nvalue entered is: %d \n", x);
}
int getIntOnly() {
int ch, num, quit, abc;
do {
num = 0;
ch = 0;
quit = 0;
abc = 0;
printf("Enter the input: ");
do {
ch = getchar();
if (ch >= 48 && ch <= 57) {
num = num * 10 + (ch - 48);
}
else if (ch == '\n') {
quit = 1;
}
else {
abc = 1;
}
}
while (quit == 0);
}
while (quit == 0 || abc == 1);
return (num);
}
Using fgets() means you'll get the full text at once.
You can then examine it (and convert it too) to suit your needs.
int getIntOnly( void ) {
int value = 0, i = 0;
char buf[ 64 ];
do {
printf( "Enter integer value: " );
fgets( buf, sizeof( buf ), stdin );
value = 0;
for( i = 0; '0' <= buf[i] && buf[i] <= '9'; i++ )
value = value * 10 + buf[i] - '0';
} while( buf[i] != '\n' ); // good! reached end of line
return value;
}
May be better? Add some validity checks for the result of fgets() and strtol() according to your original code.
#include <stdio.h>
#include <limits.h>
#include <stdbool.h>
#include <stdlib.h>
int getIntOnly();
int main() {
int x = 0;
x = getIntOnly();
printf("\nvalue entered is: %d \n", x);
}
bool isDigit(char ch) {
return (ch >= '0' && ch <= '9')? true : false;
}
bool isAllDigit(char *buf) {
int i;
for (i = 0; buf[i] != '\n'; i++) {
if (isDigit(buf[i]) == false) {
return false;
}
}
return true;
}
bool isVaildInt(long int number) {
return (number >= INT_MIN && number <= INT_MAX)? true : false;
}
int getIntOnly() {
char buf[100];
long int num;
bool done = false;
do {
/* read line-by-line */
fgets(buf, 100, stdin);
if (isAllDigit(buf) == false)
continue;
num = strtol(buf, NULL, 10);
/* strtol() returns long int */
if (isVaildInt(num) == false)
continue;
done = true;
} while (done == false);
return num;
}
I have problem with extracting numbers from string.
Problem is I can not use strtol or isdigit functions as teacher requested so.
I am supposed to save numbers in new array.
For example, string input:
11-some12meh13text-14
.
So new array would be:
11,12,13,14
(NOT -14)
I came to idea to do following:
char str1[150];
int array[20];
int temporary, i=0, j=0; //i - for string, j - for array
for(i=0;i<=strlen(str1);i++) {
if(i==0) { //not needed to check if char before was number
if((str1[i]>=0) && (str1[i]<=9))temporary=str1[i];
if((str1[i+1]<=0) && (str1[i+1]>=9)) {//if next char is NOT number
array[j]=temporary;
j++;
}
}
else if(i!=0) { //needs to be checked if char before was number
if((str1[i]>=0) && (str1[i]<=9)) {
if((str1[i-1]>=0) && (str1[i-1]<=9))temporary=temporary*10+str1[i];
else temporary=str1[i];
if((str1[i+1]<=0) && (str1[i+1]>=9)) {//if next char is NOT number
array[j]=temporary;
j++;
}
}
}
}
I tried it on my PC, but program crashes and I have no idea or ability to find what I did wrong.
Please help!
Thank you!
The integral values of characters '0'...'9' are not 0...9.
Hence, change every occurrence of str1[k] to str1[k]-'0'.
If using sscanf() is allowed, this will parse the string for integers. The %n specifier will report the number of characters processed by the scan. This lets you move through the string.
When the scan for an integer fails ( != 1), the scanset "%*[^0-9\n]%n" scans and discards characters that are not a digit or newline. The %n captures the number of characters processed.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main ( ) {
char str1[150] = {"0+1-=2!3*4-5/6#7&8|9^10"};
int array[20] = {0};
int offset = 0;
int each = 0;
int loop = 0;
int used = 0;
int length = 0;
length = strlen ( str1);
do {
sscanf ( str1 + offset, "%*[^0-9\n]%n", &used);
offset += used;
if ( ( sscanf ( str1 + offset, "%d%n", &array[each], &used)) == 1) {
offset += used;
each++;
if ( each >= 20) {
break;
}
}
} while ( offset < length);
for ( loop = 0; loop < each; loop++) {
printf ( "%d\n", array[loop]);
}
return 0;
}
Here is a version of your code that seems to work
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main ( ) {
char str1[150] = {"-0+1-=2!3*4-text-5/6#7&8|9^10 11end"};
int array[20] = {0};
int each = 0;
int loop = 0;
int saved = 1;
int length = 0;
int temporary = 0, i=0;
length = strlen ( str1);
for ( i = 0; i < length; i++) {
if ( ( str1[i] >= '0') && ( str1[i] <= '9')) {//found a digit
temporary = ( temporary * 10) + ( str1[i] - '0');
saved = 0;//flag not saved. temporary value may change
}
else {//found NOT a digit
if ( i > 0 && !saved) {//not at first character and not saved
array[each] = temporary;//save integer
each++;
saved = 1;//flag saved
temporary = 0;//reset
if ( each >= 20) {
break;
}
}
}
}
if ( !saved && each < 19) {//end of string is an integer. save it
array[each] = temporary;
each++;
}
for ( loop = 0; loop < each; loop++) {
printf ( "%d\n", array[loop]);
}
return 0;
}
i'm newbie in C programming .
i have written this code for adding two numbers with 100 digits , but i don't know why the code does not work correctly , it suppose to move the carry but it doesn't .
and the other problem is its just ignoring the first digit (most significant digit) .
can anybody help me please ?
#include <stdio.h>
#include <ctype.h>
int sum[101] = {0};
int add(int a, int b);
void main()
{
static int a[100];
static int b[100];
char ch;
int i = 0;
int t;
for (t = 0; t != 100; ++t)
{
a[t] = 0;
}
for (t = 0; t != 100; ++t)
{
b[t] = 0;
}
do
{
ch = fgetc(stdin);
if ( isdigit(ch) )
{
a[i] = ch - 48;
++i;
}
else
break;
}
while (ch != '\n' || i == 100 || i != '\0');
i = 0;
do
{
ch = fgetc(stdin);
if ( isdigit(ch) )
{
b[i] = ch - 48;
++i;
}
else
break;
}
while (ch != '\n' || i == 100 || i != '\0');
for (;i!=0; --i)
{
add(a[i], b[i]);
}
for (i==0;i != 101; ++i)
{
printf("%d", sum[i]);
}
}
int add( int a , int b)
{
static int carry = 0;
float s = 0;
static int p = 101;
if (0 <= a+b+carry <= 9)
{
sum[p] = (a + b + carry);
carry = 0;
--p;
return 0;
}
else
{
if (10 <= a+b+carry < 20)
{
s = (((a+b+carry)/10.0 ) - 1) * 10 ;
carry = ((a+b+carry)/10.0) - (s/10);
}
else
{
s = (((a+b+carry)/10 ) - 2) * 10;
carry = ((a+b+carry)/10.0) - (s/10);
}
sum[p] = s;
--p;
return 0;
}
}
Your input loops have serious problem. Also you use i to count the length of both a and b, but you don't store the length of a. So if they type two numbers that are not equal length then you will get strange results.
The losing of the first digit is because of the loop:
for (;i!=0; --i)
This will execute for values i, i-1, i-2, ..., 1. It never executes with i == 0. The order of operations at the end of each iteration of a for loop is:
apply the third condition --i
test the second condition i != 0
if test succeeded, enter loop body
Here is some fixed up code:
int a_len;
for (a_len = 0; a_len != 100; ++a_len)
{
int ch = fgetc(stdin); // IMPORTANT: int, not char
if ( ch == '\n' || ch == EOF )
break;
a[a_len] = ch;
}
Similarly for b. In fact it would be a smart idea to make this code be a function, instead of copy-pasting it and changing a to b.
Once the input is complete, then you could write:
if ( a_len != b_len )
{
fprintf(stderr, "My program doesn't support numbers of different length yet\n");
exit(EXIT_FAILURE);
}
for (int i = a_len - 1; i >= 0; --i)
{
add(a[i], b[i]);
}
Moving onto the add function there are more serious problems here:
It's not even possible to hit the case of sum being 20
Do not use floating point, it introduces inaccuracies. Instead, doing s = a+b+carry - 10; carry = 1; achieves what you want.
You write out of bounds of sum: an array of size [101] has valid indices 0 through 100. But p starts at 101.
NB. The way that large-number code normally tackles the problems of different size input, and some other problems, is to have a[0] be the least-significant digit; then you can just expand into the unused places as far as you need to go when you are adding or multiplying.
Suppose n numbers are to be input in a single line without any spaces given the condition that these numbers are subject to the condition that they lie between 1 and 10.
Say n is 6 , then let the input be like "239435"
then if I have an array in which I am storing these numbers then I should get
array[0]=2
array[1]=3
array[2]=9
array[3]=4
array[4]=3
I can get the above result by using array[0]=(input/10^n) and then the next digit
but is there a simpler way to do it?
Just subtract the ASCII code of 0 for each digit and you get the value of it.
char *s = "239435"
int l = strlen(s);
int *array = malloc(sizeof(int)*l);
int i;
for(i = 0; i < l; i++)
array[i] = s[i]-'0';
update
Assuming that 0 is not a valid input and only numbers between 1-10 are allowed:
char *s = "239435"
int l = strlen(s);
int *array = malloc(sizeof(int)*l);
int i = 0;
while(*s != 0)
{
if(!isdigit(*s))
{
// error, the user entered something else
}
int v = array[i] = *s -'0';
// If the digit is '0' it should have been '10' and the previous number
// has to be adjusted, as it would be '1'. The '0' characater is skipped.
if(v == 0)
{
if(i == 0)
{
// Error, first digit was '0'
}
// Check if an input was something like '23407'
if(array[i-1] != 1)
{
// Error, invalid number
}
array[i-1] = 10;
}
else
array[i] = v;
s++;
}
E.g.
int a[6];
printf(">");
scanf("%1d%1d%1d%1d%1d%1d", a,a+1,a+2,a+3,a+4,a+5);
printf("%d,%d,%d,%d,%d,%d\n", a[0],a[1],a[2],a[3],a[4],a[5]);
result:
>239435
2,3,9,4,3,5
You can use a string to take the input and then check each position and extact them and store in an array. You need to check for the numeric value in each location explicitly, as you are accepting the input as a string. For integers taken input as string, there's no gurantee that the input is pure numeric and if it is not, things can go wild.
check this code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char ipstring[64];
int arr[64];
int count, len = 0;
printf("Enter the numbersi[not more than 64 numbers]\n");
scanf("%s", ipstring);
len = strlen(ipstring);
for (count = 0; count < len ; count++)
{
if (('0'<= ipstring[count]) && (ipstring[count] <= '9'))
{
arr[count] = ipstring[count] - '0';
}
else
{
printf("Invalid input detectde in position %d of %s\n", count+1, ipstring );
exit(-1);
}
}
//display
for (count = 0; count < len ; count++)
{
printf("arr[%d] = %d\n", count, arr[count]);
}
return 0;
}