C-如何阅读短语直到阅读CTRL + Z?

时间:2018-12-18 09:03:52

标签: c string memory-management

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

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

1 个答案:

答案 0 :(得分:1)

反复试验很容易学习。但是此刻,要清理一下。

第一个do not cast malloc in C:它没有用,只能让讨厌的bug保持沉默。

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

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