我有一堆printf()
正确打印了一个我必须构建的非常复杂的字符串。
问题是我需要将该字符串存储在一个变量中(所有这些printf()
的结果一起通过套接字发送它们。我很确定我需要立即发送它们 - 但如果你想让我相信那不是真的,我会打开一个小窗口。
实现这一目标的最佳方式是什么?
字符串长度是REALLY变量。我听说过sprintf()
和realloc()
,甚至asprintf()
,但我不能只看到如何将所有这些混合在一起。
这是我目前的代码:
void mostrarVariable(char *variable, void *valor) {
printf("%s=%d\n", variable, *(int *)valor);
}
void mostrarEntradaStack(t_registro_stack *entradaStack) {
printf("%d,%s\n", entradaStack->retorno, entradaStack->nombre_funcion);
}
void suspender(t_pcb *pcb) {
char *mensaje = NULL;
mensaje = strdup("1Proceso suspendido...");
// FIXME: guardar los printf en una variable y enviarlo por la red
printf("----------------\n\n");
printf("ID=%d\n", pcb->id_proceso);
printf("PC=%d\n", pcb->program_counter);
printf("\n-- Estructura de codigo --\n");
int indice = 0;
// believe me: this iterates a char** printf-ing each line
while(pcb->codigo[indice] != NULL) {
printf("%s\n", pcb->codigo[indice++]);
}
printf("----------------\n");
printf("\n-- Estructuras de datos --\n");
// believe me: this calls mostrarVariable() for each entry in the pcb->datos dictionary
dictionary_iterator(pcb->datos, mostrarVariable);
printf("----------------\n\n");
printf("-- Estructura de Stack --\n");
// believe me: this calls mostrarEntradaStack() for each element in the stack without modifying it
pila_hacer(pcb->stack, mostrarEntradaStack);
printf("\n----------------\n");
// believe me: this sends "mensaje" via a socket ("pcb->id_proceso"), and it handles the partial send()s and all of that
// it has to be on one socket_send() to correctly send the message length to the other endpoint - the protocol pretty works
socket_send(pcb->id_proceso, mensaje, strlen(mensaje) + 1);
}
相信我,代码目前有效,但由于mensaje
只有值“1Proceso suspendido ...”,数据会在本地打印而不是发送到遥控器。
示例输出:
----------------
ID=4
PC=6
-- Estructura de codigo --
#!/home/desert69/workspaces/operativos/no-quiero/procer/pi/build/pi
# Comentario
variables a,b,c,d,e
comienzo_programa
a=1
b=2;3
c=a+b
d=c-3
f1()
f2()
e=a+c;2
imprimir a
imprimir b
imprimir c
imprimir d
imprimir e
fin_programa
comienzo_funcion f1
a=3
f3()
b=4
fin_funcion f1
comienzo_funcion f2
a=a+1
fin_funcion f2
comienzo_funcion f3
c=d
fin_funcion f3
----------------
-- Estructuras de datos --
c=159769736
d=159769776
a=159769600
b=159769696
e=159769816
----------------
-- Estructura de Stack --
----------------
对不起西班牙语的代码,但我想确定它与我正在运行的完全相同。也许以后(如果可以的话)我会尝试翻译它,但我不确定。即使很难,重要的是将每个printf()
替换为 ,以便将这些输出附加到mensaje
。
如果您需要任何进一步的信息,请随时发表评论。
感谢。真的:)
答案 0 :(得分:2)
最简单的方法是连接一堆sprintf
语句。忽略错误条件,该语句返回写入的字符数。所以你基本上可以这样做:
char *bufptr = buffer;
bufptr += sprintf( bufptr, "ID=%d\n", pcb->id_proceso );
bufptr += sprintf( bufptr, "PC=%d\n", pcb->program_counter );
等
然后buffer
包含从sprintf
的连续调用构建的字符串。显然你需要确保缓冲区足够大。如果您预计有任何错误, 应该处理错误。
此外,您使用bufptr - buffer
获取字符串的最终长度,这有助于了解您是否通过套接字发送此字符串。
答案 1 :(得分:0)
您可以在该缓冲区中创建大buffer
和sprintf()
个所有数据。
char buffer[20000]; // large enough
char str[500]; // temporary string holder
buffer[0] = '\0'; // clean up the buffer
sprintf( str, "----------------\n\n"); strcat( buffer, str);
sprintf( str, "ID=%d\n", pcb->id_proceso); strcat( buffer, str);
sprintf( str, "PC=%d\n", pcb->program_counter); strcat( buffer, str);
sprintf( str, "\n-- Estructura de codigo --\n"); strcat( buffer, str);
......等等
答案 2 :(得分:0)
乍一看看起来很琐碎。在每一步,您都要附加一个字符串或一个int。
可以将前者简化为后者char tmp[100];
snprintf(tmp, sizeof tmp - 1, "%d", n);
append_string(tmp); // pseudo-code
所以你需要的是一种将字符串附加到另一个字符串的方法。这可以通过strlen
,realloc
,strcpy
或memcpy
的组合来完成。
更大的问题是,您的dictionary_iterator
和pila_hacer
功能似乎不允许您将任何其他信息传递给回调。 printf
并不关心,因为它只能使用全局stdout
,但是如果你想将它附加到字符串,你可能需要在这里使用全局变量,所以你的回调知道了在哪里追加。
答案 3 :(得分:0)
我最终创建了一个string_concat()
函数,它接收一个original
字符串,一个格式和一个变量参数列表,并应用vsnprintf
格式和参数,并附加到原始字符串:
编辑:好的,所以我之前的做法是错误的。我认为va_list
存在问题。这是新版本:
/**
* @NAME: string_append
* @DESC: Agrega al primer string el segundo
*
* Ejemplo:
* char *unaPalabra = "HOLA ";
* char *otraPalabra = "PEPE";
*
* string_append(&unaPalabra, otraPalabra);
*
* => unaPalabra = "HOLA PEPE"
*/
void string_append(char** original, char* string_to_add) {
*original = realloc(*original, strlen(*original) + strlen(string_to_add) + 1);
strcat(*original, string_to_add);
}
/**
* @NAME: string_concat
* @DESC: Concatena al primer string el resultado de aplicar los parametros al
* formato especificado
*
* Ejemplo:
* char *saludo = "HOLA ";
* char *nombre = "PEPE";
*
* string_concat(&saludo, "%s!", nombre);
*
* => saludo = "HOLA PEPE!"
*/
void string_concat(char **original, const char *format, ...) {
size_t buffer_size = strlen(format) + 1;
char *temporal = malloc(buffer_size);
size_t message_length = 0;
va_list arguments;
va_start(arguments, format);
while((message_length = vsnprintf(temporal, buffer_size, format, arguments)) > buffer_size - 1) {
buffer_size *= 2;
temporal = (char *) realloc(temporal, buffer_size);
}
va_end(arguments);
temporal = (char *) realloc(temporal, message_length + 1);
string_append(original, temporal);
}
string_append()
仍在泄露记忆(由于realloc()
),我希望能管理后者。
BUGGY CODE在这里开始
/**
* @NAME: string_append
* @DESC: Appends the second string to the first
*
* Example:
* char *aWord = "Hello, ";
* char *anotherWord = "world!";
*
* string_append(&aWord, anotherWord);
*
* => aWord = "Hello, world!"
*/
void string_append(char** original, char* string_to_add) {
*original = realloc(*original, strlen(*original) + strlen(string_to_add) + 1);
strcat(*original, string_to_add);
}
/**
* @NAME: string_concat
* @DESC: Concatenates to the first string the result of applying the arguments to
* the specified format
*
* Example:
* char *salute = "Hello";
* char *name = "world";
*
* string_concat(&salute, ", %s!", name);
*
* => salute = "Hello, world!"
*/
void string_concat(char **original, const char *format, ...) {
size_t buffer_size = strlen(format) + 1;
char *temporal = malloc(buffer_size);
size_t message_length = 0;
va_list arguments;
va_start(arguments, format);
while((message_length = vsnprintf(temporal, buffer_size, format, arguments)) > buffer_size - 1) {
buffer_size *= 2;
temporal = (char *) realloc(temporal, buffer_size);
}
va_end(arguments);
temporal = (char *) realloc(temporal, message_length + 1);
string_append(original, temporal);
}
BUGGY CODE结束
我之前从my assignature repository获得了string_append()
。
我认为它没有内存泄漏/问题,但还没有真正测试过那么多。但是对我来说是合情合好的,至少我在最初的问题中已经展示了这个例子。
所以这是我之前展示的代码的最终版本:
void suspender(t_pcb *pcb) {
char *mensaje = NULL;
mensaje = strdup("1Proceso suspendido...\n\n");
string_concat(&mensaje, "----------------\n\n");
string_concat(&mensaje, "ID=%d\n", pcb->id_proceso);
string_concat(&mensaje, "PC=%d\n", pcb->program_counter);
string_concat(&mensaje, "\n-- Estructura de codigo --\n");
int indice = 0;
while(pcb->codigo[indice] != NULL) {
string_concat(&mensaje, "%s\n", pcb->codigo[indice++]);
}
string_concat(&mensaje, "----------------\n");
string_concat(&mensaje, "\n-- Estructuras de datos --\n");
// TODA la magia negra junta: inner functions!! (?!!?!?!)
void mostrarVariableEnMensaje(char *variable, void *valor) {
string_concat(&mensaje, "%s=%d\n", variable, *(int *)valor);
}
dictionary_iterator(pcb->datos, mostrarVariableEnMensaje);
string_concat(&mensaje, "----------------\n\n");
string_concat(&mensaje, "-- Estructura de Stack --\n");
void mostrarEntradaStackEnMensaje(t_registro_stack *entradaStack) {
string_concat(&mensaje, "%d,%s\n", entradaStack->retorno, entradaStack->nombre_funcion);
}
pila_hacer(pcb->stack, mostrarEntradaStackEnMensaje);
string_concat(&mensaje, "\n----------------\n");
socket_send(pcb->id_proceso, mensaje, strlen(mensaje) + 1);
free(mensaje);
}