2
\$\begingroup\$

I have implemented the code for finding the longest common substring between two strings in C language.

Syntax: int compute_lcs(char *first_string, char *second_string, struct lcs_result *lcsr, int *error_num_ptr);

I know that I can declare/define variables anywhere in a function but I don't do that. I use K & R style of declaring/defining all variables at the top of the function. So, please don't give review comments on this.

The code has been compiled using the following gcc flags:

-Wall -Werror -Wextra -Wundef -Wunreachable-code -Winit-self -Wparentheses -Wconversion -Wsign-conversion -Wsign-compare -Werror-implicit-function-declaration -Wmissing-prototypes -Wmissing-declarations -Wformat-security

The code is below:


longest_common_substring.c


#include "longest_common_substring.h"

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

/*
 * const char *get_error_string(int error_num):
 *
 * Function get_error_string() returns the error string corresponding to the
 * value in 'error_num' argument.
 */
const char *get_error_string(int error_num)
{

    switch (error_num) {
        case NO_ERROR:
            return "No error happened.";
        case FIRST_STRING_IS_NULL:
            return "Argument 'first_string' is NULL.";
        case SECOND_STRING_IS_NULL:
            return "Argument 'second_string' is NULL.";
        case FIRST_STRING_IS_EMPTY:
            return "Argument 'first_string' is empty.";
        case SECOND_STRING_IS_EMPTY:
            return "Argument 'second_string' is empty.";
        case LCSR_IS_NULL:
            return "Argument 'lcsr' is NULL.";
        default:
            return "Invalid error number given.";
    } // end of switch

} // end of function get_error_string

/*
 * int compute_lcs(char *first_string, char *second_string, struct lcs_result *lcsr, int *error_num_ptr):
 *
 * Fucntion compute_lcs() finds the longest common substring between 'first_string'
 * and 'second_string'.
 */
int compute_lcs(char *first_string, char *second_string, struct lcs_result *lcsr, int *error_num_ptr)
{

    long first_string_len = 0;
    long second_string_len = 0;
    long temp_first_string_start_index = -1;
    long temp_first_string_end_index = -1;
    long temp_second_string_start_index = -1;
    long temp_second_string_end_index = -1;
    long cs_len = 0;
    long i = 0, j = 0, m = 0, n = 0;
    int find_no_more = 0;
    int some_cs_found = 0;

    if (!first_string) {
        if (error_num_ptr)
            *error_num_ptr = FIRST_STRING_IS_NULL;
        return LCS_NOT_FOUND;
    }

    if (!second_string) {
        if (error_num_ptr)
            *error_num_ptr = SECOND_STRING_IS_NULL;
        return LCS_NOT_FOUND;
    }

    if (!*first_string) {
        if (error_num_ptr)
            *error_num_ptr = FIRST_STRING_IS_EMPTY;
        return LCS_NOT_FOUND;
    }

    if (!*second_string) {
        if (error_num_ptr)
            *error_num_ptr = SECOND_STRING_IS_EMPTY;
        return LCS_NOT_FOUND;
    }

    if (!lcsr) {
        if (error_num_ptr)
            *error_num_ptr = LCSR_IS_NULL;
        return LCS_NOT_FOUND;
    }

    lcsr->first_string_start_index = -1;
    lcsr->first_string_end_index = -1;
    lcsr->second_string_start_index = -1;
    lcsr->second_string_end_index = -1;

    first_string_len = (long)(strlen(first_string));
    second_string_len = (long)(strlen(second_string));

    for (i = 0; i < first_string_len; i = i + 1) {

        for (j = 0; j < second_string_len; j = j + 1) {

            temp_first_string_start_index = -1;
            temp_first_string_end_index = -1;
            temp_second_string_start_index = -1;
            temp_second_string_end_index = -1;
            some_cs_found = 0;

            for (m = i, n = j; ((m < first_string_len) && (n < second_string_len)); m = m + 1, n = n + 1) {
                if (second_string[n] != first_string[m]) {
                    break;
                }

                some_cs_found = 1;

                if (temp_first_string_start_index == -1) {

                    if (temp_second_string_start_index != -1) {
                        fprintf(stderr, "Error: temp_first_string_end_index is -1 but"
                               " temp_second_string_start_index is not -1. Exiting..");
                        exit(1);
                    }

                    temp_first_string_start_index = m;
                    temp_first_string_end_index = m;
                    temp_second_string_start_index = n;
                    temp_second_string_end_index = n;

                } else {

                    temp_first_string_end_index = m;
                    temp_second_string_end_index = n;

                } // end of if else temp_first_string_start_index == -1

            } // end of for m, n

            if (some_cs_found == 1) {

                if ((lcsr->first_string_start_index == -1) ||
                    ((temp_first_string_end_index - temp_first_string_start_index + 1) > (lcsr->first_string_end_index - lcsr->first_string_start_index + 1))) {

                    lcsr->first_string_start_index = temp_first_string_start_index;
                    lcsr->first_string_end_index = temp_first_string_end_index;
                    lcsr->second_string_start_index = temp_second_string_start_index;
                    lcsr->second_string_end_index = temp_second_string_end_index;

                }

                // now check if length of CS is equal to length of any string
                cs_len = lcsr->first_string_end_index - lcsr->first_string_start_index + 1;
                if ((cs_len == first_string_len) || (cs_len == second_string_len)) {
                    find_no_more = 1;
                    break;
                }

            } // end of if some_cs_found == 1

        } // end of for j

        if (find_no_more == 1) {
            break;
        }

    } // end of for i

    if (lcsr->first_string_start_index == -1)
        return LCS_NOT_FOUND;
    
    return LCS_FOUND;

} // end of compute_lcs


