-1

We are being taught programming using C in this semester and in our first assignment we were asked to print the list of values of sin(x), cos(x) and tan(x) using manual and library implementations. So, I wrote the following code:

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

#define START   0
#define STOP    360
#define STEP    10

#define PI      3.14159265358979323846  /*For conversion: degrees <-> radians */

double rad(double x);   /* Converts angle in degrees to radians */
double next_term(double angle, int term_index);

/* Function prototypes for manual implementation of sin(x), cos(x) and tan(x) */
double sin_series(double x);
double cos_series(double x);
double tan_series(double x);


int main() {

    /* Creating and printing the table title:
    ** ==================================================================== */

    char table_title[] = "   n | ";
    strcat(table_title, "sin series | sin library | ");
    strcat(table_title, "cos series | cos library | ");
    strcat(table_title, "tan series | tan library | ");

    printf("%s \n", table_title);

    /* ==================================================================== */



    /* Creating and printing the line between the title and the table:
    ** ==================================================================== */

    char* second_line = (char*)malloc((strlen(table_title) + 1) * sizeof(char));

    for (int i = 0; i < strlen(table_title) - 1; i++) {
        second_line[i] = '=';
    }

    second_line[strlen(table_title)] = '\0';

    printf("%s \n", second_line);

    /* ==================================================================== */

    free(second_line);

    /* Creating each line of the table and printing it:
    ** ==================================================================== */

    for (int angle = 0; angle < 360; angle += 10) {

        printf("%4i | ", angle);
        printf("%10.5f | %11.5f | ",sin_series(angle), sin(rad(angle)) );
        printf("%10.5f | %11.5f | ",cos_series(angle), cos(rad(angle)) );
        printf("%10.5f | %11.5f | ",tan_series(angle), tan(rad(angle)) );
        printf("\n");
    }

    return 0;   
}

double rad(double x) {
    return ((PI * x) / 180);
}

double next_series_term(double angle, int term_index) {
    double result = 1.0;

    for (int i = 0; i < term_index; i++) {
        result *= angle;
        result /= (i + 1);
    }

    return result;
}

unsigned long long factorial(int x) {

    unsigned long long result = 1;

    for (int i = 0; i < x; i++) {
        result *= (i + 1);
    }

    return result;
}

double sin_series(double x) {

    double result = 0;

    if (x == 0 || x == 180 || x == 360) {
        result = 0;
    }
    else {
        for (int i = 0; i < 100; i++) {

        /* Calculating the next term to add to result to increase precision.*/

        double next_term = next_series_term(rad(x), 2*i + 1);
        next_term *= pow(-1,i);


        result += next_term; 
        }
    }


    return result;  
}

double cos_series(double x) {

    double result = 0;

    if (x == 90 || x == 270) {
        result = 0;
    }
    else {
        for (int i = 0; i < 100; i++) {

        /* Calculating the next term to add to result to increase precision.*/

        double next_term = next_series_term(rad(x), 2*i);
        next_term *= pow(-1,i);     

        result += next_term; 
        }

    }

    return result;  
}

double tan_series(double x) {
        return sin_series(x)/cos_series(x); //non-portable! searching for
                                            // better solution
}   

But this code results in Segmentation fault after returning 0 as I found after using gdb and has left me completely baffled. Being a novice in C and programming, this has completely baffled me. Please help.

Crazy-Fool
  • 96
  • 1
  • 13

4 Answers4

4

This declaration

char table_title[] = "   n | ";

That declares table_title to be an array of eight characters. When you append other strings to the end of the array, you will write out of bounds and have undefined behavior.

Either specify a size big enough to hold all the data you need, or initialize it properly with the complete string.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • That means I cannot concatenate strings the way I am intending to without using extra memory ? Anyhow using a large buffer for the tite solved the problem. But still asking. – Crazy-Fool Jan 23 '15 at 11:18
  • @AbhirupMondal you are not using "extra memory". Yes, you won't be able to store dozens of characters in an array of 8 characters. Is that surprising or what? – The Paramagnetic Croissant Jan 23 '15 at 11:30
  • @AbhirupMondal If you don't specify a size when creating the array, it will be the exact size of the string you initialize it to. The `strcat` function doesn't reallocate or otherwise extend the destination string in any way, it just finds the string terminator and starts appending there. – Some programmer dude Jan 23 '15 at 11:30
  • @JoachimPileborg Thanks. That clears up the things. But I was asking whether there was any way in C which could perform the task. (Reallocating memory and extending the string beyond the size of it when it was initialised) – Crazy-Fool Jan 23 '15 at 11:34
  • @TheParamagneticCroissant I was speaking of extra memory as I need to allocate a large enough size most of which may be left unused. Not that I was expecting to store dozens of characters in a 8 char string. :) – Crazy-Fool Jan 23 '15 at 11:35
  • 2
    @AbhirupMondal Yes, declare it as a pointer, allocate the memory dynamically with [`malloc`](http://en.cppreference.com/w/c/memory/malloc), and use [`realloc`](http://en.cppreference.com/w/c/memory/malloc) to reallocate. This brings with it other problems though, and the esiest solution is to just plainly initialize the array with the *complete* string to begin with, there's no need to append a static string to another static string like you do. – Some programmer dude Jan 23 '15 at 11:37
1

table_title you assign a string so the sizof(table_title) will not be able to hold the whole string which you are passing so accessing array out of bound is undefined behavior and might cause crash.

Gopi
  • 19,784
  • 4
  • 24
  • 36
1

Why did you use table_title? There is no need. Just use printf.

printf ("sin series | sin library | cos series | cos library | tan series | tan library | ");

You declared table_title statically. free() is used to deallocate memory that you allocated dynamically. So do it. There wont be segmentation fault.

ninja
  • 809
  • 5
  • 9
  • I need to print the code and submit it for grading. So your option results in line wraps which our instructor does not like. So I felt that to be the solution. Also I needed the string length for the second line. – Crazy-Fool Jan 23 '15 at 11:22
1

Ok then you can use printf as

printf (
    "sin series | sin library | " \
    "cos series | cos library | " \
    "tan series | tan library | ");

There is no wraps. Try this. :)

ninja
  • 809
  • 5
  • 9