There is a question: I should scan a number with 300 digits and print the sum the digits but I cant scan it with long long int and I dont know what to do.
You can scan the number as a string with fgets() or simply read one byte at a time with getchar():
#include <stdio.h>
int main() {
int c;
int sum = 0;
while ((c = getchar()) != EOF) {
if (c >= '0' && c <= '9')
sum += c - '0';
else
break;
}
printf("sum: %d\n", sum);
return 0;
}
I you must use scanf(), here is an alternative:
#include <stdio.h>
int main() {
char buf[2];
int sum = 0;
while (scanf("%1[0-9]", buf) == 1) {
sum += *buf - '0';
}
printf("sum: %d\n", sum);
return 0;
}
#include <stdio.h>
int main()
{
char digit;
int sum = 0;
while ( scanf("%c", &digit) != EOF)
{
sum += digit - '0';
}
printf("sum: %d\n", sum);
return 0;
}
The most straight forward solution seems to be to repeatedly read in 1-digit ints and sum them up while that works.
One digit numbers can easily be read into an int (no long needed) and even the sum of 300 digits will not exceed an int.
#include <stdio.h>
int main()
{
int digit=0;
int sum=0;
while(1==scanf("%1d",&digit))sum+=digit;
printf("sum:%d\n", sum);
return 0;
}
This admittedly (thanks chqrlie for pointing out) expect an end of line, as it comes with e.g. test input at online compilers or judges. In an interactive prompt
... a single line of digit will not suffice, an explicit end of file with ^D is needed.
In such a case you need to enter a number as a string.
To enter a number you should use the standard function fgets. The corresponding character array must have 302 characters: 300 characters for digits, one character for the new line character '\n' that is appended by the function fgets to the entered string and one character for the terminating zero character '\0' of the string.
If the new line character '\n' is not present in the string it means that the user entered more than 300 characters.
Also the user can enter a number with leading or trailing spaces.
You need to check that the entered string contains a valid number.
Here is a demonstration program.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int is_valid_number( const char *number )
{
while ( isblank( ( unsigned char )*number ) ) ++number;
int valid = *number != '\0';
if ( valid )
{
while ( isdigit( ( unsigned char )*number ) ) ++number;
while ( isblank( ( unsigned char )*number ) ) ++number;
valid = *number == '\0';
}
return valid;
}
int main( void )
{
enum { N = 300 };
char number[N + 2] = { 0 };
printf( "Enter a non-negative number (no greater than %d digits): ", N );
fgets( number, sizeof( number ), stdin );
int valid = strchr( number, '\n' ) != NULL;
char *p = number;
if ( valid )
{
number[ strcspn( number, "\n" ) ] = '\0';
while ( isblank( ( unsigned char )*p ) ) ++p;
valid = is_valid_number( p );
}
if ( !valid )
{
puts( "Invalid number." );
}
else
{
unsigned int sum = 0;
for ( char *digit = p; isdigit( ( unsigned char )*digit ); ++digit )
{
sum += *digit - '0';
}
printf( "The sum of digits = %u\n", sum );
}
}
Its output might look like
Enter a non-negative number (no greater than 300 digits): 1234567890123456789012345678901234567890
The sum of digits = 180
you can use char to scan each digit. also in this way you do not need string.enter image description here
Related
I am having an issue with the output of my code, which is trying to return an array backwards in c using pointers. Do you guys have any solutions to the error I am getting?
Sample input:
Please enter the array size: 3
Please enter 3 elements:
4, 5, 7
Segmentation fault (core dumped)
Code:
#include <stdio.h>
int main(void){
int size, i;
int *pointer;
int arr[size];
printf("Please enter the array size: ");
scanf("%d/n", &size);
pointer = &arr[0];
printf("Please enter %d elements: \n", size);
for(i = 0; i < size; i++){
scanf("%d", arr[i]);
pointer++;
}
pointer = &arr[size - 1];
printf("The reversed array is \n");
for(i = size; i > 0; i--){
printf("%d", arr[i]);
pointer--;
}
return 0;
}
The task is not simple for beginners like you and me.
As I have understood the user can enter any number of integers in one line and all entered integers in the line must be outputted like
You entered 2
In this case neither array nor character array nor integer array will help. And in fact you need not to define an array if you want only to output numbers stored in the input buffer.
In this case you can just use the standard function getchar. Using the function in a loop you can read all numbers placed by the user in one line in the I/O buffer.
Here is a sample program. It is a little complicated because I allow the user to enter sign symbols.
There is no check in the program whether the user entered not a digit or a sign. You can develop the program further. The program demonstrates an approach to solve the task.
#include <stdio.h>
#include <ctype.h>
int main( void )
{
const int Base = 10;
printf( "Enter a seria of integer numbers in one line: " );
int c;
int sign = 0;
int num = 0;
do
{
c = getchar();
if (c == EOF || c == '\n' )
{
if (sign)
{
printf( "You entered %d\n", num );
}
}
else if (isblank( ( unsigned char )c ))
{
if (sign)
{
printf( "You entered %d\n", num );
sign = 0;
num = 0;
}
}
else
{
if (c == '-' || c == '+')
{
if (sign)
{
printf( "You entered %d\n", num );
num = 0;
}
sign = c == '-' ? -1 : 1;
}
else if (isdigit( ( unsigned char )c ))
{
c -= '0';
if (sign == 0) sign = 1;
if (sign == 1)
{
num = Base * num + c;
}
else
{
num = Base * num - c;
}
}
}
} while (c != EOF && c != '\n');
}
The program output might look for example like
Enter a seria of integer numbers in one line: 1 -1 +12-12+13 +14 -15
You entered 1
You entered -1
You entered 12
You entered -12
You entered 13
You entered 14
You entered -15
If you want to enter several lines of numbers and output numbers that are present in each line then the program can look the following way
#include <stdio.h>
#include <ctype.h>
int main( void )
{
const int Base = 10;
size_t i = 0;
while (1)
{
printf( "Enter a seria of integer numbers in one line (or press just Enter to exit): " );
int c = getchar();
if (c == EOF || c == '\n') break;
ungetc( c, stdin );
printf( "Line %zu contains the following numbers:\n", i++ );
int sign = 0;
int num = 0;
do
{
c = getchar();
if (c == EOF || c == '\n')
{
if (sign)
{
printf( "You entered %d\n", num );
}
}
else if (isblank( ( unsigned char )c ))
{
if (sign)
{
printf( "You entered %d\n", num );
sign = 0;
num = 0;
}
}
else
{
if (c == '-' || c == '+')
{
if (sign)
{
printf( "You entered %d\n", num );
num = 0;
}
sign = c == '-' ? -1 : 1;
}
else if (isdigit( ( unsigned char )c ))
{
c -= '0';
if (sign == 0) sign = 1;
if (sign == 1)
{
num = Base * num + c;
}
else
{
num = Base * num - c;
}
}
}
} while (c != EOF && c != '\n');
putchar( '\n' );
}
}
The program output might look for example like
Enter a seria of integer numbers in one line (or press just Enter to exit): 1 -2 3 +4
Line 0 contains the following numbers:
You entered 1
You entered -2
You entered 3
You entered 4
Enter a seria of integer numbers in one line (or press just Enter to exit): 11-12 13+14
Line 1 contains the following numbers:
You entered 11
You entered -12
You entered 13
You entered 14
Enter a seria of integer numbers in one line (or press just Enter to exit):
As the program just outputs entered numbers then actually there is no need to build an object of the type int like
num = Base * num + c;
You could just output adjacent digits in a line.
int array[100];
int n;
scanf("%d", &n);
for(int i=0; i<n; i++) {
scanf("%d", &array[i]);
}
for(int i=0; i<n; i++) {
printf("You entered %d \n", array[i]);
}
We use the array to get all of the values, and just print them out at the end.
In C and C++ it does not matter if the values are separated by space or a newline, so you can get every integer in a single line if separated by spaces.
output
3
1 2 3
You entered 1
You entered 2
You entered 3
C makes this very easy, but you need to leverage some library functions. At the most simple:
use fgets() and strpbrk() to obtain and verify a line of text
use strtok() and strtol() to parse and verify integer values.
What you do with those values is up to you. Following your example prompt, let’s just print them.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int error( const char * message, const char * value )
{
fprintf( stderr, "%s%s\n", message, value );
return 1;
}
int main()
{
printf( "Input: " );
// Get all input on a single line
char text[1000];
fgets( text, sizeof(text), stdin );
// Verify that the entire line of input was obtained
char * nl = strpbrk( text, "\r\n" );
if (!nl) return error( "Line too long!", "" );
*nl = '\0';
puts( "Output:" );
// For each whitespace-delimited (spaces, tabs) token in the line:
for (char * token = strtok( text, " \t" ); token; token = strtok( NULL, " \t" ))
{
// Attempt to convert it to an integer
char * nok;
int n = strtol( token, &nok, 10 );
if (*nok) return error( "Invalid integer value: ", token );
// Success!
printf( "You entered %d\n", n );
}
return 0;
}
Notice also how it is OK to create a little helper function (error()). You can make helpers as complex or simple as you need. For this helper, all we need was to complain with one or two strings and return an “error happened” exit code that main() can pass right to the shell.
fgets can be used to read a line.
strtol can parse integers and report overflow and invalid input.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <limits.h>
int parselint ( char *line, int *value, char **end) {
long int number = 0;
errno = 0;
number = strtol ( line, end, 10);
if ( *end == line) {// nothing was parsed. no digits
size_t span = strcspn ( *end, "-+0123456789"); // characters to next int
if ( ! span) {
span = 1;
}
fprintf ( stderr, "problem parsing: %.*s\n", (int)span, line);
*end += span; // advance pointer to next int
return 0;// return failure
}
if ( ( errno == ERANGE && ( number == LONG_MAX || number == LONG_MIN))
|| ( errno != 0 && number == 0)) {// parsing error from strtol
fprintf ( stderr, "problem %.*s", (int)(*end - line), line);
perror ( " ");
return 0;
}
if ( number > INT_MAX || number < INT_MIN) {
fprintf ( stderr, "problem %.*s ", (int)(*end - line), line);
fprintf ( stderr, "out of int range\n");
return 0;
}
*value = number;//assign number to pointer
return 1;//success
}
int main ( void) {
char line[4096] = "";
char *parse = line;
int number = 0;
fgets ( line, sizeof line, stdin);
line[strcspn ( line, "\r\n")] = 0; // remove newline
while ( *parse) {
if ( 1 == parselint ( parse, &number, &parse)) {
printf ( "you entered %d\n", number);
}
}
return 0;
}
I want to have a loop of scanf that repeats until the user presses enter.
#include <stdio.h>
int main() {
char num[127];
int i=-1;
do
{
i++;
scanf("%c ", &num[i]);
}while ((num[i]!='\n') && i<=127);
printf("%c", num[3]);
return 0;
}
With this code, when I input > 0 1 2 3 4 5 6 , the output num[3] is nothing. How can I fix this? I already tried using while and for, but i get the same problem.
What you need is something like the following
#include <stdio.h>
#include <ctype.h>
int main(void)
{
enum { N = 127 };
char num[N];
size_t len = 0;
char c;
while ( len < N && scanf( "%c", &c ) == 1 && c != '\n' )
{
if ( !isblank( ( unsigned char )c ) ) num[len++] = c;
}
if ( 3 < len ) printf( "%c\n", num[3] );
return 0;
}
The if statement
if ( !isblank( ( unsigned char )c ) ) num[len++] = c;
may be substituted for this one if you are going to enter only digits
if ( isdigit( ( unsigned char )c ) ) num[len++] = c;
If to use getchar then the program will look like
#include <stdio.h>
#include <ctype.h>
int main(void)
{
enum { N = 127 };
char num[N];
size_t len = 0;
int c;
while ( len < N && ( c = getchar() ) != EOF && c != '\n' )
{
if ( isdigit( c ) ) num[len++] = c;
}
if ( 3 < len ) printf( "%c\n", num[3] );
return 0;
}
Using the format specifier "%c ", scanf will never write \n into buf[i] except for i == 0. (If the first character of input is a newline, it will be written to buf[0]. Otherwise, all newlines will be discarded because of the whitespace in the conversion specifier.) If you are entering data interactively, the program will not terminate correctly, since eventually the scanf will invoke undefined behavior when it tries to write to buf[127]
Also, you're not checking the value returned by scanf. It's not clear to me what you want to do with whitespace, but perhaps you want something like:
#include <stdio.h>
int
main(void)
{
char num[127];
int i=-1;
while( i < 125 && scanf("%c", &num[++i]) == 1 && num[i] != '\n' ){
; /* scanf is the wrong tool for this!! */
}
printf("%c", num[3]);
return 0;
}
(But note that using scanf is absolutely the wrong way to read a single character. fgetc, getc, and getchar are better for that.)
I am working on a problem where I need to input a line of numbers with one or more whitespaces in between and add the numbers. But I am having a problem with ignoring the whitespaces.
I have tried using scanf(" ") and scanf("%*c").
What is the most efficient way to do so?
Thanks.
If the number of input integers in an entered string is unknown then you can use the approach shown in the demonstrative program.
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
enum { N = 100 };
char line[N];
while ( fgets( line, N , stdin ) != NULL && line[0] != '\n' && line[0] != '\0' )
{
long long int sum = 0;
const char *s = line;
char *p = line;
do
{
s = p;
sum += strtol( s, &p, 10 );
} while ( s != p );
printf( "sum = %lld\n", sum );
}
return 0;
}
If to enter string
1 2 3 4 5
then the output will be
sum = 15
To read integers, use the format string %d, like this:
#include <stdio.h>
int main(void)
{
int sum, i, n;
sum = 0;
n = scanf("%d", &i);
while (n == 1) {
sum += i;
n = scanf("%d", &i);
}
printf("%d\n", sum);
return 0;
}
If you want to read real numbers, use the format string %lf (which stands for long float) and adjust the code above accordingly.
The way to do it in C++ would be
double a;
double b;
double c;
std::cin >> a >> b >> c;
I am not sure if you can do something very similar in C, please tell me if that was helpful.
Problem: I can't seem to get my test case 4 to work.
Question:
Write a C function that accepts an English sentence as a parameter, and returns the length of the longest word in the sentence. For example, if the sentence is "I am Tim.", then the length of the longest word "time" in sentence 3 will be returned.
Test Case 1:
Enter a string: I am lee.
longWordLength(): 3
Test Case 2:
Enter a string: There are two disciples in the class.
longWordLength(): 9
Test Case 3:
Enter a string: Good night!
longWordLength(): 5
Test Case 4:
Enter a string: Jovial
longWordLength(): 6
This is the code I have so far:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int longWordLength(char *s);
int main()
{
char str[80], *p;
printf("Enter a string: \n");
fgets(str, 80, stdin);
if (p=strchr(str,'\n')) *p = '\0';
printf("longWordLength(): %d\n", longWordLength(str));
return 0;
}
int longWordLength(char *s)
{
int i, count, max;
max = 0;
count = 0;
while( *(s) != '\0' )
{
if ( *(s) != '\0' && *(s) != ' ' && *(s) != '.' )
{
count++;
printf("current count is %d\n", count);
}
else
{
if(count>max)
{
max = count;
printf("There is a new max! It is %d\n", max);
count = 0;
}
count = 0;
printf("count is resetted!\n");
}
s++;
printf("reach the end of the while loop\n");
}
printf("current max outside while loop is: %d\n", max);
printf("exited\n");
return max;
}
Problem:
Your code does not work when the key word is at the end of a line.
That is because your max is updated inside that while loop and the while loop terminates when the null character is found. Since the null character is always appended to the end of your input string, the last word in a string does not contribute to the output. In this edge case, the loop does not give a chance to execute that else block in the final iteration.
In fact, your code will pass only Test Case 2 because all other cases contain the key word at the end of the input string.
Solution:
Even if you rectify that, your code may still fail if the sentence contains a punctuation mark other than the period.
For example: "Test Case!"
The new code will count "Case!" as a word of length 5 which is greater than the length of "Test" or "Case", and give a wrong answer.
You may look into some library functions that C has to offer in order to help you pass all edge cases.
If you need more assistance, I have made the required modifications to your code:
while( *(s) != '\0' )
{
// if ( *(s) != '\0' && *(s) != ' ' && *(s) != '.' )
// Why check the null character again?
// Spaces and period will not be the only punctuation marks
// You can check for all punctuation marks using ispunct() from <ctype.h>
if (!isspace(*s) && !ispunct(*s))
{
count++;
printf("current count is %d\n", count);
// You can update max here
if(count > max)
{
max = count;
printf("There is a new max! It is %d\n", max);
}
}
/*
Now you can eliminate this block of code
else
{
if(count>max)
{
max = count;
printf("There is a new max! It is %d\n", max);
count = 0;
}
count = 0;
printf("count is resetted!\n");
}
*/
// You can reset count after all that
else
{
count = 0;
printf("count is resetted!\n");
}
s++;
printf("reach the end of the while loop\n");
}
The code assumes that the input will be a proper English sentence.
P. S. This answer earned me the 1K reputation :)
For starters the function parameter should be declared with the qualifier const because within the function the passed string is not being changed. And the function return type should be size_t. It is the return type of the function strlen or the type of the value returned by the sizeof operator.
size_t longWordLength( const char *s);
The last word of a string does not take part in the calculation of the maximum word because the loop stops its iterations as soon as the next character is the terminating zero character '\0'.
It will be a bad idea to process the size of the last word outside the loop. All processing should be done within the loop.
Also your function does not take into account punctuation characters except the point.
For example for a sentence like this "How are you?" your function will give incorrect result.
Instead of checking each character whether it is for example a blank or not you could use standard C functions like strspn and strcspn.
Here is a demonstrative program that shows how the function can be implemented.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
size_t longWordLength( const char *s )
{
const char *delim = " \t";
size_t max = 0;
while ( *s )
{
s += strspn( s, delim );
if ( *s )
{
const char *first = s;
s += strcspn( s, delim );
const char *last = s;
while ( last != first && ispunct( ( unsigned char )*( last - 1 ) ) )
{
--last;
}
if ( max < last - first ) max = last - first;
}
}
return max;
}
int main(void)
{
const char *s = "Why are not you using string functions?!";
printf( "The size of the longest word is %zu\n", longWordLength( s ) );
return 0;
}
The program output is
The size of the longest word is 9
Another approach is to write two functions similar to strspn and strcspn that deal with blank and punctuation symbols.
Here is a demonstrative program.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
size_t count_non_alpha( const char *s )
{
size_t n = 0;
while ( isblank( ( unsigned char )s[n] ) || ispunct( ( unsigned char )s[n] ) )
{
++n;
}
return n;
}
size_t count_alpha( const char *s )
{
size_t n = 0;
while ( s[n] && !isblank( ( unsigned char )s[n] ) && !ispunct( ( unsigned char )s[n] ) )
{
++n;
}
return n;
}
size_t longWordLength( const char *s )
{
size_t max = 0;
while ( *s )
{
s += count_non_alpha( s );
if ( *s )
{
const char *first = s;
s += count_alpha( s );
if ( max < s - first ) max = s - first;
}
}
return max;
}
int main(void)
{
const char *s = "Why are not you using string functions?!";
printf( "The size of the longest word is %zu\n", longWordLength( s ) );
return 0;
}
The program output is the same as shown above.
Please refer to my comment to your original question.
You can resolve your problem by adding the following code, after your while loop.
if (*(s - 1) != ' ' && *(s - 1) != '.' )
{
if(count>max)
{
max = count;
printf("There is a new max! It is %d\n", max);
}
}
The code checks the last character in the input string. If it is not a word terminating character, then you didn't compare the last word with the current max in the loop and hence you do it after the loop completes.
use isalpha() to check the kind of character
don't forget to count the final word if it is followed by a '\0'
#include <stdio.h>
#include <ctype.h>
unsigned longest_word(char *str)
{
unsigned length,longest;
for(longest=length = 0; ; str++) {
if (isalpha(*str)) { length++; continue; }
if (length > longest) longest = length;
length = 0;
if (!*str) break;
}
return longest;
}
int main(void)
{
char * string1 = "The longest word is short";
char * string2 = "The longest word is unbelievable";
printf("%s: %u\n", string1, longest_word( string1) );
printf("%s: %u\n", string2, longest_word( string2) );
return 0;
}
Please help me in understanding the below code.
The function get_digit takes a character argument by address. I am unable to get what
scanf("%1[0123456789]", ch) does here.
If I give 1234 on the terminal then it takes only the first digit. Same is if I give 2345 it takes 2. I have never came across such usage of scanf. Please help me in understanding this feature.
int get_digit ( char *ch )
{
int rc;
printf ( "Enter a single digit: " );
fflush ( stdout );
if ( rc = scanf ( "%1[0123456789]", ch ) == 1 ) {
jsw_flush();
}
return rc;
}
void jsw_flush ( void )
{
int ch;
do
ch = getchar();
while ( ch != '\n' && ch != EOF );
clearerr ( stdin );
}
void fill_table ( char table[] )
{
char ch;
while ( get_digit ( &ch ) ) {
unsigned i = ch - '0';
if ( table[i] != 0 ) {
printf ( "That index has been filled\n" );
}
else {
table[i] = ch;
}
}
}
void show_table ( const char table[], size_t size )
{
size_t i;
for ( i = 0; i < size; i++ ) {
printf ( "%c\n", table[i] != 0 ? table[i] : '~' );
}
}
scanf ( "%1[0123456789]", ch ) scans 1 character (%1) which is a decimal digit ([0123456789]) int the characer pointed to by ch.
The number immediately following the % is the field width, how many characters (maximally) to scan. The characters inside the square brackets are the characters scanf will accept. The scan ends when a character not listed is encountered.
An extremely simple example to scan two-digit numbers:
#include <stdlib.h>
#include <stdio.h>
int main(void) {
char chs[2] = {0}; // space for two digits, zero-initialized
unsigned u = 0, i;
if (scanf("%2[0123456789]",&chs[0]) == 1) {
// parse the number
for(i = 0; i < 2 && chs[i]; ++i) {
u = 10*u + chs[i] - '0';
}
printf("Got %u\n",u);
} else {
puts("Scan failed.");
}
return EXIT_SUCCESS;
}
Of course, instead of parsing ourselves, we could make the character array one longer than we expect digits (zero-initialise!, scanf doesn't add a 0-terminator with that format) and leave the parsing to strtoul(chs,NULL,10).