longest_common_substring.h


#ifndef LONGEST_COMMON_SUBSTRING_H
#define LONGEST_COMMON_SUBSTRING_H

#define LCS_NOT_FOUND 0
#define LCS_FOUND 1

struct lcs_result {
    long first_string_start_index;
    long first_string_end_index;
    long second_string_start_index;
    long second_string_end_index;
};

enum {
    NO_ERROR = 0, // No error happened
    FIRST_STRING_IS_NULL = -1, // Argument 'first_string' is NULL
    SECOND_STRING_IS_NULL = -2, // Argument 'second_string' is NULL
    FIRST_STRING_IS_EMPTY = -3, // Argument 'first_string' is empty
    SECOND_STRING_IS_EMPTY = -4, // Argument 'second_string' is empty
    LCSR_IS_NULL = -5, // Argument 'lcsr' is NULL
};

/*
 * const char *get_error_string(int error_num):
 *
 * Function get_error_string() returns the error string corresponding to the
 * value in 'error_num' argument.
 */
const char *get_error_string(int error_num);

/*
 * int compute_lcs(char *first_string, char *second_string, struct lcs_result *lcsr, int *error_num_ptr):
 *
 * Fucntion compute_lcs() finds the longest common substring between 'first_string'
 * and 'second_string'.
 */
int compute_lcs(char *first_string, char *second_string, struct lcs_result *lcsr, int *error_num_ptr);

#endif


test_longest_common_substring.c


#include "longest_common_substring.h"

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

char *get_input_from_stdin_and_discard_extra_characters(char *str, long size);

#define ARRAY_SIZE 256

