简体   繁体   English

读取 C 中的任意长度字符串

[英]Reading arbitrary length strings in C

I've attempted to write a C program to read a string and display it back to the user.我试图编写一个 C 程序来读取字符串并将其显示给用户。 I've tested it with a lot of input and it seems to work properly.我已经用大量输入对其进行了测试,它似乎工作正常。 The thing is that I'm not sure whether or not the c != EOF condition is necessary inside the while expression, and since by definition, the size of a char is 1 byte, maybe I can remove the sizeof(char) expressions inside the malloc and realloc statements, but I'm not sure about this.问题是我不确定c != EOF条件是否在 while 表达式中是必需的,因为根据定义,char 的大小是 1 字节,也许我可以删除里面的sizeof(char)表达式mallocrealloc语句,但我不确定这一点。

Here's the program, also, I manually added a null terminating character to the string:这是程序,我也手动在字符串中添加了一个 null 终止字符:

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

int main(void)
{
    char *str = malloc(sizeof(char));

    if (!str)
        return 1;

    char c;
    char *reallocStr;
    size_t len = 0;
    size_t buf = 1;

    printf("Enter some text: ");

    while ((c = getchar()) != '\n' && c != EOF) {
        if (len == buf) {
            buf *= 2;

            reallocStr = realloc(str, buf * sizeof(char));

            if (!reallocStr)
                return 1;

            str = reallocStr;
        }

        str[len++] = c;
    }

    str[len] = '\0';

    printf("You entered: %s\n", str);

    free(str);
    
    return 0;
}

As mentioned in the comments, you have a buffer overflow in your code, so you would need to fix that at the very least.如评论中所述,您的代码中有缓冲区溢出,因此您至少需要修复它。 To answer your specific questions, sizeof(char) is guaranteed to be 1 (dictated by the c99 spec), so you don't need to multiply by sizeof(char) .要回答您的具体问题, sizeof(char)保证为 1(由 c99 规范规定),因此您无需乘以sizeof(char) It's good practice to check for EOF as if your input is coming from an alternate source that has no newline, you don't die (so if someone for example did printf %s hello | yourprogram from a bash prompt, you wouldn't die).检查EOF是一种很好的做法,就好像您的输入来自没有换行符的备用源一样,您不会死(例如,如果有人做了printf %s hello | yourprogram来自 bash 提示,您不会死)。

Problems include问题包括

Buffer overflow缓冲区溢出

@HardcoreHenry @HardcoreHenry

Incorrect type类型不正确

getchar() reruns an int with the values [0..UCHAR_MAX] and the negative: EOF . getchar()使用值 [0..UCHAR_MAX] 和负值重新运行intEOF These 257 different values lose distinctiveness when saved as a char .这 257 个不同的值在保存为char时会失去独特性。 Possible outcomes: infinite loop or premature loop end.可能的结果:无限循环或过早的循环结束。 Instead:反而:

// char c;
int c;

Advanced: Arbitrary length进阶:任意长度

For very long lines buf *= 2;对于长的行buf *= 2; overflows when buf is SIZE_MAX/2 + 1 .bufSIZE_MAX/2 + 1时溢出。 An alterative to growing in steps of 1, 2, 4, 8, 16,..., consider 1, 3, 7, 15, .... That way code can handle strings up to SIZE_MAX .以 1, 2, 4, 8, 16,... 的步长增长的替代方法,考虑 1, 3, 7, 15, .... 这样代码可以处理高达SIZE_MAX的字符串。

Advanced: Reading '\0'高级:读取'\0'

Although uncommon, possible to read in a null character .虽然不常见,但可以在null 字符中读取。 Then printf("You entered: %s\n", str);然后printf("You entered: %s\n", str); will only print to that null character and not to the end of input.只会打印到该null 字符而不是输入的末尾。

To print all, take advantage that code knows the length.要全部打印,请利用代码知道长度的优势。

printf("You entered: ");
fwrite(str, len, 1, stdout);
printf("\n"); 

To be clear, text input here is not reading of strings , but of reading of lines .需要明确的是,这里的文本输入不是读取字符串,而是读取 That input is saved and converted to a string by appending a null character .该输入通过附加null 字符被保存并转换为字符串 Reading a '\0' complicates things, but something robust code handles.读取'\0'会使事情复杂化,但可以处理一些健壮的代码。

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

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