繁体   English   中英

从 C 中的控制台读取一行

[英]Read a line from console in C

已经够疯狂了,但是从 C 中的控制台读取一行简单的字符似乎非常非常困难... getsfgetsgetlinescanf ....事情,阅读一个简单的行,没有换行符......

那是什么语言? 我遵循这些答案,但我不明白如何存在一种仅从控制台读取字符串如此复杂的语言?

请有人指导我如何使用char* str来读取控制台文本...

以下将从stdin读取一行,然后删除换行符:

char buffer[260];
...
fgets(buffer, sizeof(buffer), stdin);
buffer[strcspn(buffer, "\n")] = 0;  

C 库函数 char *fgets(char *str, int n, FILE *stream) 从指定的流中读取一行并将其存储到 str 指向的字符串中。 它在读取 (n-1) 个字符、读取换行符或到达文件结尾时停止,以先到者为准。

为了收集更大量的输入,可以在循环内调用此构造。 请注意,如何累积每个连续的缓冲区是另一个主题。

更多关于fgets()

@ryker 提供了一个很好的答案,可以解释大部分内容。 这是一个非常安全的实现,它是 100% 可移植的,并且允许您不必担心换行符、缓冲区溢出或分配。 但它返回一个您需要释放的指针。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *gline() {
    char *buffer;

    const size_t step = 10;
    size_t size = step;

    if(!(buffer = malloc(size))) goto CLEANUP;

    char *s = buffer;

    // step-1 is not strictly necessary, but some implementations of fgets
    // are buggy. That's why it's step-1 instead of just step
    while(fgets(s, step-1, stdin)) {
        if(strchr(s, '\n')) break;
        size += step;
        if(!(buffer = realloc(buffer, size))) goto CLEANUP;
        s = &buffer[strlen(buffer)];
    }

    buffer[strcspn(buffer, "\n")] = 0;
    return buffer;

CLEANUP:
    free(buffer);
    return NULL;
}

int main(void) {
    char *s = gline();
    if(!s)
        puts("Error reading line");
    else
        puts(s);
    free(s);
}

我还没有对它进行微调,因此它可能分配了比需要更多的内存。 它也不是很有效,因为它在每次迭代中都运行strlen 但是只要分配没有失败,它就是安全且易于使用的。

scanf这样的内置函数可以做到这一点,但我对它们的问题是你需要提前知道你会收到多少输入。 如果是 1 个字符呢? 如果是10000呢? 所以我更喜欢使用mallocrealloc动态分配内存并在接收到输入时构建字符串。 当我需要从stdin或文件中读取时,这就是我使用的。 它很简单,可能远非完美,它只是从流中获取一个字符,如果它不是换行符或EOF则将其添加到字符串中。 如果重新分配失败,它会释放整个字符串,因为我需要采用“全有或全无”的方法来构建字符串。 它返回一个指向字符串或NULL或任何失败的指针。

char* get_str(FILE* stream)
{
    char *s;
    int ix = 0, sz = 1, rf = 0, ch;

    if(stream == NULL) {
        s = NULL;
    } else {
        s = (char*)malloc(sizeof(char) * sz);
        if(s != NULL) {
            s[ix] = '\0';
            ch = fgetc(stream);
            while(ch != '\n' && ch != EOF && rf == 0) {
                sz++;
                s = (char*)realloc(s, sizeof(char) * sz);
                if(s != NULL) {
                    s[ix] = ch;
                    ix++;
                    s[ix] = '\0';
                    ch = fgetc(stream);
                } else {
                    rf = 1;
                    free(s);
                    s = NULL;
                }
            }
        }
    }

    return s;
}

然后你这样称呼它:

int main()
{
    char *s = get_str(stdin); /* or a file you opened with fopen, etc */

    printf("%s\n", s);

    free(s);

    return 0;
}

请记住,需要释放使用malloccallocrealloc分配的malloc

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM