• C

C Programming: Loop until EOF

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

LVL 8
pzozulkaAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

APoPhySptCommented:
hi,

try comparing with '\0' :) coz NULL of course is a pointer
0
jkrCommented:
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.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

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

Open in new window

0
Big Business Goals? Which KPIs Will Help You

The most successful MSPs rely on metrics – known as key performance indicators (KPIs) – for making informed decisions that help their businesses thrive, rather than just survive. This eBook provides an overview of the most important KPIs used by top MSPs.

ozoCommented:
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");
}
0
pzozulkaAuthor 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

0
pzozulkaAuthor Commented:
ozo: I tried your suggestion as well, but it has pretty much the same effect as the (!feof(stdin))
0
sarabandeCommented:
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
0
pzozulkaAuthor Commented:
while(!feof(stdin))
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C

From novice to tech pro — start learning today.