I am working on a project to create a C program that acts just like the nl command in Linux, with the exceptions; it only accepts limited options, does not accept dashes to denote standard input, and no need for division of documents into logical pages with headers/footers.
This is a link to an nl manual page: https://ss64.com/bash/nl.html
This is where I am at. The errors I have and cannot for the life of me fix, are as follows:
Line 46: warning: implicit declaration of function 'get_line'; did you mean 'fgetline'? (-Wimplicit-function-declaration)" Line 46: warning: assignment to 'char *' from 'int' makes pointer from integer without a cast (-Wint-conversion)" Line 73: error: conflicting types for 'get_line'" Line 46: note: previous implicit declaration of 'get_line' was here." note: expected 'const char * restrict' but argument is of type 'char'"
The code I have currently:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> //Preprocessor constants: #define MAX_LINE_LENGTH 100 //Prototypes: int process_stream(FILE *fpntr); char *fgetline(FILE *fpntr); int main(int argc, char* argv[]) { char filename; char *first_line; FILE *fpntr; int c; int lineNumber = 1; int beginningNum = 1; //Check for proper number of arguments: if (argc != 2) { fprintf(stderr, "Usage: firstline FILEn"); return EXIT_FAILURE; } //Get source and destination from arguments: filename = argv[1]; //Open file for reading: fpntr = fopen(filename, "r"); //Left out of body to below block: fprintf (stderr, "Error opening file %s: %sn", filename, strerror(errno)); return EXIT_FAILURE; if ((fpntr = fopen(filename, "r")) == NULL) { printf("cannot open file n"); exit(0); } //Get first line from file: if ((first_line = get_line(fpntr)) == NULL) { perror("Error reading line"); exit(EXIT_FAILURE); } // Print out line: printf("First line in file %s: n%s", filename, first_line); //read contents from file while ((c = fgetc(fpntr)) != EOF){ if (beginningNum){ printf("%d ", lineNumber); beginningNum = 0; } if (c == 'n'){ lineNumber++; beginningNum = 1; } printf("%c", c); } fclose(fpntr); return EXIT_SUCCESS; } /*Function to get next line from open file and place it as a legal string into a line buffer that is created locally and is static so it can be returned. Returns pointer to line buffer, or else NIL on error or immediate EOF.*/ char *get_line(FILE *fpntr) { static char line_buff[MAX_LINE_LENGTH]; //Get first line from file and return if (fgets(line_buff, MAX_LINE_LENGTH, fpntr) != NULL) return line_buff; else return NULL; } //EOF
Advertisement
Answer
I’ve taken this to the shop and hammered it into functional shape:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #define MAX_LINE_LENGTH 1024 int main(int argc, char* argv[]) { if (argc != 2) { fprintf(stderr, "Usage: firstline FILEn"); return EXIT_FAILURE; } // argv[n] is type char* char* filename = argv[1]; FILE* fpntr = fopen(filename, "r"); if (!fpntr) { fprintf (stderr, "Error opening file %s: %sn", filename, strerror(errno)); return EXIT_FAILURE; } if ((fpntr = fopen(filename, "r")) == NULL) { printf("cannot open file n"); exit(0); } static char line[MAX_LINE_LENGTH]; if (!fgets(line, MAX_LINE_LENGTH, fpntr)) { perror("Error reading line"); exit(EXIT_FAILURE); } printf("First line in file %s: n%s", filename, line); // Try and declare variables as close as possible to where they're used // as it makes figuring out what they are way easier. Types are very // important in C! int begin = 1; size_t lineNumber = 0; int c; // Note: Would be better to read line by line here instead of individual // characters, fgets has you covered, but this is your call. while ((c = fgetc(fpntr)) != EOF){ if (begin) { // You can get printf() to do the formatting for you if you // let it with %-4 being 4 wide (%4), left-aligned(%-4) // %zu is just the type used by size_t for display printf("%-4zu ", lineNumber); begin = 0; } if (c == 'n') { lineNumber++; begin = 1; } putc(c, stdout); } fclose(fpntr); return EXIT_SUCCESS; }
It Works on My Machineā¢ (Clang) and apart from needing to rewind (fseek
) after your debugging code to dump the first line, it looks good.
On the whole it only took a few little nudges to get things to fit into place properly. You had the right idea, but a lot of the details were just a tiny bit off.
Unfortunately in C a single character can be the difference between “works fine” and agonizing hours of debugging or a whole slew of compiler errors.