Segmentation fault when reading floats from terminal input - c

After confirming input Segmentation fault pops up and I can't see why. I was told to use fgets and sscanf in loop to read an undefined number of floats from terminal input and this is what i came up with..
Code
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#define EMPTY 3.141592
#define BUFFERSIZE 100
void removeSubstring(char *s,const char *toremove){
while( (s=strstr(s,toremove)) )
memmove(s,s+strlen(toremove),1+strlen(s+strlen(toremove)));
}
int main(){
int x=0;
int y=0;
float a[BUFFERSIZE] = {EMPTY};
char buffer[BUFFERSIZE] = {EMPTY};
char *pos;
char *start = 0;
int space = ' ';
printf("Input: ");
fgets(buffer, BUFFERSIZE, stdin);
while(x< BUFFERSIZE){
sscanf(buffer, "%f ", &a[x]);
pos = strchr(buffer, space);
removeSubstring(start, pos);
x++;
}
printf("Saved input: ");
while(y<BUFFERSIZE && a[y] != EMPTY){
printf("%.2f", a[y]);
y++;
}
printf("\n");
return 0;
}
Edit: Increased both array sizes and removed feof

Almost certainly the problem is in the line pos = strchr(buffer, space);. If the input does not contain a space character, then pos is set equal to NULL. Passing a NULL to strstr() will likely result in a SEGV.

Related

How do I output a result to the number of decimal-points user previously entered (C)?