int main(void)
{

    struct lcs_result lcsr;
    char first_string[ARRAY_SIZE] = {0};
    char second_string[ARRAY_SIZE] = {0};
    int error_num = 0;
    char *arg_first_string = NULL;
    char *arg_second_string = NULL;
    struct lcs_result *arg_lcsr = NULL;
    int *arg_error_num_ptr = NULL;
    int ret_val = LCS_NOT_FOUND;
    char user_input_yes_no[2] = {0};

    while (1) {

        system("clear");

        lcsr.first_string_start_index = -1;
        lcsr.first_string_end_index = -1;
        lcsr.second_string_start_index = -1;
        lcsr.second_string_end_index = -1;

        error_num = 0;

        arg_first_string = first_string;
        arg_second_string = second_string;
        arg_lcsr = &lcsr;
        arg_error_num_ptr = &error_num;

        printf("\nPlease input first string (max 255 characters) (To enter NULL"
               " string, type NULL and press ENTER): ");
        get_input_from_stdin_and_discard_extra_characters(first_string, ARRAY_SIZE);
        if (strcmp(first_string, "NULL") == 0) {
            arg_first_string = NULL;
        }

        printf("\nPlease input second string (max 255 characters) (To enter NULL"
               " string, type NULL and press ENTER): ");
        get_input_from_stdin_and_discard_extra_characters(second_string, ARRAY_SIZE);
        if (strcmp(second_string, "NULL") == 0) {
            arg_second_string = NULL;
        }

        while (1) {
            printf("\nDo you want pass argument 'lcsr' as NULL? [y/n]: ");
            get_input_from_stdin_and_discard_extra_characters(user_input_yes_no, 2);
            if (strcmp(user_input_yes_no, "y") == 0) {
                arg_lcsr = NULL;
                break;
            } else if (strcmp(user_input_yes_no, "n") == 0) {
                break;
            }
        }

        user_input_yes_no[0] = 0; user_input_yes_no[1] = 0;
        while (1) {
            printf("\nDo you want pass argument 'error_num_ptr' as NULL? [y/n]: ");
            get_input_from_stdin_and_discard_extra_characters(user_input_yes_no, 2);
            if (strcmp(user_input_yes_no, "y") == 0) {
                arg_error_num_ptr = NULL;
                break;
            } else if (strcmp(user_input_yes_no, "n") == 0) {
                break;
            }
        }

        printf("\n");
        printf("\n-----------------");
        printf("\nInput parameters:");
        printf("\n-----------------\n");
        printf("first_string = \"%s\" (length = %zu)\n", arg_first_string ? arg_first_string : "(null string)", arg_first_string ? strlen(arg_first_string) : 0);
        printf("second_string = \"%s\" (length = %zu)\n", arg_second_string ? arg_second_string : "(null string)", arg_second_string ? strlen(arg_second_string) : 0);

        printf("\n-------");
        printf("\nResult:");
        printf("\n-------\n");
        ret_val = compute_lcs(arg_first_string, arg_second_string, arg_lcsr, arg_error_num_ptr);
        if (ret_val == LCS_FOUND) {
            long lcs_len = lcsr.first_string_end_index - lcsr.first_string_start_index + 1;
            printf("Longest common substring = \"%.*s\" (length = %ld)\n",
                   (int)(lcs_len), first_string + lcsr.first_string_start_index, lcs_len);
            printf("First string (Index starts from 0): start index of LCS = %ld, end index of LCS = %ld\n",
                   lcsr.first_string_start_index, lcsr.first_string_end_index);
            printf("Second string (Index starts from 0): start index of LCS = %ld, end index of LCS = %ld\n",
                   lcsr.second_string_start_index, lcsr.second_string_end_index);
            printf("\n");
        } else {
            printf("Longest common substring not found.");
            if (arg_error_num_ptr)
                printf(" Error: %s\n", get_error_string(error_num));
            else
                printf("\n");
            printf("\n");
        }

        printf("\n\nPlease press ENTER to continue..");
        // now clear the stdin input buffer
        get_input_from_stdin_and_discard_extra_characters(NULL, 0);

    } // end of while (1) loop

    return(0);

} // end of main

/*
 * get_input_from_stdin_and_discard_extra_characters(char *str, long size):
 *
 * Function get_input_from_stdin_and_discard_extra_characters() reads at most
 * 'size - 1' characters into 'str' from stdin and then appends the null
 * character ('\0'). If 'size' is 0 then this function will discard all input
 * and return NULL. So, to discard all input, this function can be called with
 * 'str' having value NULL and 'size' having value 0.
 * In all cases, reading input stops after encountering a newline ('\n') or EOF
 * even if 'size - 1' characters have not been read. If a newline ('\n') or EOF
 * is read then it is replaced by null character ('\0'). If there are extra
 * characters in input, they are read and discarded.
 * In all cases, 'str' or NULL is returned.
 */
char *get_input_from_stdin_and_discard_extra_characters(char *str, long size)
{

    int c = 0;
    long i = 0;

    // If size is 0 then this function will discard all input and return NULL.
    // No need to check str if size is 0.
    if (size == 0) {
        // discard all input
        while ((c = getchar()) && (c != '\n') && (c != EOF));
        return NULL;
    }

    if (!str)
        return str;

    if (size < 0)
        return NULL;

    for (i = 0; i < (size - 1); i = i + 1) {

        c = getchar();

        if ((c == '\n') || (c == EOF)) {
            str[i] = 0;
            return str;
        }

        str[i] = (char)(c);

    } // end of for loop

    str[i] = 0;

    // discard rest of input
    while ((c = getchar()) && (c != '\n') && (c != EOF));

    return str;

} // end of get_input_from_stdin_and_discard_extra_characters

\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

How I Review Code

The criteria I use for code reviews is:

  1. Does the code compile without errors and warnings?
  2. Does the code work as expected?
  3. Is the code easy to maintain, especially by others?
  4. Is the code portable (will it compile and run on multiple systems, Window, Linux and Unix)?
  5. Does the code follow best practices? Usually this goes hand in hand with number 3.
  6. How complex is the code? (Really also part of number 3)
  7. Is the code extendable?

