I have problem reading file form command line.
I am trying to do " abcd: ./rev < numbers", but it gives me an error:

./rev < numbers
Usage : 
 ./rev FILENAME

Here is the code:

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

void reverse(FILE * file) 
{
  int fscanf_return_value;
  char x;
  /* read a char */
  fscanf_return_value = fscanf(file,"%c",&x) ;
  if(fscanf_return_value == EOF) 
    { //fscanf returns EOF as the END OF FILE
      return;
    }
  reverse(file); //Get the next char
  //do something with the char e.g. print
  putchar(x);
  return;
}

int main(int argc, char *argv[]) 
{
 int i;
 FILE *fd;
 if (argc!=2) 
   {
     printf("Usage : \n %s FILENAME\n",argv[0]);
     exit(0);
   }
 if(!(fd=fopen(argv[1],"r"))) 
   {
     printf("Opening file error\n");
     exit(1);
   }
 reverse(fd);
 printf("\n\n\t---\tenoD - Done\t---\n");
 exit(0);
}

Also I can't read a file one per line, and prints them back out in reverse order. I need output like:
.
.
.
12
11
10
9
8
7
6
5
4
3
2
1
0
But I am getting:
21
11
01
9
8
7
6
5
4
3
2
1
0

Dani AI

Generated

Short clarification and cause: using shell redirection (./rev < numbers) feeds the file into the program's standard input — it does not place the filename in argv. The posted program expects a filename on the command line, so it prints the Usage message when only redirected input is given. Also, the recursive char-by-char routine prints characters after the recursive call, which reverses every character in the whole stream; that is why multi-character lines like 12 become 21. spotted the stdin/argument mismatch; ’s output is the expected side effect of a character-wise reversal rather than a line-wise reversal.

A straightforward, commonly used approach for producing the desired result (lines printed in reverse order, with each line kept intact) is: read the input one line at a time, store each line into a dynamic array (or linked list), then print the stored lines in reverse order. The example below accepts either a filename or redirected stdin and demonstrates that pattern.

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

int main(int argc, char *argv[]) {
    FILE *f = stdin;
    if (argc == 2) {
        f = fopen(argv[1], "r");
        if (!f) { perror(argv[1]); return 1; }
    }

    char *line = NULL;
    size_t len = 0;
    ssize_t nread;
    char **lines = NULL;
    size_t count = 0, cap = 0;

    while ((nread = getline(&line, &len, f)) != -1) {
        if (count == cap) {
            cap = cap ? cap * 2 : 16;
            char **tmp = realloc(lines, cap * sizeof *lines);
            if (!tmp) { perror("realloc"); exit(1); }
            lines = tmp;
        }
        lines[count++] = strdup(line);
    }
    free(line);
    if (f != stdin) fclose(f);

    for (size_t i = count; i-- > 0; ) {
        fputs(lines[i], stdout);
        free(lines[i]);
    }
    free(lines);
    return 0;
}

Notes and caveats: getline/strdup are POSIX conveniences (on some Windows toolchains an alternative is needed). Storing all lines uses memory proportional to the file; for very large files prefer a backward-scan using fseek/ftell or an external temporary file. Verify return values and free allocated memory to avoid leaks. This approach preserves each line’s characters while reversing the line order, which matches the output shown as the intended result.

Recommended Answers

All 4 Replies

when you type ./rev < numbers you are redirecting the contents of numbers into rev program. That is not what rev is expecting. Leave out the < symbol, just ./rev numbers (assuming numbers if the name of a text file)

Also I can't read a file one per line, and prints them back out in reverse order. I need output like:

A couple ways to solve that problem:

  1. Read the file backwards. This is a little more complicated than reading the file forwards as normal because you have to back up the file pointer before every read.

  2. Keep all the numbers in memory (linked list is good for that) then print them out backwards.

Thanks. So what should I do to redirecting the contents of numbers into rev program?

You don't need command-line argumnents. Delete lines 24-33 because you don't have a file to open. On line 24 substitute stdin for fp. stdin is always an open file that represents keyboard input and can also be used for redirected files.

reverse(stdin);

Thanks' Ancient Dragon. I appreciate.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.