Другие уже говорили вам о некоторых специфических проблемах с вашим кодом, но одна вещь, которую они, похоже, упустили, это то, что c
должно быть int
, а не char
. В противном случае сравнение с EOF
не будет работать должным образом.
Кроме того, вы получаете segfault из-за этой последовательности:
line[n++]=tmp;
printf("\n%s\n",line[n]);
У вас уже увеличен n
до следующего элемента массива, затем вы пытаетесь его распечатать. Эта вторая строка должна быть:
printf("\n%s\n",line[n-1]);
Если вы просто хотите, чтобы какой-то код работал (с бесплатной лицензией «делай, что хочешь, черт побери»), вот полезный фрагмент из моей библиотеки кодов.
Я не уверен, почему вы думаете, что fgets
следует избегать, это на самом деле очень удобно и очень безопасно. Я предполагаю, что вы имели в виду gets
, который менее удобен и абсолютно небезопасен. Ваш код также подвержен переполнению буфера, так как он будет успешно записывать за пределы вашей выделенной области, если получит много символов, которые не являются ни пробелом, ни концом файла.
Во что бы то ни стало, напишите свой собственный код, если вы обучаетесь, но часть этого должна быть посвящена проверенному на производстве пуленепробиваемому коду, чтобы увидеть, как это можно сделать . И, если вы не обучаете себя, вы оказываете себе медвежью услугу, не используя свободно доступный код.
Ниже приведен фрагмент кода:
#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;
}
Это полезная функция ввода строки, которая имеет такую же защиту от переполнения буфера, что и fgets
, и также может обнаруживать слишком длинные строки, введенные пользователем. Он также отбрасывает оставшуюся часть слишком длинной строки, чтобы не влиять на следующую операцию ввода.
Пример запускается с 'hello', CTRL D и слишком большой строкой:
pax> ./qq
Enter string> hello
OK [hello]
pax> ./qq
Enter string>
No input
pax> ./qq
Enter string> dfgdfgjdjgdfhggh
Input too long
pax> _
Для чего это стоит (и не сдавайте это как свою собственную работу, так как вы почти наверняка будете пойманы на плагиат) - любой полу-приличный преподаватель будет искать ваш код в сети как первое, что он делает ), вот как я к этому подхожу.
#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;
}
Я предлагаю вам прочитать это и изучить комментарии, чтобы вы знали, как это работает. Не стесняйтесь задавать любые вопросы в разделе комментариев, и я отвечу или уточню.
Вот пример прогона:
pax$ echo 'hello my name is pax andthisisaverylongword here' | ./testprog
hello
my
name
is
pax
andthisisaveryl
here