使用read()扫描char数组

时间:2017-11-29 19:14:51

标签: c

我可以在函数中使用read方法设置char数组吗?我尝试了下面的方法,但它没有产生任何影响。对我来说,我在method()参数中取一个指针,我通过read()将数据保存到它,然后我只是“给”文本的args地址。 不要怪我,我以前用java编码,所以指针可能用错了,注意我犯的每一个错误(请告诉我)。

void method(char* text) {
 char args[100];
 int read = read(STDIN_FILENO, args, 100); // i write "sth" on keyboard
 text = args;
}

在main中:

char c[100];
method(c);
printf("%s",c); // should print "sth"

1 个答案:

答案 0 :(得分:1)

最简单的解决方案:使method需要(通过文档保证,因为C不能强制传递特定的数组大小)调用者提供100大小的缓冲区,而不是维护本地和非本地缓冲。您还希望从read返回结果,以便调用者知道他们收到了多少有效字节:

/* ...
 * text - must point to at least 100 bytes of valid memory
 * Returns number of read bytes
 */
int method(char* text) {
    return read(STDIN_FILENO, text, 100); // i write "sth" on keyboard
}

main

char c[100];
// Store number of valid bytes available
int numvalid = method(c);
// Use .* to specify a dynamic maximum field width, so you don't have a read overflow
printf("%.*s", numvalid, c); // should print "sth"

其他方法包括让函数为调用者执行分配(调用者传递双指针并自己free缓冲区):

int method(char** text) { // Receives double-pointer so it can change caller's char*
    *text = malloc(100); // Dynamic allocation (add error checking)
    return read(STDIN_FILENO, *text, 100); // i write "sth" on keyboard
}

char *c = NULL; // Pointer to be filled, not array
int numvalid = method(&c); // Pass address of pointer so method can change c
// Use .* to specify a dynamic maximum field width, so you don't have a read overflow
printf("%.*s", numvalid, c); // should print "sth"
free(c); // Free memory allocated by method

或继续使用当前的分隔缓冲区,并在method退出之前通过memcpy(复制数据)从一个缓冲区复制到另一个缓冲区,而不是通过指针赋值(不会更改)调用者可见的任何内容):

int method(char* text) {
    char args[100];
    int read = read(STDIN_FILENO, args, 100); // i write "sth" on keyboard
    // Copy data from args to text buffer
    // Note: Using memcpy, *not* strcpy, because read provides no guarantees
    // that the buffer will be NUL-terminated
    memcpy(text, args, read);
    return read; // Still need to return number of valid bytes
}

char c[100];
int numvalid = method(c);
printf("%.*s", numvalid, c); // should print "sth"

这种方法虽然毫无意义; method仍然需要传递一个100字节的缓冲区才能安全运行,它只是不必要地将数据放入临时空间,然后将其复制到最终目的地以浪费周期。

最后,一个保持安全的解决方案,而要求您向method添加返回值:

/* ...
 * text - must point to at least 100 bytes of valid memory
 * On return, data is NUL-terminated, *unless* 100 non-NUL bytes were read
 */
void method(char* text) {
    int numread = read(STDIN_FILENO, text, 100);
    if (0 <= numread && numread < 100) text[numread] = '\0';

    // Or the one-liner for people who don't believe in error handling: :-)
    // text[read(STDIN_FILENO, text, 100)] = '\0';
}

然后调用者可以假设他们的缓冲区最多为100个字节,因此他们可以使用%s格式代码上的限制器停止NUL或100个字节后,以先到者为准:

char c[100];
method(c);
// Use .100 to prevent read overflow, knowing that method NUL terminated
// anything shorter than 100 bytes (preventing undefined behavior reading
// uninitialized bytes for smaller reads)
printf("%.100s", c); // should print "sth"