其他人已经告诉过您的代码存在一些具体问题,但他们似乎遗漏了一件事情,那就是 c 应该是 int,而不是 char。否则与EOF 的比较将无法按预期进行。
另外,你得到的段错误是因为这个序列:
line[n++]=tmp;
printf("\n%s\n",line[n]);
您已经将n 增加到下一个数组元素,然后您尝试打印它。第二行应该是:
printf("\n%s\n",line[n-1]);
如果您只想要一些有效的代码(使用免费的“做你想做的事”许可证),这里有一个来自我的代码库的有用的 sn-p。
我不确定为什么您认为应该避免使用fgets,它实际上非常方便且非常安全。我假设您的意思是gets,它不太方便且完全不安全。您的代码也容易出现缓冲区溢出,因为如果它得到很多既不是空格也不是文件结尾的字符,它会很高兴地写入超出分配区域的末尾。
如果您正在自学,请务必编写自己的代码,但其中一部分应该是检查经过生产测试的防弹代码,以了解它是如何完成的。而且,如果您不自学,那么不使用免费提供的代码就是在伤害自己。
sn-p 如下:
#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'、CTRLD 和太大的字符串运行示例:
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;
}
我建议您阅读并研究 cmets,以便了解它是如何工作的。欢迎在 cmets 部分提出任何问题,我会回答或澄清。
这是一个示例运行:
pax$ echo 'hello my name is pax andthisisaverylongword here' | ./testprog
hello
my
name
is
pax
andthisisaveryl
here