【问题标题】:C - How to read phrases until reading CTRL+Z?C - 在阅读 CTRL+Z 之前如何阅读短语?
【发布时间】:2018-12-18 09:03:51
【问题描述】:

我想阅读短语,直到我输入 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;
}

你能告诉我我做错了什么以及应该怎么做吗?

【问题讨论】:

  • 捕捉 SIGSTOP 信号
  • 您使用的是 Windows 还是 Linux,因为答案因操作系统而异。
  • @user3386109 窗口
  • @kiranBiradar 我 99.99% 确信这不是这样做的方法。我只是尝试输入 CTRL+Z 并显示“^Z”所以我想我可以将它与它进行比较。
  • CTRL-Z 在标准输入上导致文件结束条件。您可以通过检查来自fgets 的返回值来检测这一点。 fgets 到达文件末尾时将返回 NULL。

标签: c string memory-management


【解决方案1】:

反复试验很好学。不过现在要收拾东西了。

do not cast malloc in C:没用,只能让讨厌的虫子沉默。

然后,您正在使用 2 个动态分配的字符串数组 phrasesaux,现在只需使用:

phrases=aux;

这很糟糕,因为它会泄漏先前由短语指向的内存:它仍然被分配,但在程序结束之前你既不能访问它,也不能释放它。

保持愚蠢 简单是一个很好的规则。在这里你可以忘记aux,只使用phrases

无论如何,你真正的问题是关于如何知道输入了 Ctrl Z? 那么 Windows 上的 Ctrl-Z 或类 Unix 上的 Ctrl-D 生成和 文件结尾 条件 在终端上键入时 - 从文件或管道读取时它们没有效果...

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。但是,如果您发现它更清晰或更一致,则可以保留它。

【讨论】:

  • 感谢您的所有澄清。我还删除了铸造 malloc 并停止使用 aux。它按预期工作!
猜你喜欢
  • 1970-01-01
  • 2011-08-12
  • 2016-02-14
  • 1970-01-01
  • 2013-04-17
  • 2010-11-06
  • 2010-10-28
  • 1970-01-01
  • 2019-09-11
相关资源
最近更新 更多