how can i sum realy big number? [duplicate] - c

This question already has answers here:
Digital Root in c
(2 answers)
Closed 11 months ago.
So you have to do:
11 = 1+1 = 2
3578 = 3+5+7+8 = 23 = 2+3 = 5
But the problem is that the number can be very large(consist of 10,000 digits)
But even with the easiest entrances it doesn't work:
Input : 11
Output: 2798 (and it always changes, but remains a 4-digit number)
Can someone explain why is this happening?
And how can I summarize each digit of a very large number?

You got that huge number becuase your program is adding the ASCII value of various characters.
Some improvements:
Don't use "%s", use "%<WIDTH>s", to avoid buffer-overflow
Use size_t to iterate through an array, instead of unsigned long long int
Instead of using bare return 0;, use return EXIT_SUCCESS;, which is defined in the header file stdlib.h.
always check whether scanf() input was successful or not
Don't check for '\n', because string from scanf() ends at both SPACES and NEWLINE.
adding +1 to array size for NULL terminating character
Use "%zu" instead of "%lld" for size_t
Final Code:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int main(void) {
char buffer[10001] = {0};
if(scanf("%10000s", buffer) != 1)
{
perror("bad input");
return EXIT_FAILURE;
}
size_t result = 0;
for(size_t i = 0; buffer[i]; i++) {
if(isdigit(buffer[i])){
result += buffer[i] - '0';
}
else {
perror("only digits are valid");
return EXIT_FAILURE;
}
}
printf("%zu\n", result);
return EXIT_SUCCESS;
}
Output:
1112
5
TRY IT ONLINE

You can do it without occupying memory
#include <ctype.h>
#include <stdio.h>
int main(void) {
int sum = 0;
for (;;) {
int ch = getchar();
if (!isdigit((unsigned char)ch)) break; // leave loop with ENTER, EOF, 'a', ...
sum += ch - '0';
}
printf("sum of digits is %d.\n", sum);
return 0;
}
Edit: see code running at ideone

Wiki Digital Root provides a shortcut for getting the final single digit.
Validate your input string has only numeric digits
Find the sum of all digits in ASCII form
Make use of congruence formula to get the result.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define MAX_NUM_LEN 10000
int digitRoot (int n) {
if (0 == n) return 0;
return (0 == (n % 9)) ? 9 : (n % 9);
}
int main () {
char str_num [MAX_NUM_LEN];
printf ("Finding Digital Root\nEnter a number : ");
if (NULL == fgets (str_num, sizeof (str_num), stdin)) {
perror ("Reading input string");
return 2;
}
int slen = strlen (str_num);
// remove new line if found
if ('\n' == str_num[slen - 1]) str_num[--slen] = '\0';
// validate input
int digitSum = 0;
for (int ni = 0; ni < slen; ++ni) {
if (!isdigit ((unsigned char) str_num[ni])) {
printf ("\nERROR: Invalid digit [%c]\n", str_num[ni]);
return 1;
}
digitSum += str_num[ni] - '0';
}
printf ("\nDigital Root is [%d]\n", digitRoot (digitSum));
return 0;
}

Related

Check if a number is an integer or not in C language

I want to check if a number given by a user is an integer or not in another way i want to verify if the input data is between −(2)^31= −2,147,483,648 and ((2)^31) - 1 =2,147,483,647
this is my code:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main()
{
int x;
int y = pow(3,31) * (-1);
int z = pow(3,32) - 1;
printf("\n\ty = %d et z = %d \n\n", y, z);
scanf("%d", &x);
if ((x < y) || (x > z)) {
printf("x is not an integer");
}
else {
printf("x is an integer");
}
return 0;
}
But while running the program the result always showing me x is integer even if x is greater than 2,147,483,647 or lesser than −2,147,483,648.
Testing whether input is a valid int decimal numeral or is a decimal numeral in [-231, 231) is actually a bit complicated. The C standard does not provide a direct way to do this. What we can do is:
Read characters and check to see whether they are in the expected form: spaces, an optional minus sign (hyphen), and digits. (Any non-digits after the digits will be allowed and ignored.)
Try using strtol to convert the numeral to a long. We use strtol because there is no C-standard library routine for converting to an int (or your fixed bounds using 231) that provides error indications.
Compare the long produced by strtol to the int bounds.
Example code for int bounds follows. If you want bounds of -2147483648 and 2147483647 instead, substitute those for INT_MIN and INT_MAX. To be completely safe, the code should actually use long long and strtoll, since the C standard does not require long to be able to represent −2147483648.
#include <ctype.h>
#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
// Prepare a buffer.
size_t BufferSize = 100, BufferUsed = 0;
char *Buffer = malloc(BufferSize * sizeof *Buffer);
// Skip white space.
int c;
do
c = getchar();
while (isspace(c));
if (c == EOF)
{
printf("Input is not an int: EOF before \"-\" or digit seen.\n");
exit(EXIT_SUCCESS);
}
// Accept a hyphen as a minus sign.
if (c == '-')
{
Buffer[BufferUsed++] = c;
c = getchar();
}
// Accept digits.
while (isdigit(c))
{
Buffer[BufferUsed++] = c;
if (BufferSize <= BufferUsed)
{
BufferSize *= 2;
printf("Realloc: size = %zu, used = %zu.\n", BufferSize, BufferUsed);
char *NewBuffer = realloc(Buffer, BufferSize * sizeof *NewBuffer);
if (!NewBuffer)
{
fprintf(stderr, "Error, unable to allocate %zu bytes.\n",
BufferSize);
exit(EXIT_FAILURE);
}
Buffer = NewBuffer;
}
c = getchar();
}
// Ensure we saw at least one digit (input is not blank or just a hyphen).
if (BufferUsed == 0 || BufferUsed == 1 && Buffer[0] == '-')
{
printf("Input is not an int: No digits present.\n");
exit(EXIT_SUCCESS);
}
// Put back the unaccepted character, if any.
if (c != EOF)
ungetc(c, stdin);
// Terminate the string.
Buffer[BufferUsed] = 0;
// Attempt to convert the numeral to long.
char *End;
errno = 0;
long x = strtol(Buffer, &End, 10);
// Test whether strtol succeeded.
if (*End)
{
/* I do not expect this to occur since we already tested the input
characters.
*/
printf("Input is not an int: strtol rejected %c.\n", *End);
exit(EXIT_SUCCESS);
}
if (errno == ERANGE)
{
printf("Input is not an int: strtol reported out of range.\n");
exit(EXIT_SUCCESS);
}
if (x < INT_MIN || INT_MAX < x)
{
printf("Input is not an int: Value is outside bounds.\n");
exit(EXIT_SUCCESS);
}
printf("Input is an int, %ld.\n", x);
free(Buffer);
}
Maybe i think i should store the number on a char array and check if it contains the float character '.'
#include<stdio.h>
#include<string.h>
#include <stdlib.h>
int main(){
char number[10];
int flag=0,i = 0;
printf("\n\nEnter a number: ");
scanf("%s", number);
while(number[i++] != '\0'){
if(number[i] == '.'){
flag = 1;
break;}}
if(flag)
printf("\n\n\n\tyou Entered a Floating Number not an integer number\n\n");
else
printf("\n\n\n\t you Entered an integer Number\n\n");
return 0;}

My program doesn't manipulate a string's values correctly

