Wednesday, 26 June 2019

strtol - convert str to interger


strtol - Convert the number from string into interger

NAME

  • strtol, strtoll, strtoq - convert a string to a long integer

SYNOPSIS

       #include <stdlib.h>

       long int strtol(const char *nptr, char **endptr, int base);
       long long int strtoll(const char *nptr, char **endptr, int base);

       strtoll():
           _ISOC99_SOURCE
               || /* Glibc versions <= 2.19: */ _SVID_SOURCE || _BSD_SOURCE

DESCRIPTION  

  • The strtol() function converts the initial part of the string in nptr to a long integer value according to the given base.
  • If base is 2 then binary, if 8 then octal, if 10 then decimal & 16 for hexa decimal.
  • In bases above 10, the letter 'A' in either uppercase or lowercase represents 10, 'B' represents 11, and so forth, with 'Z' representing 35.
  • Checked in sample program, Hence If u give base as 20 then, f as 15, g as 16, h as 17... j as 19, k will throw an error.
  •  
  • If endptr is not NULL, strtol() stores the address of the first invalid character in *endptr.
  • If there were no digits at all, strtol() stores the original value of nptr in *endptr (and returns 0).

RETURN VALUE

  • The strtol() function returns the result of the conversion, unless the value would underflow or overflow.
  • If an underflow occurs, strtol() returns LONG_MIN.
  • If an overflow occurs, strtol() returns LONG_MAX.
  • In both cases, errno is set to ERANGE.

Note: Program should set errno to 0 before the call, after call check the errno.

Difference between atoi, strtol & sscanf :

atoi()
    Pro: Simple.
    Pro: Convert to an int.
    Pro: In the C standard library.
    Pro: Fast.
    Con: No error handling.
    Con: Handle neither hexadecimal nor octal.

atol()
    Pro: Simple.
    Pro: In the C standard library.
    Pro: Fast.
    Con: Converts to an long, not int which may differ in size.
    Con: No error handling.
    Con: Handle neither hexadecimal nor octal.

strtol()
    Pro: Simple.
    Pro: In the C standard library.
    Pro: Good error handling.
    Pro: Fast.
    Con: Convert to an long, not int which may differ in size.

strtoul()
    Pro: Simple.
    Pro: In the C standard library.
    Pro: Good error handling.
    Pro: Fast.
    ---: Appears to not complain about negative numbers.
    Con: Converts to an unsigned long, not int which may differ in size.

sscanf(..., "%i", ...)
    Pro: In the C standard library.
    Pro: Converts to int.
    ---: Middle-of-the-road complexity.
    Con: Slow.
    Con: OK error handling (overflow is not defined).
    #define BASE_DECIMAL             10
Eg: pid_count = (int)strtol(buf, NULL, BASE_DECIMAL);

Program:

/* strtol - convert str to interger by Velraj.K
 * Check : http://velrajcoding.blogspot.in
 */

#include <stdio.h>>
#include <errno.h>  // errno & ERANGE
#include <stdlib.h>  // strtol & LONG_MAX
#include <limits.h>  // LONG_MAX & LONG_MIN
#include <string.h>  // for strerror

enum {
    FAILED = -1,
    SUCCESS,
};

/*************************************************************************************
 * FUNCTION NAME: convert_str_to_int
 *
 * DESCRIPTION  : convert the string into interget value
 *
 * RETURNS      : None
 * RETURNS      : FAIL on failure,
 *                SUCCESS on successfull update.
 *************************************************************************************/
static int convert_str_to_int(char *str_val, unsigned int *conv_value, char **save_endptr)
{
    char *endptr = NULL;
    long int result = 0;

    if (!str_val || !conv_value) {
        printf("input string is NULL \n");
        return FAILED;
    }

   errno = 0;
    result = strtol(str_val, &endptr, 10);
    *conv_value = (unsigned int)result;
    if (((errno == ERANGE) && ((result == LONG_MAX) || (result == LONG_MIN))) ||
            ((errno != 0) && (result == 0))) {
        printf("Error: conversion %s(%d) \n", strerror(errno), errno);
        return FAILED;
    }

    /* Save the endptr string for any future usage, after conversion. */
    if (save_endptr) {
        *save_endptr = endptr;
        if ((*save_endptr) && (**save_endptr != '\0') &&
                (!isspace(**save_endptr))) {
            printf("End string of input value saved as:%s \n", *save_endptr);
        }
    }

    if (endptr == str_val) {
        printf("No digits were found \n");
        return FAILED;
    }


    return SUCCESS;
}

int main()
{
    int      value = 0;
    char     *endptr = NULL;
    char     str[32] = {0};

    while (1) {
        printf("Enter the number to convert strint to int   :   ");
//        scanf("%[^\t\n]s", str);
        fgets(str, sizeof(str), stdin);
        convert_str_to_int(str, &value, &endptr);
        /*
         * Check the endptr has any invalid trailing strings,
         * after strtol conversion.
         */
        if ((endptr) && (*endptr != '\0') && (!isspace(*endptr))) {
            printf("Error invalid string is present \n");
        } else {
            printf("Input value    :  %s", str);
            printf("Value after convert val to : %d\n",value);
        }
    }

        convert_str_to_int("5m", &value, &endptr);
    if ((endptr) && (*endptr != '\0') && (!isspace(*endptr))) {
        printf("Error invalid string is present for 5m \n");
    } else {
        printf("Value after conver 5m val : %d \n", value);
    }

    return 0;
}



