Coding Exercise – Simple [nl] Implementation on Windows Platform using C++ (GCC)


On Linux BASH shell, the ‘nl’ utility is used to print out text file (or string) with line numbers. If you type in nl –help you will have a page of help information on using this program. The first two lines are:

1
2
3
root@uploadbeta:~# nl --help | head -2
Usage: nl [OPTION]... [FILE]...
Write each FILE to standard output, with line numbers added.
root@uploadbeta:~# nl --help | head -2
Usage: nl [OPTION]... [FILE]...
Write each FILE to standard output, with line numbers added.

If you do not give any command line parameter, the nl will ask input from keyboard until you hit Ctrl+C or Ctrl+D. At each line, it will print line numbers. It is noted that on Windows, Ctrl+Z is used to terminate the keyboard input (EOF) but on Linux, the shortcut is used to put the current job in the background. On Linux, Ctrl+D yields the EOF. Ctrl+C on both OS are used to break the input.

1
2
3
4
5
6
7
root@uploadbeta:~# nl
HelloACM.com
     1  HelloACM.com
Rocks!
     2  Rocks!
hello
     3  hello
root@uploadbeta:~# nl
HelloACM.com
     1  HelloACM.com
Rocks!
     2  Rocks!
hello
     3  hello

You can also give the text file names one by one on command line. And the line numbers will be shown continuously.

1
2
3
4
5
6
7
8
root@uploadbeta:~# echo -e "test1\ntest2\ntest3" > test
root@uploadbeta:~# nl test test
     1  test1
     2  test2
     3  test3
     4  test1
     5  test2
     6  test3
root@uploadbeta:~# echo -e "test1\ntest2\ntest3" > test
root@uploadbeta:~# nl test test
     1  test1
     2  test2
     3  test3
     4  test1
     5  test2
     6  test3

If some file is not found, it will show the not-found message.

1
2
3
4
5
6
7
8
root@uploadbeta:~# nl test test aa
     1  test1
     2  test2
     3  test3
     4  test1
     5  test2
     6  test3
nl: aa: No such file or directory
root@uploadbeta:~# nl test test aa
     1  test1
     2  test2
     3  test3
     4  test1
     5  test2
     6  test3
nl: aa: No such file or directory

C++ Implementation

Now, we are going to use C++ (GCC Compiler) to make a simple implementation of the nl shown above. It is noted that the full nl supports many command line options, but we are just going to implement the basics.

The following deals with the input from the keyboard if no parameters are given.

1
2
3
4
5
6
7
8
9
10
11
    if (argc == 1) {
        int num = 1;
        while (true) {
            string s;
            getline(std::cin, s);
            if (cin.eof()) break; // check for Ctrl + D
            cout << TAB << num << TAB << s << endl;
            num ++;
        }
        return 0;
    }
    if (argc == 1) {
        int num = 1;
        while (true) {
            string s;
            getline(std::cin, s);
            if (cin.eof()) break; // check for Ctrl + D
            cout << TAB << num << TAB << s << endl;
            num ++;
        }
        return 0;
    }

To simulate the usage message is easy.

1
2
3
4
5
6
    if ((argc == 2) && (strcmp(argv[1], "--help") == 0)) {
        cout << "http://HelloACM.com" << endl;
        cout << "Usage: nl [FILE]..." << endl;
        cout << "Write each FILE to standard output, with line numbers added." ;
        return 0;
    }
    if ((argc == 2) && (strcmp(argv[1], "--help") == 0)) {
        cout << "http://HelloACM.com" << endl;
        cout << "Usage: nl [FILE]..." << endl;
        cout << "Write each FILE to standard output, with line numbers added." ;
        return 0;
    }

Now, we can treat each parameter in the command line as a input source file name and check if it can be opened. Read each file line by line and output the line number.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    int num = 1;
    for (int i = 1; i < argc; i ++) {
        ifstream f(argv[i]); // open file
        if (f.good()) { // check if is a file and can be opened
            string s;
            while (getline(f, s)) {  // read a line
                cout << TAB << num << TAB << s << endl;
                num ++; 
            }
            f.close();
        } else {
            f.close();
            cout << "nl: " << argv[i] << " is not a file." << endl;
        }
    }
    int num = 1;
    for (int i = 1; i < argc; i ++) {
        ifstream f(argv[i]); // open file
        if (f.good()) { // check if is a file and can be opened
            string s;
            while (getline(f, s)) {  // read a line
                cout << TAB << num << TAB << s << endl;
                num ++; 
            }
            f.close();
        } else {
            f.close();
            cout << "nl: " << argv[i] << " is not a file." << endl;
        }
    }