General Observations

There are some good points to the code, the header file longest_common_substring.h is generally well written.

Does the code compile without errors and warnings?

Yes

Does the code work as expected?

It does as far as I can test it, but I don't feel the program is especially user friendly.

  1. There is no way the user can terminate the main loop using the keyboard.
  2. For unit testing purposes it might be better to allow the user to use a test file as input so that the tests are repeatable. Another option would be to remove the user input completely and implement tests with expected out put.
  3. There doesn`t seem to be a way to test the error handling portion of the code, which means the code can't be fully unit tested. How does one force errors into the input?
  4. There is no new line after the prompt for user input.

Is the code easy to maintain, especially by others?

No. While the variable names and function names are very descriptive, the code doesn't follow general good programming practices, and it is too complex.

  1. The code doesn't follow the Don't Repeat Yourself principle.
  2. The code doesn't follow the Single Responsibility Principle.
  3. While each variable is declared and initialized on a single line, which is a very good practice, the question author wants to ignore the best practice of declaring variables as you need them and insists on using the obsolete K&R style of declaring variables which has been out of date since the ANSI Standard for C was first introduced in 1989.
  4. The code doesn't follow KISS principle.
  5. The code doesn't use C library functions such as fgets().

Is the code portable (will it compile and run on multiple systems, Window, Linux and Unix)?

Yes.

  1. Is the code extendable?

No, an example of how the code is not extendable and not easy to maintain is the following code:

        printf("\nPlease input first string (max 255 characters) (To enter NULL"
            " string, type NULL and press ENTER): ");
        get_input_from_stdin_and_discard_extra_characters(first_string, ARRAY_SIZE);
        if (strcmp(first_string, "NULL") == 0) {
            arg_first_string = NULL;
        }

The printf() statement above should be formatted to print an integer value for max characters, and the integer value passed to the formatting should be ARRAY_SIZE - 1.

        printf("\nPlease input first string (max %d characters) (To enter NULL"
            " string, type NULL and press ENTER): ", ARRAY_SIZE - 1);
        get_input_from_stdin_and_discard_extra_characters(first_string, ARRAY_SIZE);
        if (strcmp(first_string, "NULL") == 0) {
            arg_first_string = NULL;
        }

The formatting of the code is inconsistent, in the printf() statement above the code is wrapped at under 90 characters, but later in main is the following printf() which is 167 characters:

        printf("second_string = \"%s\" (length = %zu)\n", arg_second_string ? arg_second_string : "(null string)", arg_second_string ? strlen(arg_second_string) : 0);

This statement can be more easily broken into multiple lines than the earlier printf() statement.

        printf("second_string = \"%s\" (length = %zu)\n", arg_second_string ?
            arg_second_string : "(null string)", arg_second_string ?
            strlen(arg_second_string) : 0);

I voted up on this question, I suspect, but don't know for sure that the reason this question received a down vote is this statement: I know that I can declare/define variables anywhere in a function but I don't do that. I use K & R style of declaring/defining all variables at the top of the function. So, please don't give review comments on this.

Declare the Variables as Needed

I realize you don`t want comments on this, but one of the reasons for declaring variables as the are needed is that it limits the scope of the variable to the code block it is declared in. This makes it easier to maintain the code because if the maintainer feels that it is necessary to break the code into smaller functions to implement new features the code can be easily moved and still compiles properly. This code is harder to maintain because it is quite difficult to create new functions.

Use Library Functions Where Possible

The function get_input_from_stdin_and_discard_extra_characters(char* str, long size) can be greatly simplified using the C library function fgets(char * str, int num, FILE * stream), the whole point of this function is to read a single line from a file, whether that file is stdin or some other file doesn't matter.

char* get_input_from_stdin_and_discard_extra_characters(char* str, long size)
{
    char buffer[BUFSIZ];

    // Clear the input, no matter the result
    fgets(buffer, BUFSIZ, stdin);

    // If size is 0 then this function will discard all input and return NULL.
    // No need to check str if size is 0.
    if (size <= 0) {
        return NULL;
    }

    if (str)
    {
        int length = strlen(buffer);
        strncpy(str, buffer, ((length < size) ? length : size));
    }

    return str;
}

DRY Code

There is a programming principle called the Don't Repeat Yourself Principle sometimes referred to as DRY code. If you find yourself repeating the same code multiple times it is better to encapsulate it in a function. If it is possible to loop through the code that can reduce repetition as well.