Output: 

 velraj@virtual-machine:~/velrajk/sample$ ./a.out
Enter the number to convert strint to int   :   5
Input value    :  5
Value after convert val to : 5
Enter the number to convert strint to int   :   5m
End string of input value saved as:m

Error invalid string is present
Enter the number to convert strint to int   :   5
Input value    :  5
Value after convert val to : 5
Enter the number to convert strint to int   :   5    m
Input value    :  5    m
Value after convert val to : 5
Enter the number to convert strint to int   :   5 mnews
Input value    :  5 mnews
Value after convert val to : 5
Enter the number to convert strint to int   :   ^C
 

Friday, 7 June 2019

stat, fstat & lstat Usage & diff

Name

  • stat, fstat, lstat - get file status

Synopsis

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

  • int stat(const char *path, struct stat *buf);
  • int fstat(int fd, struct stat *buf);
  • int lstat(const char *path, struct stat *buf)

Description

  • These functions return information about a file.
  • No permissions are required for file, but-in the case of stat() and lstat() - execute (search) permission is required on all of the directories in path that lead to the file.

Def:

  • stat() stats the file pointed to by path and fills in buf.
  • lstat() is identical to stat(), except that if path is a symbolic link, then the link itself is stat-ed, not the file that it refers to.
  • fstat() is identical to stat(), except that the file to be stat-ed is specified by the file descriptor fd.

Difference:

  • lstat() - if pathname is a symbolic link, then it returns information about the link itself, not the file (target) that it refers to.
  • stat()  - if pathname is a symbolic link, then it returns information about the target file that it refers to.

Symbolic file behaviour while opening:

  • Even if we touch the symbalic file, the modified time for target fill only will get modified, symbolic file modified time will be remain same.
  • If we edit the file using symbolic link, then modified time for target will be get changed but not symbolic file.

  • All of these system calls return a stat structure, which contains the following fields:
    struct stat {
        dev_t     st_dev;     /* ID of device containing file */
        ino_t     st_ino;     /* inode number */
        mode_t    st_mode;    /* protection */
        nlink_t   st_nlink;   /* number of hard links */
        uid_t     st_uid;     /* user ID of owner */
        gid_t     st_gid;     /* group ID of owner */
        dev_t     st_rdev;    /* device ID (if special file) */
        off_t     st_size;    /* total size, in bytes */
        blksize_t st_blksize; /* blocksize for file system I/O */
        blkcnt_t  st_blocks;  /* number of 512B blocks allocated */
        time_t    st_atime;   /* time of last access */
        time_t    st_mtime;   /* time of last modification */
        time_t    st_ctime;   /* time of last status change */
    };

st_mode field:

The following POSIX macros are defined to check the file type using the st_mode field:
    S_ISREG(m)     is it a regular file?
    S_ISDIR(m)     directory?
    S_ISCHR(m)     character device?
    S_ISBLK(m)     block device?
    S_ISFIFO(m)    FIFO (named pipe)?
    S_ISLNK(m)     symbolic link? (Not in POSIX.1-1996.)
    S_ISSOCK(m)    socket? (Not in POSIX.1-1996

Return Value

On success, zero is returned. On error, -1 is returned, and errno is set appropriately.

Program:



/* Difference between stat & lstat  by Velraj.K
 * Check : http://velrajcoding.blogspot.in
 */

#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>         // For memset

/* Note:
 *     Even if we touch the symbalic file, the modified time for target fill only will get modified,
 *          symbolic file modified time will be remain same.
 *     If we edit the file using symbolic link, then modified time for target will be get changed but not symbolic file.
 *     Difference:
 *       lstat() - if pathname is a symbolic link, then it returns information about the link itself,
 *                     not the file (target) that it refers to.
 *       stat()  - if pathname is a symbolic link, then it returns information about the target file that it refers to.
 */

void hline(char ch)
{
    int i;

    for (i = 0; i < 80; printf("%c", ch), i++);
    printf("\n");

    return;
}

void stat_display(struct stat *sb, char *method)
{
    if (!sb || !method) {
        printf("Error stat details is NULL \n");
        return;
    }

    hline('*');
    printf("\n\t Retrieve the file stat details using %s API\n", method);
    printf("\n\t ------------------------------------------------\n");
    printf("File type:                ");

    switch (sb->st_mode & S_IFMT) {
        case S_IFBLK:  printf("block device\n");            break;
        case S_IFCHR:  printf("character device\n");        break;
        case S_IFDIR:  printf("directory\n");               break;
        case S_IFIFO:  printf("FIFO/pipe\n");               break;
        case S_IFLNK:  printf("symlink\n");                 break;
        case S_IFREG:  printf("regular file\n");            break;
        case S_IFSOCK: printf("socket\n");                  break;
        default:       printf("unknown?\n");                break;
    }

    printf("I-node number:            %ld\n", (long) sb->st_ino);

    printf("Mode:                     %lo (octal)\n",
            (unsigned long) sb->st_mode);

    printf("Link count:               %ld\n", (long) sb->st_nlink);
    printf("Ownership:                UID=%ld   GID=%ld\n",
            (long) sb->st_uid, (long) sb->st_gid);

    printf("Preferred I/O block size: %ld bytes\n",
            (long) sb->st_blksize);
    printf("File size:                %lld bytes\n",
            (long long) sb->st_size);
    printf("Blocks allocated:         %lld\n",
            (long long) sb->st_blocks);

    printf("Last status change:       %s", ctime(&sb->st_ctime));
    printf("Last file access:         %s", ctime(&sb->st_atime));
    printf("Last file modification:   %s", ctime(&sb->st_mtime));
    hline('*');


}

int main(int argc, char *argv[])
{
    struct stat sb = {0};

    if (argc != 2) {
        fprintf(stderr, "Usage: %s pathname\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    if (stat(argv[1], &sb) == -1) {
        perror("stat");
        exit(EXIT_FAILURE);
    }

    stat_display(&sb, "stat");
    memset(&sb, 0, sizeof(struct stat));
    if (lstat(argv[1], &sb) == -1) {
        perror("stat");
        exit(EXIT_FAILURE);
    }
    stat_display(&sb, "lstat");



   exit(EXIT_SUCCESS);
}

 

Output:

 labuser@labuser-virtual-machine:~/velrajk/sample$ touch ../temp/new_s
labuser@labuser-virtual-machine:~/velrajk/sample$ ./a.out ../temp/new_s
********************************************************************************

         Retrieve the file stat details using stat API

         ------------------------------------------------
File type:                regular file
I-node number:            1887181
Mode:                     100664 (octal)
Link count:               1
Ownership:                UID=1000   GID=1000
Preferred I/O block size: 4096 bytes
File size:                11 bytes
Blocks allocated:         8
Last status change:       Fri Jun  7 12:05:50 2019
Last file access:         Fri Jun  7 12:05:50 2019
Last file modification:   Fri Jun  7 12:05:50 2019
********************************************************************************
********************************************************************************

         Retrieve the file stat details using lstat API

         ------------------------------------------------
File type:                symlink
I-node number:            1963069
Mode:                     120777 (octal)
Link count:               1
Ownership:                UID=1000   GID=1000
Preferred I/O block size: 4096 bytes
File size:                3 bytes
Blocks allocated:         0
Last status change:       Thu Jun  6 19:45:36 2019
Last file access:         Thu Jun  6 19:45:38 2019
Last file modification:   Thu Jun  6 19:45:36 2019
********************************************************************************
labuser@labuser-virtual-machine:~/velrajk/sample$
labuser@labuser-virtual-machine:~/velrajk/sample$
labuser@labuser-virtual-machine:~/velrajk/sample$
labuser@labuser-virtual-machine:~/velrajk/sample$ date
Fri Jun  7 12:06:05 IST 2019
labuser@labuser-virtual-machine:~/velrajk/sample$

Monday, 3 June 2019

Skip the String or Char or int using format specifier %*

Format specifiers in C

  •  It is a way to tell the compiler what type of data is in a variable during taking input using scanf() or printing using printf().
    •  EG: %c, %d, %f, etc.
    • printf(char *format, arg1, arg2, …)

printing format:


  • A minus(-) sign tells left alignment.
  • A number after % specifies the minimum field width to be printed if the characters are less than the size of width the remaining space is filled with space and if it is greater than it printed as it is without truncation.
  • A period( . ) symbol seperate field width with the precision.
  •  %%    Prints % character

Program:

/* Skip the String or Char or int using format specifier %*  by Velraj.K
 * Check : http://velrajcoding.blogspot.in
 */

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

int main () {
    int day = 0, year = 0, ret;
    char weekday[20] = {0}, month[20] = {0}, dtm[100]= {0}, time[128] = {0}, meridiem[8] = {0};

    /*
     * The abbreviations am and pm derive from Latin:
     *   AM = Ante meridiem: Before noon
     *   PM = Post meridiem: After noon
     */
    strcpy( dtm, "Saturday March 25 1989 v1Hour before 10 AM" );
    //sscanf( dtm, "%s %*s %d  %d", weekday, month, &day, &year );
    /*
     * %*s  -> Skip the string
     * %*c  -> Skip the character
     * %*d  -> Skip the interger
     */
    ret = sscanf(dtm, "%s %*s %d  %d %*c %s %*s %*d %s", weekday, &day, &year, time, meridiem);



    printf("ret:%d Value: Day:<%d> Year:<%d> Week:<%s> Time:%s Meridiem:%s\n", ret, day, year, weekday, time, meridiem);
    printf("Velraj %n \n", &ret);

    return(0);
} 

Output: 

  /sample$ ./a.out ret:5 Value: Day:25 Year:1989 Week:saturday Time:1Hour Meridiem:AM