nl-on-windows Coding Exercise - Simple [nl] Implementation on Windows Platform using C++ (GCC) BASH Shell beginner c / c++ code code library console I/O File implementation programming languages windows windows command shell

nl utility on windows gcc compiler C++ programming

The full C++ source code can be found below.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <iostream>
#include <fstream>
#include <string.h>
 
using namespace std;
const char TAB = 9;
 
int main(int argc, char *argv[]) {
    if (argc == 1) {
        int num = 1;
        while (true) {
            string s;
            getline(std::cin, s);
            if (cin.eof()) break; // check for Ctrl + D
            cout << TAB << num << TAB << s << endl;
            num ++;
        }
        return 0;
    }
    if ((argc == 2) && (strcmp(argv[1], "--help") == 0)) {
        cout << "http://HelloACM.com" << endl;
        cout << "Usage: nl [FILE]..." << endl;
        cout << "Write each FILE to standard output, with line numbers added." ;
        return 0;
    }
    int num = 1;
    for (int i = 1; i << argc; i ++) {
        ifstream f(argv[i]);
        if (f.good()) {
            string s;
            while (getline(f, s)) {
                cout << TAB << num << TAB << s << endl;
                num ++;
            }
            f.close();
        } else {
            f.close();
            cout << "nl: " << argv[i] << " is not a file." << endl;
        }
    }
    return 0;
}
#include <iostream>
#include <fstream>
#include <string.h>

using namespace std;
const char TAB = 9;

int main(int argc, char *argv[]) {
    if (argc == 1) {
        int num = 1;
        while (true) {
            string s;
            getline(std::cin, s);
            if (cin.eof()) break; // check for Ctrl + D
            cout << TAB << num << TAB << s << endl;
            num ++;
        }
        return 0;
    }
    if ((argc == 2) && (strcmp(argv[1], "--help") == 0)) {
        cout << "http://HelloACM.com" << endl;
        cout << "Usage: nl [FILE]..." << endl;
        cout << "Write each FILE to standard output, with line numbers added." ;
        return 0;
    }
    int num = 1;
    for (int i = 1; i << argc; i ++) {
        ifstream f(argv[i]);
        if (f.good()) {
            string s;
            while (getline(f, s)) {
                cout << TAB << num << TAB << s << endl;
                num ++;
            }
            f.close();
        } else {
            f.close();
            cout << "nl: " << argv[i] << " is not a file." << endl;
        }
    }
    return 0;
}

It is noted that we can use pipe line (supported both on Linux and Windows shell) to give input to nl program. (the following BASH script is to print a square number using bc)

