C Programming: Loop until EOF

pzozulka
pzozulka used Ask the Experts™
on
In the while loop below, I need to break if EOF. I'm new to C, and am not sure how to accomplish this. I tried NULL below as well as EOF. When I do EOF, I get an error message saying: "warning: comparison between pointer and integer".

In other words, the program keeps asking for user input from STDIN, but needs to stop looping when user hits ^d.

#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <fcntl.h>
#include <string.h>
#include <stdio.h>
#include <pwd.h>

static void writeLine(char *b, int filedes);
static void readInput(char *u, char *b);

int main( int argc, char *argv[] ) {
   struct passwd *mypasswd;
   int fd;
   char *usr = malloc(sizeof(char) * 1024);
   char *buf = malloc(sizeof(char) * 1024);
   char *mytty;

   // get username
   if( (mypasswd = getpwuid(geteuid())) != NULL ) {
      char *user = mypasswd->pw_name;

      if(( mytty = ttyname(STDIN_FILENO)) == NULL)
         perror("ttyname() error");

      strcpy(usr, user);
      strcat(usr, "@");
      strcat(usr, mytty);
      strcat(usr, ": ");
   }

   //open file
   fd = open(argv[1], O_RDWR);

   //get user input
   readInput(usr, buf);

   //write
   while(buf != NULL) {
      writeLine(buf, fd);
      readInput(usr, buf);
   }

   close(fd);
}

static void writeLine(char *b, int filedes) {
   size_t nbytes;
   ssize_t bytes_written;

   nbytes = strlen(b);
   if(( bytes_written = write(filedes, b, nbytes)) == -1)
        perror("write() error");
}

static void readInput(char *u, char *b) {
   int max_input = 200;
   char buffer[max_input];

   strcpy(b, "");
   printf("%s", u);
   fgets(buffer, max_input, stdin);

   // append user input to *b string
   strcat(b, u);
   strcat(b, buffer);
   //strcat(b, "\n");
}

Open in new window

Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
hi,

try comparing with '\0' :) coz NULL of course is a pointer
Top Expert 2012
Commented:
Um, the loop

   while(buf != NULL) {
      writeLine(buf, fd);
      readInput(usr, buf);
   }

Open in new window


actually is infinite - since 'buf' is allocate before via 'malloc()', it never can become NULL here.

Author

Commented:
I tried changing it to this, but that doesn't help either:
while(buf[(strlen(buf))-1] != '\0')

Open in new window

Ensure you’re charging the right price for your IT

Do you wonder if your IT business is truly profitable or if you should raise your prices? Learn how to calculate your overhead burden using our free interactive tool and use it to determine the right price for your IT services. Start calculating Now!

ozo
Most Valuable Expert 2014
Top Expert 2015
Commented:
while( strcmp(usr,buf) ) {
      writeLine(buf, fd);
      readInput(usr, buf);
   }

static void readInput(char *u, char *b) {
   int max_input = 200;
   char buffer[max_input];
   buffer[0]='\0';
   strcpy(b, "");
   printf("%s", u);
   fgets(buffer, max_input, stdin);

   // append user input to *b string
   strcat(b, u);
   strcat(b, buffer);
   //strcat(b, "\n");
}
Commented:
I changed it to this, and it's kind of working now. I say kind of because if I type "^d" it works, but if I type "test^d", it doesn't.

#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <fcntl.h>
#include <string.h>
#include <stdio.h>
#include <pwd.h>

static void writeLine(char *b, int filedes);
static void readInput(char *u, char *b);

int main( int argc, char *argv[] ) {
   struct passwd *mypasswd;
   int fd;
   char *usr = malloc(sizeof(char) * 1024);
   char *buf = malloc(sizeof(char) * 1024);
   char *mytty;

   // get username
   if( (mypasswd = getpwuid(geteuid())) != NULL ) {
      char *user = mypasswd->pw_name;

      if(( mytty = ttyname(STDIN_FILENO)) == NULL)
         perror("ttyname() error");

      strcpy(usr, user);
      strcat(usr, "@");
      strcat(usr, mytty);
      strcat(usr, ": ");
   }

   //open file
   fd = open(argv[1], O_RDWR);

   //get user input
   readInput(usr, buf);
   //printf("%d\n",strlen(buf));
   //write
   while(!feof(stdin)) {
      writeLine(buf, fd);
      readInput(usr, buf);
      //printf("%c\n",buf[(strlen(buf))-2]);
   }

   close(fd);
}

static void writeLine(char *b, int filedes) {
   size_t nbytes;
   ssize_t bytes_written;

   strcat(b, "\n");
   nbytes = strlen(b);
   if(( bytes_written = write(filedes, b, nbytes)) == -1)
        perror("write() error");
}

static void readInput(char *u, char *b) {
   int max_input = 200;
   char buffer[max_input];

   strcpy(b, "");
   printf("%s", u);
   fgets(buffer, max_input, stdin);

   // append user input to *b string
   strcat(b, u);
   strcat(b, buffer);
   //strcat(b, "\n");
}

Open in new window

Author

Commented:
ozo: I tried your suggestion as well, but it has pretty much the same effect as the (!feof(stdin))
Top Expert 2016

Commented:
int ulen = strlen(usr);
do
{
       buf[0] = '\0';
       char * p = fgets(buf, max_input, stdin);  // buf includes '\n' at end
       int blen;
       // loop breaks if an error (or eof) occurs or if the user hits <Enter> without input.
       if (p == NULL || (blen = strlen(buf)) == 0 || strcmp(buf, "\n") == 0)
            break;
       if (writeLine(usr, ulen, buf, blen, fd) < 0)
           break;
 } while (1); 

int writeLine(const char * u, int ul, const char * b, int bl, int fd)
{
       if (write(fd, u, ul) < 0 ||
           write(fd, b, bl) < 0 )    
       {
             perror("write() error");
             return -1;
       }
       return 0;
 } 

Open in new window

note, your input and output functions make not so much sense. they add complexity which is totally unneeded, for example string copy and string concatenation where you always have the risk of a buffer overflow. All that make the code more error-prone as it was without the functions. you only should use separate functions if it makes the code simpler (for example by avoiding redundancy) and/or more readable.

i also would use fopen, fwrite, fclose instead of open, write, close. it is not much difference but as you were using fgets for user input, it would make sense to use all functions of the same family.

Sara

Author

Commented:
while(!feof(stdin))

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial