Error with code: Segmentation Fault, Core dumped - c

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;
}

Related

Scanf a number with 300 digits in C

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

How can i make a string that only accepts numbers and the character "." in c?

im trying to make a program in c that detects if a number is an integrer or a float, and if it is a float counts the number of decimal places.
But im having an issue here, when i insert a float number, because of the "." the program says it is a "word" and not a number since i made it accept only numbers and i get stuck in the while loop.
My code:
#include<stdio.h>
#include <string.h>
#define BASE 10
main()
{
int length, number;
char str[10];
char ch = '.';
char *ret;
char *endptr;
do{
printf("Enter string: ");
scanf("%s", str);
number = strtol(str, &endptr, BASE);
}while (*endptr != '\0' || endptr == str);
ret = strchr(str, ch);
if(ret > 0){
length = strlen(ret);
printf("decimal places: %d\n", length - 1);
}
else {
printf("the number is integrer\n");
}
return 0;
}
Using strtol is only meaningful once you know that the input is an integer. If you know that the input is a floating-point number, then you can use strtod instead. There is no function that can handle both types, unless you want to handle integers as floating-point numbers.
In order to determine whether the input is an integer, floating-point or invalid input, it would probably be best to examine the input string yourself, for example like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdbool.h>
int main( void )
{
char str[100];
retry_input:
//prompt user for input
printf( "Enter number: " );
//read one line of input
if ( fgets( str, sizeof str, stdin ) == NULL )
{
fprintf( stderr, "input error!\n" );
exit( EXIT_FAILURE );
}
//if newline character exists, remove it
str[strcspn(str,"\n")] = '\0';
//this variable keeps track of the number of digits encountered
int num_digits = 0;
//this variable specifies whether we have encountered a decimal point yet
bool found_decimal_point = false;
//inspect the string one character at a time
for ( char *p = str; *p!='\0'; p++ )
{
if ( *p == '.' )
{
if ( found_decimal_point )
{
printf( "encountered multiple decimal points!\n" );
goto retry_input;
}
found_decimal_point = true;
}
else if ( isdigit( (unsigned char)*p ) )
{
num_digits++;
}
else if ( *p != '+' && *p != '-' )
{
printf( "encountered unexpected character in input!\n" );
goto retry_input;
}
else if ( p - str != 0 )
{
printf(
"sign characters (+/-) are only permitted at the start "
"of the string!\n"
);
goto retry_input;
}
}
if ( found_decimal_point )
{
//input is floating-point
printf( "The input is float and has %d digits.\n", num_digits );
}
else
{
//input is integer
printf( "The input is integer and has %d digits.\n", num_digits );
}
return EXIT_SUCCESS;
}
Note that this program will also count the number of digits encountered, and print the total number at the end of the program. Since you stated in the question that you wanted to count the "number of decimal places", this may be what you want.
Also note that this program won't accept floating point numbers in exponential notation.

C - How to make sure that an array contains 8 integers with the value 0 or 1?

