I've just made this program and I want to know how to improve it. It just receives a word and prints it backwards. Sequences of numbers are also accepted, but not white spaces (that's why I used scanf). #include <stdio.h>#include <string.h>int main(void){    const unsigned short MAX = 30;    char array[MAX];    unsigned short length;    scanf(%s, array);    length = strlen(array) - 1;    char array2[length];    for (unsigned short i = length, n = 0; i >= 0, n <= length; i--, n++)    {        array2[n] = array[i];        printf(%c, array2[n]);    }    return 0;}
Word Inverter in C
beginner;c;strings
Buffer overflowchar array[MAX];scanf(%s, array);This can overflow the buffer in array if the user input exceeds MAX-1 characters. There are multiple ways around this:Ask scanf to allocate an appropriately sized buffer (if you have a moderately recent glibc):char *array = NULL;scanf(%ms, &array);You need to release the allocated buffer later:free(array);To use free you need to #include <stdlib.h>.Use fgets() and inform it about the buffer size:fgets(array, sizeof(array), stdin);This will read a whole line though and not just a single word. It may also include the newline character at the end that you need to remove yourself:length = strlen(array) - 1;if (array[length] == '\n')    array[length--] = '\0';getline() works in a similar fashion but also allocates a buffer for you; conveniently it also returns the amount of characters read (which may differ from length of the allocated buffer stored in array_size):char *array = NULL;size_t array_size;size_t length = getline(&array, &array_size, stdin);// ... remove potential newline ...// ... do stuff with array ...free(array);getline requires glibc's GNU extensions (#define _GNU_SOURCE) or POSIX.1-2008 (#define _POSIX_C_SOURCE 200809L).Use appropriate data typessize_t for length since that's the return type of strlen at it is guaranteed to hold all possible string lengths. You need to watch out for the corner cases below though to avoid an integer underflow (which you'd also have with any unsigned type).same for i since it depends on length.Corner casesWhat if strlen(array) == 0? Then strlen(array) - 1 has a huge positive value since it underflows the unsigned return type of strlen and wraps around to the largest possible value of that type.In a similar fashion i >= 0 is always true since unsigned types cannot assume values less than 0.You'll have to find a way to take care of these corner cases. What about simply doing nothing in that case since the reversion of the empty string is the empty string itself?length = strlen(array);if (length > 0) {    for (size_t i = length - 1, n = 0; n < length; i--, n++) {        // ...    } }I left out i >= 0 intentionally since it is redundant with n < length. It had also no effect since the , operator in C means that only the right side of it is responsible for the value of the entire (sub-)expression. You probably wanted && but, as I said, the two conditions are (nearly) equivalent here.Unnecessary code and (possibly) better algorithmsYou don't need an array2 if you end up printing the characters one by one. You can just print them directly from array:printf(%c, array[i]);Alternatively you can first revert the string and later print the whole string:for (unsigned short i = length, n = 0; i >= 0, n <= length; i--, n++)    array2[n] = array[i];fwrite(array2, 1, length, stdout);Or you can revert the string in-place without an additional buffer/array:for (unsigned short i = length, n = 0; i > n; i--, n++){    char c = array[n];    array[n] = array[i];    array[i] = c;}puts(array);puts prints the whole string and appends a newline. *nix programs append always terminate their lines by convention (unless they operate on raw bytes).Better character output functionprintf is very comfortable to use if you want formatted output but it's also pretty heavy-weighted. If you're only printing individual characters you can just use:putchar(array[i]);Error checkingYou should check the return values of all functions that may fail if it impacts the outcome of the program. For instance:scanf, fgets, or getline may all return error conditions if an I/O error occurred that would mess up the remainder of the program. You should check for errors and react accordingly (i. e. shut down the program):if (scanf(%ms, &array) <= 0)    // ...if (fgets(...) == NULL)    // ...if (getline(...) == -1)    // ...If an error occurs I suggest you print an error message and return an error condition yourself (which terminates the program if done from main()): if (...) {     perror(Input error);     return 1; }Terminating a program with a value other than 0 notifies the caller of an error by convention.In a similar fashion you can check for errors on printf, fwrite, and putc and react to them.You can read about the error conditions of functions in their manual pages. On most *nices you can access those comfortably with man <FUNCTION_NAME>.Use expressive variable namesarray is a buffer for a string: string_buffer or shorter strbuf.i and n are the left and right indices of the reversion loop: left and right.Final programA possible final program could look like this:#define _POSIX_C_SOURCE 200809L#include <stdlib.h>#include <stdio.h>int main(void){    char *strbuf = NULL;    size_t strbuf_size;    ssize_t length = getline(&strbuf, &strbuf_size, stdin);    if (length == -1) {        perror(Input error);        return 1;    }    if (length != 0) {      if (strbuf[length-1] == '\n')            strbuf[--length] = '\0';        if (length != 0) {            for (size_t right = (size_t) length - 1, left = 0; left < right; right--, left++) {                char c = strbuf[left];                strbuf[left] = strbuf[right];                strbuf[right] = c;            }            if (puts(strbuf) == EOF) {                perror(Output error);                return 1;            }        }    }    free(strbuf);    return 0;}