I need to code a program that gets input values for a string, then it ignores the characters that are not digits and it uses the digits from the string to create an integer and display it. here are some strings turned into integers as stated in the exercise.
I wanted to go through the string as through a vector, then test if the each position is a digit using isdigit(s[i]), then put these values in another vector which creates a number using the digits. At the end it's supposed to output the number. I can't for the life of it figure what's wrong, please help.
#include <stdio.h>
#include <ctype.h>
#include <string.h>
int main()
{
char *s;
scanf("%s", s);
printf("%s\n", s);
int i, n=0, v[100], nr=0;
for(i=0; i<strlen(s); i++)
{
if (isdigit(s[i]) == 1)
{
v[i] = s[i];
n++;
}
}
for(i=0;i<n;i++)
{
printf("%c\n", v[i]);
}
for(i=0; i<n; i++)
{
nr = nr * 10;
nr = nr + v[i];
}
printf("%d", nr);
return 0;
}
The pointer s is unintialized which is your major problem. But there are other problems too.
isdigit() is documented to return a non-zero return code which is not necessarily 1.
The argument to isdigit() needs to be cast to unsigned char to avoid potential undefined behaviour.
Your array v is also using the same index variable i - which is not right. Use a different variable to index v when you store the digits.
You need to subtract '0' to get the each digits integer equivalent.
scanf()'s format %s can't handle inputs with space (among other problems). So, use fgets().
#include <stdio.h>
#include <ctype.h>
#include <string.h>
int main(void)
{
char s[256];
fgets(s, sizeof s, stdin);
s[strcspn(s, "\n")] = 0; /* remove trailing newline if present */
printf("%s\n", s);
int i, n = 0, v[100], nr = 0;
size_t j = 0;
for(i = 0; i < s[i]; i++)
{
if (isdigit((unsigned char)s[i]))
{
v[j++] = s[i];
n++;
}
}
for(i = 0;i < j; i++)
{
printf("%c\n", v[i]);
}
if (j) { /* No digit was seen */
int multiply = 1;
for(i= j-1 ; i >= 0; i--) {
nr = nr + (v[i] - '0') * multiply;
multiply *= 10;
}
}
printf("%d", nr);
return 0;
}
In addition be aware of integer overflow of nr (and/or multiply) can't hold if your input contains too many digits.
Another potential source of issue is that if you input over 100 digits then it'll overflow the array v, leading to undefined behaviour.
Thanks a lot for your help, i followed someone's advice and replaced
v[i] = s[i] -> v[n] = s[i] and changed char *s with char s[100]
now it works perfectly, i got rid of the variable nr and just output the numbers without separating them through \n . Thanks for the debugger comment too, I didn't know I can use that effectively.
Firstly, you did not allocate any memory, I changed that to a fixed array.
Your use of scanf will stop at the first space (as in the first example input).
Next, you don't use the right array index when writing digits int v[]. However I have removed all that and simply used any digit that occurs.
You did not read the man page for isdigit. It does not return 1 for a digit. It returns a nonzero value so I removed the explicit test and left it as implicit for non-0 result.
I changed the string length and loop types to size_t, moving the multiple strlen calls ouside of the loop.
You have also not seen that digits' character values are not integer values, so I have subtracted '0' to make them so.
Lastly I changed the target type to unsigned since you will ignore any minus sign.
#include <stdio.h>
#include <ctype.h>
#include <string.h>
int main(void)
{
char s[100]; // allocate memory
unsigned nr = 0; // you never check a `-` sign
size_t i, len; // correct types
if(fgets(s, sizeof s, stdin) != NULL) { // scanf stops at `space` in you example
len = strlen(s); // outside of the loop
for(i=0; i<len; i++) {
if(isdigit(s[i])) { // do not test specifically == 1
nr = nr * 10;
nr = nr + s[i] - '0'; // character adjustment
}
}
printf("%u\n", nr); // unsigned
}
return 0;
}
Program session:
a2c3 8*5+=
2385
Just use this
#include <stdio.h>
#include <ctype.h>
int main()
{
int c;
while ((c = getchar()) != EOF) {
switch (c) {
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
case '\n':
putchar(c); break;
}
}
return 0;
} /* main */
This is a sample execution:
$ pru_$$
aspj pjsd psajf pasdjfpaojfdapsjd 2 4 1
241
1089u 0u 309u1309u98u 093u82 40981u2 982u4 09832u4901u 409u 019u019u 0u3 0ue
10890309130998093824098129824098324901409019019030
Very elegant! :)