This code in main() could be replaced with function calls:

        printf("\nPlease input first string (max 255 characters) (To enter NULL"
            " string, type NULL and press ENTER): ");
        get_input_from_stdin_and_discard_extra_characters(first_string, ARRAY_SIZE);
        if (strcmp(first_string, "NULL") == 0) {
            arg_first_string = NULL;
        }

        printf("\nPlease input second string (max 255 characters) (To enter NULL"
            " string, type NULL and press ENTER): ");
        get_input_from_stdin_and_discard_extra_characters(second_string, ARRAY_SIZE);
        if (strcmp(second_string, "NULL") == 0) {
            arg_second_string = NULL;
        }

Here are 2 functions that reduce the repetition in main(), this code requires one additional standard C header file, stdbool.h:

char* get_user_input_testStrings(char *prompt_value)
{
    char input_sting[ARRAY_SIZE] = { 0 };
    char* result = NULL;

    printf("\nPlease input %s (%d) (To enter NULL string, type NULL and press ENTER): ",
        prompt_value, ARRAY_SIZE);
    get_input_from_stdin_and_discard_extra_characters(input_sting, ARRAY_SIZE);

    if (strcmp(input_sting, "NULL") != 0) {
        result = strdup(input_sting);
    }
    return result;
}

bool yes_no_user_input(char* user_prompt)
{
    bool answer_is_yes = false;

    while (1) {
        char user_input_yes_no[2] = { 0 };
        printf("\nDo you want pass argument '%s' as NULL? [y/n]: ", user_prompt);
        char* user_response =
            get_input_from_stdin_and_discard_extra_characters(user_input_yes_no, 2);
        if (*user_response == 'y') {
            answer_is_yes = true;
            break;
        }
        else if (*user_response == 'n') {
            break;
        }
    }

    return answer_is_yes;
}

This reduces the code in main() to:

        char *arg_first_string = get_user_input_testStrings("first string");
        char* arg_second_string = get_user_input_testStrings("second string");
        if (!yes_no_user_input("lscr"))
        {
            arg_lcsr = &lcsr;
        }
        if (!yes_no_user_input("error_num_ptr"))
        {
            arg_error_num_ptr = &error_num;
        }

Code Organization

Function prototypes are very useful in large programs that contain multiple source files, and that in case they will be in header files. In a single file program like this it is better to put the main() function at the bottom of the file and all the functions that get used in the proper order above main(). Keep in mind that every line of code written is another line of code where a bug can crawl into the code.

Reduce Depenencies

It is important to reduce dependencies between modules so that code can stand on it's own and be reused. To reduce dependencies, the an initialization function for the struct lcs_result should be added to source file longest_common_substring.c with a function prototype defined in longest_common_substring.h.

void init_lcs_struct(struct lcs_result* lcsr)
{
    lcsr->first_string_start_index = -1;
    lcsr->first_string_end_index = -1;
    lcsr->second_string_start_index = -1;
    lcsr->second_string_end_index = -1;
}

Complexity

The functions main() and int compute_lcs(char* first_string, char* second_string, struct lcs_result* lcsr, int* error_num_ptr) are too complex (do too much). A general best practice in programming is keep functions size to one screen in an editor or IDE, any function larger than this is considered difficult to understand and maintain. Both of the functions mentioned are larger than a single screen. A second measure of complexity is the level of indentaation in a function.

The art or science of programming is to break difficult problems into smaller and smaller pieces until each piece is very easy to solve.

As programs grow in size the use of main() should be limited to calling functions that parse the command line, calling functions that set up for processing, calling functions that execute the desired function of the program, and calling functions to clean up after the main portion of the program.

There is also a programming principle called the Single Responsibility Principle that applies here. The Single Responsibility Principle states:

that every module, class, or function should have responsibility over a single part of the functionality provided by the software, and that responsibility should be entirely encapsulated by that module, class or function.

The Single Responsibility Principle is one of the 5 pillars of SOLID programming which is important in Object Oriented programming. While the C programming language does not support object oriented programming, certain principles can be applied, this princple is one of them.

To reduce the complexity of main(), using the functions defined above as well as some additional functions shown here, main() can be reduced to 34 lines of code:

void perform_test_and_report(char* arg_first_string, char* arg_second_string,
    struct lcs_result* arg_lcsr, int* arg_error_num_ptr)
{
    int ret_val = LCS_NOT_FOUND;