That's my code so far:
int main(void) {
int byte[8], position = 0, match8 = 0;
printf("Please enter 1 byte as a binary sequence: ");
match8 = scanf("%1d%1d%1d%1d%1d%1d%1d%1d", &byte[0], &byte[1], &byte[2], &byte[3], &byte[4], &byte[5], &byte[6],&byte[7]);
return 0;
}
Now I want to make sure that the user made a correct input and if not the program should say "Error! Please enter 1 byte as a binary sequence: " and check the input again.
I tried:
while(getchar() != '\n' || match8 != 8) {
...do something
}
But I can't figure out how to check if the array contains only 0 and 1.
I hope you can help me with my problem :)
try this
char bits[9], ch;
int byte[8];
while(1){
printf("Please enter 1 byte as a binary sequence: ");fflush(stdout);
bits[8] = 1, ch = 0;
if(2 == scanf(" %8[01]%c", bits, &ch) && ch == '\n' && bits[8] == 0)
break;
if(ch != '\n')
while(getchar() != '\n');//clear input
printf("Error! ");
}
sscanf(bits, "%1d%1d%1d%1d%1d%1d%1d%1d", &byte[0], &byte[1], &byte[2], &byte[3], &byte[4], &byte[5], &byte[6],&byte[7]);
A scanset %8[01] could be used to restrict input to the characters 0 and 1. The 8 will also limit input to 8 characters. The characters can be converted to numbers with number = onezero[i] - '0';
#include <stdio.h>
#include <string.h>
int main( void) {
char onezero[9] = "";
int valid = 0;
do {
printf("Please enter 1 byte as a binary sequence: ");
if ( ( 1 == ( valid = scanf ( " %8[01]", onezero))) && ( 8 == strlen ( onezero))) {
printf ( "input was %s\n", onezero);
}
else {
if ( valid == EOF) {
break;
}
while ( getchar ( ) != '\n') {}
valid = 0;
}
} while ( !valid);
return 0;
}
Suggest to avoid scanf() and use fgets() to read a line of user input
char buf[100];
if (fgets(buf, sizeof buf, stdin)) {
Then use strspn() to test buf[] for only '0' or '1'
size_t strspn(const char *s1, const char *s2);
The strspn function computes the length of the maximum initial segment of the string pointed to by s1 which consists entirely of characters from the string pointed to by s2. C11 7.23.5.6
size_t offset = strspn(buf, "01");
if (buf[offset] == '\n') {
buf[offset--] = '\0'; // eat trailing \n
}
if (offset == 8 && buf[offset] == '\0') {
sscanf(buf, "%1d%1d%1d%1d%1d%1d%1d%1d",
&byte[0], &byte[1], &byte[2], &byte[3], &byte[4], &byte[5], &byte[6],&byte[7]);
// Success!
}
}
try this...
int main(void) {
int byte[8]={0};
printf("Please enter 1 byte as a binary sequence: ");
for(int i=0; i<8; i++)
{
byte[i]=getchar()-'0';
if(byte[i]!=0&&byte[i]!=1) /*error*/;
}
return 0;
}

Restrict user input to 8 digit number

I am looking to have a user enter an 8 digit account number. The code I have seems to work for everything unless you have multiple letters, i.e.: 'bbb' as an input. If that happens, it runs the while loop 3 times, displaying the printf, but not asking for another input.
Any input on how to fix this, or a better way to do it is welcome!
Right now, I'm using:
#include <stdio.h>
int main()
{
int return_val = 0;
int account_number = 0;
int within_range = 0;
printf("Please enter your 8 digit account number:\n");
return_val = scanf("%d", &account_number);
getchar();
getchar();
if((account_number > 9999999) && (account_number < 99999999))
{
within_range = 1;
}
while ((return_val != 1) || (within_range != 1))
{
printf("Invalid account number. Account number must be 8 digits.\n");
printf("Please enter your 8 digit account number: \n");
//scanf("%d", &clear);
return_val = scanf("%d", &account_number);
getchar();
getchar();
if((account_number > 9999999) && (account_number < 99999999))
{
within_range = 1;
}
}
printf("Account #: %d", account_number);
}
Will it help if you read the input as a string of characters (using fgets) and parse it from there using sscanf? You will not have to worry about the extra getchars.
#include <stdio.h>
int get_acct_num()
{
char line[80];
int acct_num;
int return_val = 0;
printf("Please enter your 8 digit account number:\n");
fgets ( line, sizeof ( line ), stdin );
return_val = sscanf(line, "%d", &acct_num);
if ( return_val != 1 )
return ( 0 );
if ( ( acct_num < 10000000 ) || ( acct_num > 99999999 ) )
return ( 0 );
return ( acct_num );
}
int main()
{
int account_number = 0;
while ( ! ( account_number = get_acct_num() ) )
printf("Invalid account number. Account number must be 8 digits.\n");
printf("Account #: %d", account_number);
}
In this case it is better to parse a string
#include <ctype.h>
...
char input[200];
scanf("%s", input);
int len = strlen(input);
int dig = 0;
if (len == 8) {
for ( ; dig<len ; dig++) if ( ! isdigit(input[dig])) break;
}
if (dig == 8) printf("OK\n");
else printf("Not ok\n");
the code ensures we have 8 digits and nothing else in input (prints "OK").
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
int main()
{
int account_number = 0;
int inval = 0;
char acc_buf[256];
printf("Please enter your 8 digit account number:\n");
scanf("%s", acc_buf);
if (strlen(acc_buf) == 8) {
for (int i = 0; i < 8; i++)
if (!isdigit(acc_buf[i])) {
inval++;
break;
}
} else inval++;
if (!inval) {
account_number = atoi(acc_buf);
printf("Account #: %d\n", account_number);
}
return 0;
}
May I suggest a little rewrite?
#include <stdio.h>
#include <string.h> /* this is for strlen */
#include <stdlib.h> /* this is for atoi */
int main()
{
char input [55]; /* this is to store the user input */
int account_number = 0;
printf("Please enter your 8 digit account number:\n");
while (fgets(input, 55, stdin)[0] == '\n')
; /* this is a safer way to get input, loop until there is input, ignore new lines */
account_number = atoi(input); /* convert to an int */
if (account_number < 10000000 || account_number > 99999999)
return -1;
/* quit if invalid input */
printf("Account #: %d\n", account_number);
return 0;
}
EDIT: I've used fgets here and atoi as I think it would be good to be familiar with those functions. Having said that atoi is not necessarily the best way to convert to an number. Strtol is far more reliable but a little more complicated to use.
This is one way to use strtol in this context:
char* temp = 0;
account_number = strtol(input, &temp, 10); /* convert to an int */
More on the subject of converting strings to numbers here.
EDIT-2:
Taking into account chux's comment, the loop can be constructed like this too:
char* out;
do
{
out = fgets(input, 55, stdin);
}
while (out == NULL || out[0] == '\n')
;
I really don't like using scanf(), prefer fgets(), then sscanf().
Details below.
2 key lines:
if (fgets(buf, sizeof(buf), stdin) == NULL)
...
while (1 != sscanf(buf, " %8lu %c", &AccontNummner, &ch));
Solution
#include <stdio.h>
#include <stdlib.h>
// Get 8 digit account number. Returns -1 on I/O error or EOF
// Parsing error just tries again.
long Get8DigitAccountNumber(void) {
const char *prompt = "Enter 8 digit account number: ";
unsigned long AccontNummner;
char ch; // Extra text
char buf[1024];
do { // or while (1)
ch = '\0';
printf(prompt);
fflush(stdout); // Appears to be needed on some systems.
prompt = "Error, try again: "; // Used on re-try
if (fgets(buf, sizeof(buf), stdin) == NULL) {
return -1; // handle I/O error
}
// If not _exactly_ one 1-8 digit field parsed, then try again.
// Leading and trailing whitespaces are OK
} while (1 != sscanf(buf, " %8lu %c", &AccontNummner, &ch));
return (long) AccontNummner;
}
int main() {
long AccontNummner;
while ((AccontNummner = Get8DigitAccountNumber()) >= 0) {
printf("# %lu\n", AccontNummner);
}
return 0;
}
If you want to read exactly 8 digits ...
int n1 = 0;
int n2 = 0;
} while ((1 != sscanf(buf, " %n%8lu%n %c", &n1, &AccontNummner, &n2, &ch) || ((n2 - n1) != 8));
Acceptable format: [optional whitespaces][1-8 digits][optional whitespaces][nothing more]
sscanf() format: " %8lu %c".
Use %u instead of %d to not allow '-'.
Explicitly allow optional leading and trailing spaces.
The %c catches any non-white char after the 8-digit number.
Scanning anything via %c causes sscanf() to return 2.
It's been a while since I fooled with formatted input in C but try scanf("%8d", &account_number);

Understanding that scanf is doing in this code

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).

Resources