Input to array of strings won't show?

I'm in C and I'm supposed to have an input of numbers (don't know how many) formatted into one column without storing them into an array of integers. I can't figure out why my code won't read the input and out put it. Please help.
#include <stdio.h>
#include <stdlib.h>
int main() {
int i;
char *nums[400];
for (i=0; i<nums; i++) {
scanf(nums[i]);
printf( "%.*s", 3, nums[i] );
}
return 0;
}
You have an array of 400 pointers, but you've never initialized them. Instead, you could declare a 2-dimension array:
char nums[400][4];
Then you're trying to use nums as a limit to the for loop. What you actually want is the number of elements in nums, which is sizeof(nums)/sizeof(nums[0]); or you could define a macro that specifies the size of the array.
Next, you left out the format string argument to scanf().
#include <stdio.h>
#include <stdlib.h>
#declare SIZE 400
int main()
{
int i;
char *nums[SIZE][4];
for(i=0; i<SIZE; i++){
scanf("%3s", nums[i]);
printf( "%.*s", 3, nums[i] );
}
return 0;
}
As Baramar correctly and thoroughly explained your main problems, I think I might have a different understanding of your problem. You want a given string of number, e.g.: 2134567896543245678 and print it out in a single column, neatly formated in rows of three digits each like that:
213
456
789
654
324
567
8
without an intermittent array of integers.
That could be done like e.g.: this
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFFER_SIZE 512
int main()
{
int res;
// for the scanf input, set all to '\0'
char buffer[BUFFER_SIZE + 1] = { '\0' }, *idx;
size_t len, i;
// restrict max-size to BUFFER_SIZE
res = scanf("%512s", buffer);
if (res != 1) {
exit(EXIT_FAILURE);
} else {
if (strcmp(buffer, "exit") == 0) {
exit(EXIT_SUCCESS);
}
// TODO: check if the buffer contains all digits
len = strlen(buffer);
idx = buffer;
for (i = len; i >= 3; i -= 3, idx += 3) {
printf("%.3s\n", idx);
}
// last entries, if any
if (*idx != '\0') {
printf("%s\n", idx);
}
}
exit(EXIT_SUCCESS);
}
If you get actual integers in a row like e.g.: 12 3123 23478 34 5456 567456 567 678 you can use something like that:
EDIT
After the comment by the OP to use floating points I changed the code to accept input of the form:
24722.319352 51433.662233
56087.991042 49357.684934 67875.375848 68421.563197
54521.615295
22744.470483
38097.001461 80878.250982
92131.575748 7217.137271
20750.671365 7620.695008 37118.391541 28655.609469 46885.110202 87114.202312
46462.577299
20557.716648
And the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXNUM 400
int main()
{
int res;
int i = 0, m;
// input and two temporary variables
double in, in1, in2;
for (m = 0; m < MAXNUM; m++) {
res = scanf("%lf", &in);
if (res != 1) {
break;
} else {
switch (i) {
case 0:
// set value of first temporary variable to input
in1 = in;
// increment indicator indicating position in output row
i++;
break;
case 1:
in2 = in;
i++;
break;
case 2:
// print the three numbers and a newline
fprintf(stdout, "%f %f %f\n", in1, in2, in);
// reset counter
i = 0;
break;
}
}
}
// if there are still numbers, print them
if (i != 0) {
if (i == 1) {
fprintf(stdout, "%f\n", in1);
} else {
fprintf(stdout, "%f %f\n", in1, in2);
}
}
exit(EXIT_SUCCESS);
}
Try it out with
$ gcc-4.9 -O3 -g3 -W -Wall -Wextra -std=c11 sc.c -o sc
$ ./sc < floatin
24722.319352 51433.662233 56087.991042
49357.684934 67875.375848 68421.563197
54521.615295 22744.470483 38097.001461
80878.250982 92131.575748 7217.137271
20750.671365 7620.695008 37118.391541
28655.609469 46885.110202 87114.202312
46462.577299 20557.716648
If you enter less than 400 entries you need to end with EOF which can be triggered in most Unix shells with ctrl+d or set an entry to end the entries like e.g.: -1 if all you have is positive numbers and check for it to break out of the loop. If you submit a file like in the example above it works automatically.

How to find the length of an input

i am trying to measure how many numbers my input has.
if i input the following line: 1 2 65 3 4 7,
i want the output to be 8.but what I'm getting is 1 2 3 4.
#include <stdio.h>
int main(void) {
int data;
int i = 1;
while (i <= sizeof(data)) {
scanf("%d", &data)
printf("%d", i);
i++;
}
}
You are printing i which have no relation to the input at all. So no matter what your input is, you'll get 1234
sizeof(data) is the same as sizeof(int), i.e. a constant with value 4 on your system.
If you want to count the number of numbers and don't care about the value of the individual number, you could do:
#include <stdio.h>
#include <ctype.h>
int main(void) {
char s[1024];
char* p;
int i = 0;
fgets(s, 1024, stdin);
p=s;
while (*p != '\0')
{
if (!isdigit(*p))
{
p++;
}
else
{
i++; // Found new number
// Search for a delimiter, i.e. skip all digits
p++;
while (*p != '\0' && isdigit(*p))
{
p++;
}
}
}
printf("We found %d numbers", i);
return 0;
}
Output:
We found 6 numbers
Notice that this code will accept any non-digit input as delimiter.
put the scanf before the while-loop and move the printf after the while-loop.
I'm also providing solution according to my openion.
#include <stdio.h>
int main(void) {
int data = 1;
int i = 0;
// here data != 0 is trigger point for end input,
// once you done with your inputs you need to last add 0 to terminate
while (data != 0) {
scanf("%d", &data)
printf("Collected Data: %d", data);
i++;
}
printf("Total number of inputs are %d.", i);
}
Hope this solution helps you.
Here is my solution:
#include <stdio.h>
#include <stdlib.h>
int main() {
int i = 0;
int data[100]; // creating an array
while(1) { // the loop will run forever
scanf("%d", &data[i]);
if (data[i] == -1) { //unless data[i] = -1
break; // exit while-loop
}
i++;
}
printf("%d\n", data[2]); // print 2nd integer in data[]
return 0;
}
Do not forget to hit enter once you entered an int. Output of the program:
2
56
894
34
6
12
-1
894
Hope that helps. :)