    printf("\n");
    printf("\n-----------------");
    printf("\nInput parameters:");
    printf("\n-----------------\n");
    printf("first_string = \"%s\" (length = %zu)\n", arg_first_string ? arg_first_string :
        "(null string)", arg_first_string ? strlen(arg_first_string) : 0);
    printf("second_string = \"%s\" (length = %zu)\n", arg_second_string ?
        arg_second_string : "(null string)", arg_second_string ?
        strlen(arg_second_string) : 0);

    printf("\n-------");
    printf("\nResult:");
    printf("\n-------\n");
    ret_val = compute_lcs(arg_first_string, arg_second_string, arg_lcsr, arg_error_num_ptr);
    if (ret_val == LCS_FOUND) {
        long lcs_len = arg_lcsr->first_string_end_index - arg_lcsr->first_string_start_index + 1;
        printf("Longest common substring = \"%.*s\" (length = %ld)\n",
            (int)(lcs_len), arg_first_string + arg_lcsr->first_string_start_index, lcs_len);
        printf("First string (Index starts from 0): start index of LCS = %ld, end index of LCS = %ld\n",
            arg_lcsr->first_string_start_index, arg_lcsr->first_string_end_index);
        printf("Second string (Index starts from 0): start index of LCS = %ld, end index of LCS = %ld\n",
            arg_lcsr->second_string_start_index, arg_lcsr->second_string_end_index);
        printf("\n");
    }
    else {
        printf("Longest common substring not found.");
        if (arg_error_num_ptr)
            printf(" Error: %s\n", get_error_string(*arg_error_num_ptr));
        else
            printf("\n");
        printf("\n");
    }
}

int main(void)
{
    while (1) {
        system("clear");

        int* arg_error_num_ptr = NULL;
        struct lcs_result lcsr;
        struct lcs_result* arg_lcsr = NULL;
        init_lcs_struct(&lcsr);

        int error_num = 0;

        char *arg_first_string = get_user_input_testStrings("first string");
        char* arg_second_string = get_user_input_testStrings("second string");
        if (!yes_no_user_input("lscr"))
        {
            arg_lcsr = &lcsr;
        }
        if (!yes_no_user_input("error_num_ptr"))
        {
            arg_error_num_ptr = &error_num;
        }

        perform_test_and_report(arg_first_string, arg_second_string, arg_lcsr, 
            arg_error_num_ptr);

        printf("\n\nPlease press ENTER to continue..");
        // now clear the stdin input buffer
        get_input_from_stdin_and_discard_extra_characters(NULL, 0);

    } // end of while (1) loop

    return(0);

} // end of main```

\$\endgroup\$
16
  • \$\begingroup\$ Thanks for voting up on this question. \$\endgroup\$
    – user245050
    Mar 7, 2022 at 11:12
  • \$\begingroup\$ About this: author wants to ignore the best practice of declaring variables as you need them and insists on using the obsolete K&R style of declaring variables which has been out of date since the ANSI Standard for C was first introduced in 1989.: The flexibility of declaring/defining variables when needed came with C99 (1999) and not with C89 (1989). Many developers around the world and many open source projects are still using obsolete K&R style of declaring variables. I worked for Juniper Networks from 2008 - 2010 and there also everyone was using obsolete K&R style of declaring variables \$\endgroup\$
    – user245050
    Mar 7, 2022 at 11:13
  • \$\begingroup\$ Obsolete K&R style of declaring variables is still very popular. You can check source code of open source projects. \$\endgroup\$
    – user245050
    Mar 7, 2022 at 11:13
  • \$\begingroup\$ I worked for around 12 years extensively in C from 2000 to 2012 and I worked in 4 companies. No where I saw anyone doing declare/define variables when needed. I think that most of the people who still write code in C follow K&R style of declaration. I worked for a company in 2020 in C language and there also people were doing K&R style of declaration. On codereview.stackexchange.com, I see that most of the reviewers recommend declare/define variables when needed. I think that they are from C++ background rather than extensive C background. \$\endgroup\$
    – user245050
    Mar 7, 2022 at 13:58
  • \$\begingroup\$ @Amit I started programing in C in 1983, K&R was the only reference book, I still have a first edit, which is not ANSI. In 1991 I had to convert all the code I wrote from C to C++. I've been writing code in C professionally since 1984 and C++ since 1991. There are good reasons to change. \$\endgroup\$
    – pacmaninbw
    Mar 7, 2022 at 13:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.