I'm trying to output my results to the decimal accuracy the user has input. In other words, if they enter 145, then it outputs to 0 d.p. - if they enter 145.67, it outputs the result to 2 d.p.
I've tried achieving this by trying different things with %.lf but didn't manage to do it so far. Is there a way to do this in C? If so, is there a name for it - so I can learn more about it.
#include <math.h>
#include <stdio.h>
int main() {
// Using long, double or something else?
double number, fourthRoot;
printf("Enter a number: ");
scanf("%lf", &number);
fourthRoot = sqrt(sqrt(number));
printf("4th root of number %lf is %.10lf", number, fourthRoot);
return 0;
}
Read user input as a line with fgets() or some scanf("%s",...-like code.
char buf[400];
if (fgets(buf, sizeof buf, stdin)) {
And then process the string. One way is with sscanf()
int n;
// Get the number and offset to end of scan
if (sscanf(buf, "%lf%n", &number, &n) == 1) {
// Look for '.'
char *dp = strchr(buf, '.');
if (dp && dp < buf + n) {
// decimal point found
int pre = buf + n - dp - 1;
printf("%.*f\n", pre, number);
This works OK but does get fooled if exponential notation used. Additional code could look for the E or e (or P, p with hexadecimal FP notation).
There are a lot of edge cases that you should worry about, but this should get you started:
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static int
compute_root(const char *s)
{
char *end;
double number = strtod(s, &end);
if( *end ){
fprintf(stderr, "Invalid input: %s\n", s);
return 1;
}
char *dp = strchr(s, '.');
int precision = dp ? end - dp - 1: 0;
char fmt[256];
snprintf(fmt, sizeof fmt, "4th root of %%s is %%.%dlf\n", precision);
printf(fmt, s, pow(number, .25));
return 0;
}
int
main(int argc, char **argv)
{
int errors = 0;
char buf[64];
if( argc > 1 ){
while( *++argv ){
errors += compute_root(*argv);
}
} else while( scanf("%63s", buf) == 1 ){
errors += compute_root(buf);
}
return errors ? EXIT_FAILURE : EXIT_SUCCESS;
}
As an exercise, consider inputs like 5.345e4. The above code will output with a precision of 5, but you probably want 3. Handling those cases is non-trivial (for certain definitions of "trivial").

read 1/2/5 string inputs in c

i need to read input from the standart input line by line
but each line will contain 1 or 2 or 5 strings like :
bofob fbo
blabla bibi bobo fbo fbooo
bobobo bobo
bobof
how can i do this?
my idea is really not looking profassional and not working
char a[50],b[50],c[50],d[50],f[50];
int numOfStrings=0;
scanf(" %s",a); char a[50],b[50],c[50],d[50],f[50];
int numOfStrings=0;
scanf(" %s",a);
if (scanf (" %s",b)){
numOfStrings=2;
if (scanf (" %s %d %d",c,d,f)
numOfStrings=5;
}
if (scanf (" %s",b)){
numOfStrings=2;
if (scanf (" %s %d %d",c,d,f)
numOfStrings=5;
}
but its not working because it goes and read inputs from the next line
is there a way to read a whole line (i know its max 250 chars) and then know how many words are in there?
edit:
i will add a count words function
but what is the nicest wat ro read a line untilll the end line or eof??
int words(const char *sentence)
{
int count,i,len;
char lastC;
len=strlen(sentence);
if(len > 0)
{
lastC = sentence[0];
}
for(i=0; i<=len; i++)
{
if(sentence[i]==' ' && lastC != ' ')
{
count++;
}
lastC = int words(const char *sentence)
}
return count;
}
You need to use fgets() to take the input line-by-line. check the man page here. It will also liberate you from handling the limitation of [1/2/5/.....] numbers of space-seperated strings. Provided sufficient storage, you can read 1 to any number of "string"s.
Note: You might need to take care of the trailing newline \n [caused by ENTER] yourself. Causes trouble most of the times.
You could scan one line until the '\n' with %[^\n], then split the line into words with strtok():
#include <string.h>
#include <stdio.h>
const char s[2] = " ";
const int MAX_LINE_SIZE = 128;
FILE *fp;
char *word, *str;
int word_counter;
/* Open the file here */
while (fgets(str, MAX_LINE_SIZE, fp) != NULL)
{
word_counter = 0
/* get the first word */
word = strtok(str, s);
/* walk through other words */
while (word != NULL)
{
printf(" %s\n", word);
word_counter++;
word = strtok(NULL, s);
}
printf("This string contains %d words\n",word_counter);
}
/* END of FILE */
You can use fgets to read a file and strchr to count the number of spaces:
#include <stdio.h>
#include <string.h>
int main(void)
{
char s[250];
char *p;
FILE *f;
int i;
f = fopen("demo.txt", "r");
while ((p = fgets(s, sizeof s, f))) {
i = 0;
while ((p = strchr(p, ' '))) {
p++;
i++;
}
printf("%d spaces\n", i);
}
fclose(f);
return 0;
}

C fgets and sscanf in loop : prevent useless looping

I have a problem with looping and fgets and sscanf to get the input.
I know to problem is from the size of the malloc with the input. If the user enter number larger than the malloc i want to ask again to enter a new number.
But in this code, if an user enter a too large number, it's looping lot of time (size of the word / 8) i think.
How to ask again to the user to enter new number without looping 4 times for example.
See the example i made with big number.
The idea was to free the input after the loop but it's doesn't works. Any ideas ?
There is my code :
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <stdbool.h>
#include <string.h>
int main(void) {
char x[8];
char y[8];
int result = 0;
char *input=malloc(sizeof(char)*8);
bool answer = 0;
char *pos;
while(!answer) {
fgets(input, sizeof(input)-1, stdin);
//remove the /n from fgets
if ((pos=strchr(input, '\n')) != NULL)
*pos = '\0';
result = sscanf (input, "%s %s", x, y);
printf("%d\n", result);
if(result < 2) {
fprintf(stderr, "There is an error with the number you give, try again\n");
} else {
printf("%s\n", x);
printf("%s\n", y);
}
}
return 0;
}
And the output for : "01 01"
01 01
2
01
01
Output for : 000000005 000000005
0000000000005 000000000000005
1
There is an error with the number you give, try again
1
There is an error with the number you give, try again
2
5
0000
1
There is an error with the number you give, try again
1
There is an error with the number you give, try again
fgets() doesn't throw away the rest of the line when it's longer than its buffer. You have to do it yourself.
If you look at this code I frequently use with fgets, you'll see the two tasks separated, and in which circumstances which one is done:
/*Returns 0 if OK, a negative value if EOF.*/
int fpurge(FILE *f)
{
int c;
while((c=fgetc(f))!=EOF && c!='\n')
{ }
return (c==EOF ? -1 : 0);
}
/* Returns a nonzero value if found, zero if not. */
int truncate_newline(char *str)
{
int bRet=0;
if(str!=NULL)
{
char *pNewLine = strchr(str, '\n');
if(pNewLine!=NULL)
{
bRet = 1;
*pNewLine = '\0';
}
}
return bRet;
}
/* Returns 0 if buffer is full, a positive value if line is complete,
a negative value if EOF (implies buffer full). */
int fclean(char *str, FILE *f)
{
int ret = 1;
if(!truncate_newline(str))
ret = fpurge(f);
return ret;
}
You can see that your own code does the truncate_newline part, but not the "throw away the rest of the line" (here in the function fpurge) part.
If you change your code thusly, it should work:
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <stdbool.h>
#include <string.h>
#define BUFFER_SIZE 8
int main(void) {
char x[BUFFER_SIZE];
char y[BUFFER_SIZE];
int result = 0;
char *input=calloc(BUFFER_SIZE, sizeof(char));
bool answer = 0;
char *pos;
while(!answer) {
fgets(input, BUFFER_SIZE, stdin);
//remove the /n from fgets
if ((pos=strchr(input, '\n')) != NULL)
*pos = '\0';
else
{
int c;
while((c=getchar())!='\n' && c!=EOF) {}
}
result = sscanf (input, "%s %s", x, y);
printf("%d\n", result);
if(result < 2) {
fprintf(stderr, "There is an error with the number you give, try again\n");
} else {
printf("%s\n", x);
printf("%s\n", y);
}
}
return 0;
}
Or simply replace the whole if() with fclean(input, stdin);

Remove leading zeros error

I am trying to remove the leading zeros of the number user enters so 000002 will turn into 2
However, I am getting an error saying Segmentation fault (core dumped)
#include <stdio.h>
#include <string.h>
int main()
{
char *str;
scanf("%c", *str);
int n;
if( ( n = strspn(str, "0" ) ) != 0 && str[n] != '\0' ) {
printf("String without leading zeros is %s \n", &str[n]);
} else {
printf("No leading zeros in %c \n", str);
}
return 0;
}
Change %c to %s and *str to str.
You don't need to use the * when scanning.
Besides the errors pointed out in the previous answers, scanf("%d") will take care of removing leading zeroes for you. Do the test:
#include <stdio.h>
int main()
{
int a;
scanf("%d", &a);
printf("%d\n",a);
return 0;
}
And if you absolutely need a string, just convert with sprintf:
#include <stdio.h>
int main()
{
char str[256];
int a;
scanf("%d", a);
sprintf(str, "%d", a);
puts(str);
return 0;
}
remove * from this:
scanf("%c", *str);
and change %c to %s because you are scanning a string not character
As #user3291093 has said, you need to change %c to %s since you are reading a string/char array and not a single character.
Also you need to malloc an area to store the array. For example:
char *str = NULL;
str = malloc(100*sizeof(char));
scanf("%s", str);
The compiler should have warned about this problem. Insure warnings are enabled.
char *str;
scanf("%c", *str); // "%c" does not match `*str` for scanf()
Suspect OP wanted something like
char str[100];
if (scanf("%99s", str) == 1) Continue_Along_the_Happy_Path();
An alternative fgets() solution.
char str[100];
fgets(str, sizeof str, stdin);
char *p = buffer;
while (*p == '0') p++;
if (p != buffer) {
printf("String without leading zeros is %s", p);
} else {
printf("No leading zeros in %s", str);
}

Returning position of any character in the text

The program is designed to return the position of the character in the table s2, in the text of Table S1. In case of failure it will a return -1.
#include <stdio.h>
#include <stdlib.h>
#define RANGE 10
int any(char [], char []);
int main()
{
char s1[RANGE];
char s2[RANGE];
int i,j;
while( (s1[i]=getchar()) != EOF);
while( (s2[j]=getchar()) != EOF);
printf("%d", any(s1, s2));
}
int any(char s1[], char s2[])
{
int i,j;
for(i=0;s1[i]!='\0';i++)
for(j=0;s2[j]!='\0';j++)
{
// for debug
printf("\n%s", s1[i]);
printf("\n%s", s2[j]);
//
if(s1[i]==s2[j])
return i;
}
return -1;
}
It seems to me that the problem occurs when comparing the characters in the tables.
In this case, programme should return -1:
The code has the following problems:
(1) Variables i and j are uninitialized in the code, potentially causing a crash:
int i,j;
while( (s1[i]=getchar()) != EOF);
while( (s2[j]=getchar()) != EOF);
(2) The code also needs to increment the values of i and j as input is being read. Failing to do so will cause all input to be written to s1[0] / s2[0]:
while( (s1[i]=getchar()) != EOF);
while( (s2[j]=getchar()) != EOF);
(3) The terminating ^Z characters should be removed from s1 / s2 (you might also want to remove the 0x0A (line feed)).
(4) The debug statements are outputting characters, not strings, so the printf() format string should be "\n%c", not "\n%s".
Cleaning up your code gives the following working version:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define RANGE 10
int any(char [], char []);
int main()
{
char s1[RANGE];
char s2[RANGE];
int i,j;
i = j = 0;
while( (s1[i++]=getchar()) != EOF);
s1[i-2] = 0;
while( (s2[j++]=getchar()) != EOF);
s2[j-2] = 0;
printf("%d", any(s1, s2));
}
int any(char s1[], char s2[])
{
int i,j;
for(i=0;s1[i]!='\0';i++)
for(j=0;s2[j]!='\0';j++)
{
// for debug
printf("\n%c", s1[i]);
printf("\n%c", s2[j]);
//
if(s1[i]==s2[j])
return i;
}
return -1;
}
The output for 'aaaa^Z' / 'bbbb^Z' is:
// for debug
printf("\n%s", s1[i]);
printf("\n%s", s2[j]);
%s signifies that the argument is a string (aka char*) but you are actually passing just a char.
Try this:
// for debug
printf("\n%c", s1[i]);
printf("\n%c", s2[j]);

Resources