我想阅读短语,直到输入 Ctrl + Z 然后显示它们。我写了一个代码,但是输入一个短语后,它显示了该短语并退出。另外,我想动态分配内存。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char words[100],
**phrases,
**aux;
int c = 0;
phrases = (char **)malloc(1 * sizeof(char *));
if (phrases == NULL) exit(1);
aux = (char **)malloc(1 * sizeof(char *));
if (aux == NULL) exit(1);
do {
printf("Enter phrase: ");
fgets(words, 100, stdin);
aux[c] = (char *)malloc(strlen(words) * sizeof(char));
if (aux[c] == NULL) exit(1);
phrases[c] = aux[c];
strcpy(phrases[c], words);
c++;
aux = (char **)realloc(phrases, (c + 1) * sizeof(char *));
if (aux == NULL) exit(1);
phrases = aux;
} while (strcmp(phrases, "^Z") == 0);
for (int i = 0; i < c; i++) {
fputs(phrases[i], stdout);
printf("\n");
}
for (int i = 0; i < c; i++) free (phrases[i]);
free (phrases);
return 0;
}
您能告诉我我做错了什么以及应该怎么做吗?
答案 0 :(得分:1)
反复试验很容易学习。但是此刻,要清理一下。
第一个do not cast malloc in C:它没有用,只能让讨厌的bug保持沉默。
然后您正在使用2个动态分配的字符串数组phrases
和aux
,此刻只需使用:
phrases=aux;
这很糟糕,因为它会泄漏以前由短语指向的内存:它仍处于分配状态,但是您无法访问它,甚至无法释放它,直到程序结束。
保持愚蠢简单是一个好规则。在这里,您可能会忘记aux
而仅使用phrases
。
无论如何,您真正的问题是关于如何知道是否输入了Ctrl Z?在Windows上是Ctrl-Z还是在Unix-like上是Ctrl-D,例如生成和文件的 < / em>条件在终端上键入时-从文件或管道读取时它们没有任何作用...
fgets
在文件末尾返回NULL(或错误),因此您应该在循环中对其进行测试。并且不要尝试在此处找到聪明的while
,因为读取必须在提示后进行,而测试必须在读取后立即进行。因此,请坚持使用旧的for (;;) { ... break; ...}
最后,fgets
读到行尾并将其保留在缓冲区中。因此,除非您要弄清楚长于99个字符的行会发生什么,否则在打印短语后无需再显示一个
所有这些之后,您的代码可能会变成:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char words[100], **phrases /*, **aux */;
int c=0;
phrases=(char **)malloc(1*sizeof(char *));
if (phrases==NULL) exit(1);
/* aux=(char **)malloc(1*sizeof(char *));
if (aux==NULL) exit(1); */
for(;;) {
printf("Enter phrase: ");
if (NULL == fgets(words, 100, stdin)) break; // exit loop on end of file
phrases[c]=(char *)malloc(strlen(words)*sizeof(char)); // note sizeof(char) is 1 by definition
if (phrases[c]==NULL) exit(1);
strcpy(phrases[c], words);
c++;
phrases=(char **)realloc(phrases, (c+1)*sizeof(char *));
if (phrases==NULL) exit(1);
}
printf("\n"); // skip a line here to go pass the prompt
for (int i=0; i<c; i++) {
fputs(phrases[i], stdout);
//printf("\n"); // you can keep it to make long lines splitted
}
for (int i=0; i<c; i++) free (phrases[i]); // ok free the strings
free (phrases); // then the array
return 0;
}
次要改进:sizeof(char)
可以省略,因为根据定义它是1 。但是,如果您发现它更清晰或更一致,则可以保留它。