Others have already told you some specific problems with your code but one thing they seem to have missed is that c should be an int, not a char. Otherwise the comparison to EOF wil not work as expected.
In addition, the segfault you're getting is because of this sequence:
line[n++]=tmp; printf("\n%s\n",line[n]);
You have already incremented n to the next array element then you try to print it. That second line should be:
printf("\n%s\n",line[n-1]);
If you just want some code that works (with a free "do what you darn well want to" licence), here's a useful snippet from my code library.
I'm not sure why you think fgets is to be avoided, it's actually very handy and very safe. I'm assuming you meant gets which is less handy and totally unsafe. Your code is also prone to buffer overruns as well, since it will happily write beyond the end of your allocated area if it gets a lot of characters that are neither space nor end of file.
By all means, write your own code if you're educating yourself but part of that should be examining production-tested bullet-proof code to see how it can be done. And, if you're not educating yourself, you're doing yourself a disservice by not using freely available code.
The snippet follows:
#include <stdio.h> #include <string.h> #define OK 0 #define NO_INPUT 1 #define TOO_LONG 2 static int getLine (char *prmpt, char *buff, size_t sz) { int ch, extra; // Get line with buffer overrun protection. if (prmpt != NULL) { printf ("%s", prmpt); fflush (stdout); } if (fgets (buff, sz, stdin) == NULL) return NO_INPUT; // If it was too long, there'll be no newline. In that case, we flush // to end of line so that excess doesn't affect the next call. if (buff[strlen(buff)-1] != '\n') { extra = 0; while (((ch = getchar()) != '\n') && (ch != EOF)) extra = 1; return (extra == 1) ? TOO_LONG : OK; } // Otherwise remove newline and give string back to caller. buff[strlen(buff)-1] = '\0'; return OK; }
// Test program for getLine(). int main (void) { int rc; char buff[10]; rc = getLine ("Enter string> ", buff, sizeof(buff)); if (rc == NO_INPUT) { printf ("No input\n"); return 1; } if (rc == TOO_LONG) { printf ("Input too long\n"); return 1; } printf ("OK [%s]\n", buff); return 0; }
It's a useful line input function that has the same buffer overflow protection as fgets and can also detect lines entered by the user that are too long. It also throws away the rest of the too-long line so that it doesn't affect the next input operation.
Sample runs with 'hello', CTRLD, and a string that's too big:
pax> ./qq Enter string> hello OK [hello] pax> ./qq Enter string> No input pax> ./qq Enter string> dfgdfgjdjgdfhggh Input too long pax> _
For what it's worth (and don't hand this in as your own work since you'll almost certainly be caught out for plagiarism - any half-decent educator will search for your code on the net as the first thing they do), this is how I'd approach it.
#include <stdio.h> #include <stdlib.h> #define WORDLENGTH 15 #define MAXWORDS 1000 int main (void) { char *line[MAXWORDS]; int numwords = 0; // Use decent variable names. int chr, i; // Code to run until end of file. for (chr = getchar(); chr != EOF;) { // First char. // This bit gets a word. char *tmp = malloc(WORDLENGTH + 1); // Allocate space for word/NUL i = 0; while ((chr != ' ') && (chr != EOF)) { // Read until space/EOF if (i < WORDLENGTH) { // If space left in word, tmp[i++] = chr; // add it tmp[i] = '\0'; // and null-terminate. } chr = getchar(); // Get next character. } line[numwords++] = tmp; // Store. // This bit skips space at end of word. while ((chr == ' ') && (chr != EOF)) { chr = getchar(); } } // Now we have all our words, print them. for (i = 0; i < numwords; i++){ printf ("%s\n", line[i]); free (line[i]); } return 0; }
I suggest you read that and studdy the comments so that you know how it's working. Feel free to ask any questions in the comments section and I'll answer or clarify.
Here's a sample run:
pax$ echo 'hello my name is pax andthisisaverylongword here' | ./testprog hello my name is pax andthisisaveryl here