Question

Been looking in to C and I'm working on a simple program to read a text file, apply a caesar cipher, and write to a new output file. My problem is that the while-loop supposed to build my output string terminates immediately, claiming that the next character is EOF, even when it obviously isn't. Code below:

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

#define MORD ".mord"

void die(const char *message)
{
  if(errno) {
    perror(message);
  } else {
    printf("ERROR: %s\n", message);
  }

  exit(1);
}

int main(int argc, char *argv[])
{
  if(argc != 3) die("USAGE: dodsmord <filename> <offset>");
  char *infilename = argv[1];
  char *outfilename = strcat(infilename, MORD);
  int offset = atoi(argv[2]);
  char *outstr[1000];
  FILE *infile = fopen(infilename, "r+");
  FILE *outfile = fopen(outfilename, "w+");
  if(infile == NULL) {
    die("Could not open input file");
  }
  if(outfile == NULL) {
    die("Could not open output file");
  }
  int c;
  int i = 0;
  printf("reading input file...\n");
  while(1) {
    c = fgetc(infile);
    printf("c == EOF: %d\n", c == EOF ? 1 : 0);
    printf("EOF: %d\n", EOF);
    printf("c is now: %c\n", c);
    if(c == EOF) break;
    outstr[i] = c + offset;
    i++;
  }
  printf("done reading! writing outstr to outfile...\n");
  fwrite(outstr, sizeof(char), i, outfile);

  printf("closing streams...\n");
  fclose(infile);
  fclose(outfile);

  return 0;
}

The output if I run the code on test.txt (which contains exactly "abcdefg" without quotes), I get the output

reading input file...
c == EOF: 1
EOF: -1
c is now: �
done reading! writing outstr to outfile...
closing streams...
Was it helpful?

Solution 2

Here is the problem:

  char *infilename = argv[1];
  char *outfilename = strcat(infilename, MORD);

strcat() will change infilename, and append that MORD to the end of it, therefore you are using argv[1].mord as your input file name. I bet it is a empty file.

Solution:

Change

char *outfilename = strcat(infilename, MORD);

to

char *outfilename = malloc(strlen(infilename) + strlen(MORD) + 1);
if (outfilename == NULL) { /* malloc failed */ }
strcpy(outfilename, infilename);
strcat(outfilename, MORD);

OTHER TIPS

char *infilename = argv[1];
char *outfilename = strcat(infilename, MORD);

This doesn't do what you think it does.

It sets up infilename so that it points to the same memory as argv[1], then the strcat changes that memory to append the .mord.

Then it returns it so that outfilename also points to the memory.

Hence you're changing the input file name to be the .mord one and, when you try to open it, well, I don't know what will happen exactly, it depends on whether it exists yet.

What you want is something like:

char *infilename = argv[1];
char *outfilename = malloc (strlen (infilename) + strlen (MORD) + 1);
if (outfilename == NULL) {
    handleOutOfMemoryHere();
}
strcpy (outfilename, infilename);
strcat (outfilename, MORD);
:
// weave you cypher magic here
:
free (outfilename);

The second line in that code will give you a separate memory area for the output file name and the strcpy/strcat combo will construct it correctly.

The problem is caused by:

char *infilename = argv[1];
char *outfilename = strcat(infilename, MORD);

Reason: strcat does a in-place copy and returns the address of src. Try this and you would see:

char *infilename = argv[1];
char *outfilename = strcat(infilename, MORD);
printf("TEST: %p %p\n", infilename, outfilename);

To fix this, use something like this:

char *infilename = argv[1];
char *outfilename = malloc(strlen(infilename) + strlen(MORD) + 1);
strcpy(outfilenname, infilename);
strcat(outfilename, MORD);

problem is with below line

char *outfilename = strcat(infilename, MORD);

infilename is getting modified to test.txt.mord

Move

FILE *infile = fopen(infilename, "r+");

above the following line

    char *outfilename = strcat(infilename, MORD);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top