fetching string and converting to double

I'm trying to create a function which can determine if an input can be converted perfectly into a double and then be able to store it into an array of doubles. For example, an input of "12.3a" is invalid. From what I know, strtod can still convert it to 12.3 and the remaining will be stored to the pointer. In my function doubleable, it filters whether the input string consists only of digits. However, I'm aware that double has "." like in "12.3", and my function will return 'X' (invalid).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char doubleable (char unsure[], int length){
int i;
int flag;
for (i=0; i<length; i++ ){
if(isdigit(unsure[i]==0)){
printf("You have invalid input.\n");
flag=1;
break;
}
}
//check for '.' (?)
if(flag==1)
return 'X';
else
return 'A';
}
int main(){
char input [10];
double converted[5];
char *ptr;
int i;
for(i=0; i<5; i++){
fgets(input, 10, stdin);
//some code here to replace '\n' to '\0' in input
if(doubleable(input, strlen(input))=='X'){
break;
}
converted[i]=strtod(input, &ptr);
//printf("%lf", converted[i]);
}
return 0;
}
I'm thinking of something like checking for the occurrence of "." in input, and by how much (for inputs like 12.3.12, which can be considered invalid). Am I on the right track? or are there easier ways to get through this? I've also read about the strtok function, will it be helpful here? That function is still quite vague to me, though.
EDIT:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
double HUGE_VAL= 1000000;
void string_cleaner (char *dirty){
int i=0;
while(1){
if (dirty[i]=='\n'){
dirty[i]='\0';
break;
}
i++;
}
}
int doubleable2(const char *str)
{
char *end_ptr;
double result;
result = strtod(str, &end_ptr);
if (result == HUGE_VAL || result == 0 && end_ptr == str)
return 0; // Could not be converted
if (end_ptr < str + strlen(str))
return 0; // Other input in the string after the number
return 1; // All of the string is part of the number
}
int main(){
char input [10];
double converted[10];
char *ptr;
int i;
for(i=0; i<5; i++){
while (1){
printf("Please enter:");
fgets(input, 10, stdin);
string_cleaner(input);
if (doubleable2(input)==0)
continue;
else if (doubleable2(input)==1)
break;
}
converted[i]=strtod(input, &ptr);
printf("%lf\n", converted[i]);
}
return 0;
}
thank you! It works just fine! I have a follow up question. If I enter a string that is too long, the program breaks. If I am to limit the input to, let's say, a maximum of 9 characters in input[], how am I to do that?
from what I understand about fgets(xx, size, stdin), it only gets up to size characters (including \n, \0), and then stores it to xx. In my program, I thought if I set it to 10, anything beyond 10 will not be considered. However, if I input a string that is too long, my program breaks.
You can indeed use strtod and check the returned value and the pointer given as the second argument:
int doubleable(const char *str)
{
const char *end_ptr;
double result;
result = strtod(str, &end_ptr);
if (result == HUGE_VAL || result == 0 && end_ptr == str)
return 0; // Could not be converted
if (end_ptr < str + strlen(str))
return 0; // Other input in the string after the number
return 1; // All of the string is part of the number
}
Note that you need to remove the newline that fgets most of the time adds to the string before calling this function.
From what I know, strtod can still convert it to 12.3 and the remaining will be stored to the pointer.
That is correct – see its man page:
If endptr is not NULL, a pointer to the character after the last character used in the conversion is stored in the location referenced by endptr.
So use that information!
#include <stdio.h>
#include <stdbool.h>
#include <errno.h>
bool doable (const char *buf)
{
char *endptr;
errno = 0;
if (!buf || (strtod (buf, &endptr) == 0 && errno))
return 0;
if (*endptr)
return 0;
return 1;
}
int main (void)
{
printf ("doable: %d\n", doable ("12.3"));
printf ("doable: %d\n", doable ("12.3a"));
printf ("doable: %d\n", doable ("abc"));
printf ("doable: %d\n", doable (NULL));
return 0;
}
results in
doable: 1
doable: 0
doable: 0
doable: 0
After accept answer
Using strtod() is the right approach, but it has some challenges
#include <ctype.h>
#include <stdlib.h>
int doubleable3(const char *str) {
if (str == NULL) {
return 0; // Test against NULL if desired.
}
char *end_ptr; // const char *end_ptr here is a problem in C for strtod()
double result = strtod(str, &end_ptr);
if (str == end_ptr) {
return 0; // No conversion
}
// Add this if code should accept trailing white-space like a \n
while (isspace((unsigned char) *endptr)) {
endptr++;
}
if (*end_ptr) {
return 0; // Text after the last converted character
}
// Result overflowed or maybe underflowed
// The underflow case is not defined to set errno - implementation defined.
// So let code accept all underflow cases
if (errno) {
if (fabs(result) == HUGE_VAL) {
return 0; // value too large
}
}
return 1; // Success
}
OP's code
No value with result == 0 in result == 0 && end_ptr == str. Simplify to end_ptr == str.
Instead of if (end_ptr < str + strlen(str)), a simple if (*end_ptr) is sufficient.
if (result == HUGE_VAL ... is a problem for 2 reasons. 1) When result == HUGE_VAL happens in 2 situations: A legitimate conversion and an overflow conversion. Need to test errno to tell the difference. 2) the test should be if (fabs(result) == HUGE_VAL ... to handle negative numbers.

Resources