2

I'm writing my first ever program in C and it's giving me a lot of problems. It's fairly simple; input a number and the output will be the corresponding term in the Fibonacci sequence where the first and second terms are 1. It was initially working as long as I didn't put anything other than a number as the input; letters or special characters caused a segmentation fault. To fix this, I tried to reject all non-numeric inputs, and since I couldn't find a function to do this I made my own. Unfortunately, it now gives a segmentation fault when a numeric input is given, and all non-numeric inputs are read as 26.

The compiler, gcc with pedantic warnings, only complains about my comments. I've used GDB to narrow the segmentation fault to:

return strtol(c, n, 10);

Any help for identifying the problem and avoiding it next time would be greatly appreciated.

The Code:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main()
{
  calcTerm(); //Run calcTerm()
  return 0; //Return value & exit
}

int fibTerm(int term)
{
  //Declare Variables
  int a = 0;
  int b = 1; 
  int next;
  int x;

  //Calculate the sequence
  for (x = 0; x <= (term - 2); x++)
  {
    next = a + b;
    a = b;
    b = next;
  }

  return next; //return the requested output
}

int calcTerm()
{
  //declare variables
  int in;
  char rawIn[256];
  char **n;
  int out;

  printf("Input the term you want to find:\n"); //request input

  //get input
  fgets(rawIn, 3, stdin);

  //define variables
  in = isNumeric(rawIn); /*strtol(rawIn, n, 10) works*/
  out = fibTerm(in);

  //print result
  printf("Term %i " "is %i", in, out);
}

int isNumeric(char test[256])
{
  //declare variables
  char validChars[10] = "0123456789"; //valid input characters
  char *c = test;
  char **n;

  if (strpbrk(test, validChars)) //if input contains only valid characters ?
  {
    return strtol(c, n, 10); //return the input as an integer
    //segmentation fault; strtol_l.c: no such file
  }
  else
  {
    printf("Please only input numbers."); //error message
  }

}
CybeatB
  • 57
  • 3
  • 9
  • The program does run correctly for me – Gunther Piez Jun 01 '11 at 10:23
  • The updated code works fine for me; there are a few oddities here and there (such as the usage of ``sscanf`` in ``isNumeric`` which basically overwrites ``validChars`` with the first word of the string found in ``c``), but in general it is OK. Note that your current code evaluates the Fibonacci sequence starting from (0, 1), not from (1, 1). – Tamás Jun 01 '11 at 11:21

2 Answers2

4

n is unitialized and it points to nowhere. strtol will try to write to the memory address pointed to by n, which could be anywhere in the memory and it is likely not pointing to an area where you are alloweed to write. Simply pass a null value there (i.e. strtol(c, 0, 10)).

By the way, I'd try to use sscanf to parse the number; sscanf returns the number of tokens parsed successfully, so if you get a zero as a return value, the number was invalid. E.g.:

const char* my_string = "  123";
const char* my_invalid_string = "spam spam spam";
int number;
sscanf(my_string, "%d", &number);    // this should return 1
sscanf(my_invalid_string, "%d", &number); // this should return 0

And since you are reading from the standard input anyway, you can skip storing the line in a string and then calling sscanf, you can simply use scanf to parse the standard input directly.

Tamás
  • 47,239
  • 12
  • 105
  • 124
  • That fixed the segmentation fault, but now the input for 1 generates seemingly random results. Output for 1: "Term 1 is 1197354752". – CybeatB Jun 01 '11 at 10:47
  • ...or ask another question, posting just the section of code where the problem is occurring. – razlebe Jun 01 '11 at 11:17
  • I think it's part of the calculation... An input of 1 results in x starting at 0 and increasing until it reaches -1. I should've seen that sooner. – CybeatB Jun 01 '11 at 11:22
  • 1
    Aaah, your're right. Simply make sure that ``next`` is not uninitialized then and it should work. – Tamás Jun 01 '11 at 11:24
1

You get random output for the input 1 because in fibTerm the loop will never be entered (for (x = 0; x <= (term - 2); x++) with term == 1). Therefore, the uninitialized next value will be returned

king_nak
  • 11,313
  • 33
  • 58