这对于手头的任务来说可能完全是多余的,但我喜欢将数据封装在structs 中,并为这些structs 创建支持函数。所有样板文件都需要一些时间,但完成后通常会很好。
在这里,我将struct 和typedefined 变成了String。它有一个char* 表示实际数据,size 表示数据,capacity - 这是它当前能够保存的数据量。
typedef struct {
char *data;
size_t size;
size_t capacity;
} String;
为了处理这样的String,我将从创建这些支持函数开始 - 希望具有自我解释的名称和签名:
String *String_create();
void String_destroy(String *s);
bool String_append(String *s, const char *rhs, size_t len);
bool String_getline(String *s, FILE *fp);
这是我们为此所需的最少函数集 - 但如果弹出任何其他内容,您当然可以添加更多 String 函数。
示例实现:
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
char *data;
size_t size;
size_t capacity;
} String;
String* String_create() {
String *s = malloc(sizeof *s); // allocate a String struct
if(s) {
s->size = 0; // initialize its values
s->capacity = 10;
s->data = malloc(s->capacity + 1); // some initial capacity + '\0'
if(s->data == NULL) {
free(s); // deal with allocation problems
return NULL;
}
s->data[0] = '\0'; // null terminate
}
return s;
}
void String_destroy(String *s) { // deallocates a String
free(s->data);
free(s);
}
// Append to an existing string
bool String_append(String *s, const char *rhs, size_t len) {
if(s->size + len > s->capacity) { // check capacity
// not enough space in the String - need to increase it
size_t nc = (s->size + len) * 5 / 3; // make it grow some
char* ns = realloc(s->data, nc + 1); // allocate more space
if(ns == NULL) return false; // could not increase capacity
s->capacity = nc; // set new capacity
s->data = ns; // and the new data pointer
}
// append rhs to our String
memcpy(s->data + s->size, rhs, len);
s->size += len;
s->data[s->size] = '\0'; // ... and null terminate
return true;
}
// Convenience wrappers for the String_append function
bool String_append_char(String *s, char ch) {
return String_append(s, &ch, 1);
}
bool String_append_String(String *s, const String *rhs) {
return String_append(s, rhs->data, rhs->size);
}
// Read a line into a String from a stream
bool String_getline(String *s, FILE *fp) {
s->size = 0; // zero out this String
int ch;
while((ch = fgetc(fp)) != EOF) { // read until EOF
// call the above append function
if(String_append_char(s, ch) == false) return false;
if(ch == '\n') return true; // newline, return success
}
return s->size != 0; // at EOF, did we get some data?
}
使用该样板,可以像这样将文件中的所有内容读入String:
int main() {
String* str = String_create(); // The final String
String* tmp = String_create(); // A temporary String to read lines
while(String_getline(tmp, stdin)) { // Read lines until that fails
// The String is at least one char long if String_getline succeeds so
// this is safe:
if(tmp->data[tmp->size-1] == '\n') { // got newline
tmp->data[tmp->size-1] = '\r'; // replace it with \r
String_append_char(tmp, '\n'); // and add \n
}
// Append this String to the final String
if(String_append_String(str, tmp) == false) {
printf("Could not append %s to %s\n", tmp->data, str->data);
exit(1);
}
}
String_destroy(tmp); // not needed anymore
send_msg(client_socket, str->data, str->size + 1);
String_destroy(str);
}