1
2
3
4
5
6
7
8
9
10
root@uploadbeta:~# cat sqrt | nl
     1  #!/bin/bash
       
     2  if [ $# -ne 1 ]; then
     3    echo 'Usage: sqrt number'
     4    exit 1
     5  else
     6     echo -e "sqrt($1)\nquit\n" | bc -q -i | head -2 | tail -1
     7  fi
root@uploadbeta:~# 
root@uploadbeta:~# cat sqrt | nl
     1  #!/bin/bash
       
     2  if [ $# -ne 1 ]; then
     3    echo 'Usage: sqrt number'
     4    exit 1
     5  else
     6     echo -e "sqrt($1)\nquit\n" | bc -q -i | head -2 | tail -1
     7  fi
root@uploadbeta:~# 

The pre-compiled nl (using GCC compiler on windows) can be downloaded [here] cnt Coding Exercise - Simple [nl] Implementation on Windows Platform using C++ (GCC) BASH Shell beginner c / c++ code code library console I/O File implementation programming languages windows windows command shell .

C Implementation

Here is another nice implementation but in pure C programming language. The main difference is the code to deal with reading from text files (I/O). The author is Kevin Guanche Darias.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
#include <inttypes.h>
#define TAB '\t'
#define MAX_LINE_SIZE sizeof(char) * 65536
#define EOL "\r\n"
#define NLPRINT LineNumber++;printf("%c%d%c%s",TAB,LineNumber,TAB,Line)
int main(int argc, char **argv){
    uint32_t LineNumber = 0;
    char *Line = (char *)malloc(MAX_LINE_SIZE);
    memset(Line,0,MAX_LINE_SIZE);
    puts("Kevin Guanche Darias :: nl tool");
    // File not specified use  stdin
    if(argc == 1){
        while(1){
            fgets(Line,MAX_LINE_SIZE,stdin);
            if(feof(stdin)) break;
            NLPRINT;
        }
        return EXIT_SUCCESS;
    }else if(argc == 2 && (strcmp(argv[1],"--help") == 0)){ // Show help
        puts("Kevin Guanche Darias nl for Windows");
        printf("Usage: %s [File]..."EOL,argv[0]);
        puts("Writes each file to standard output, with line numbers added");
        return EXIT_SUCCESS;
    }
    FILE *FilePointer;
    int i;
    for(i = 1; i < argc;(i++)){
        FilePointer = fopen(argv[i],"r");
        if(FilePointer != NULL){
            while(!feof(FilePointer)){
                fgets(Line,MAX_LINE_SIZE,FilePointer);
                NLPRINT;
            }
        }else{ // File Error
            printf("%s: %s is not a file "EOL,argv[0],argv[i]);
        }
        fclose(FilePointer);
    }
    return EXIT_SUCCESS;
}
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
#include <inttypes.h>
#define TAB '\t'
#define MAX_LINE_SIZE sizeof(char) * 65536
#define EOL "\r\n"
#define NLPRINT LineNumber++;printf("%c%d%c%s",TAB,LineNumber,TAB,Line)
int main(int argc, char **argv){
    uint32_t LineNumber = 0;
    char *Line = (char *)malloc(MAX_LINE_SIZE);
    memset(Line,0,MAX_LINE_SIZE);
    puts("Kevin Guanche Darias :: nl tool");
    // File not specified use  stdin
    if(argc == 1){
        while(1){
            fgets(Line,MAX_LINE_SIZE,stdin);
            if(feof(stdin)) break;
            NLPRINT;
        }
        return EXIT_SUCCESS;
    }else if(argc == 2 && (strcmp(argv[1],"--help") == 0)){ // Show help
        puts("Kevin Guanche Darias nl for Windows");
        printf("Usage: %s [File]..."EOL,argv[0]);
        puts("Writes each file to standard output, with line numbers added");
        return EXIT_SUCCESS;
    }
    FILE *FilePointer;
    int i;
    for(i = 1; i < argc;(i++)){
        FilePointer = fopen(argv[i],"r");
        if(FilePointer != NULL){
            while(!feof(FilePointer)){
                fgets(Line,MAX_LINE_SIZE,FilePointer);
                NLPRINT;
            }
        }else{ // File Error
            printf("%s: %s is not a file "EOL,argv[0],argv[i]);
        }
        fclose(FilePointer);
    }
    return EXIT_SUCCESS;
}

The malloc() part can obviously be optimized. The pre-compiled exe can be downloaded from the Author’s website.

If you prefer a local download, that is also possible: click to download from local server cnt Coding Exercise - Simple [nl] Implementation on Windows Platform using C++ (GCC) BASH Shell beginner c / c++ code code library console I/O File implementation programming languages windows windows command shell

nl-windows-pure-c-implementation Coding Exercise - Simple [nl] Implementation on Windows Platform using C++ (GCC) BASH Shell beginner c / c++ code code library console I/O File implementation programming languages windows windows command shell

Simple NL implementation in Pure C

–EOF (The Ultimate Computing & Technology Blog) —

GD Star Rating
loading...
1325 words
Last Post: Less Known HTML Tags
Next Post: Coding Exercise - Source Codes and Binaries

The Permanent URL is: Coding Exercise – Simple [nl] Implementation on Windows Platform using C++ (GCC)

Leave a Reply