我需要能够发送GET命令的输出并将其存储到程序内部的变量中,目前我正在这样做:
获取google.com | ./myprogram
并使用以下代码在我的程序中接收它:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main(int argc, char *argv[]){
char *a = (char *) malloc (10000000);
scanf("%[^\n]", a);
printf("%s\n",a);
return 0;
}
我的问题是scanf函数在新行处停止,我需要能够存储GET中的整个段落输出。
任何帮助将不胜感激。谢谢。
答案 0 :(得分:1)
一种可能性:GET是否在标头中包含尺寸信息?您可以使用它来确定要分配多少空间以及要读取多少数据吗?不过,这很奇怪,需要读取点点滴滴的数据。
更简单地说,考虑使用POSIX(和Linux)getdelim()
(getline()
的近亲)并将分隔符指定为空字节。这不太可能出现在GET
输出中,因此整个内容将是单个“行”,并且getdelim()
将自动分配适当数量的空间。它还可以告诉您数据有多长时间。
#include <stdio.h>
int main(void)
{
char *buffer = 0;
size_t buflen = 0;
int length = getdelim(&buffer, &buflen, '\0', stdin);
if (length > 0)
printf("%*.*s\n", length, length, buffer);
free(buffer);
return 0;
}
答案 1 :(得分:0)
scanf文档说
这些函数成功返回输入项的数量 匹配和分配,可能少于提供的数量,甚至 如果早期匹配失败,则为零。值EOF为 如果在第一个输入之前到达输入结束,则返回 转换成功或匹配失败。 EOF也是 如果发生读取错误,则返回,在这种情况下,错误指示符为 设置了流(请参阅ferror(3)),并且设置了errno表示 错误。
https://www.freebsd.org/cgi/man.cgi?query=scanf&sektion=3
您是否考虑过编写一个调用scanf
的循环,监视其返回值并在EOF时中断
答案 2 :(得分:0)
考虑以下在标准C中实现的readall()
函数:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
char *readall(FILE *source, size_t *length)
{
char *data = NULL;
size_t size = 0;
size_t used = 0;
size_t n;
/* If we have a place to store the length,
we initialize it to zero. */
if (length)
*length = 0;
/* Do not attempt to read the source, if it is
already in end-of-file or error state. */
if (feof(source) || ferror(source))
return NULL;
while (1) {
/* Ensure there is unused chars in data. */
if (used >= size) {
const size_t new_size = (used | 65535) + 65537 - 32;
char *new_data;
new_data = realloc(data, new_size);
if (!new_data) {
/* Although reallocation failed, data is still there. */
free(data);
/* We just fail. */
return NULL;
}
data = new_data;
size = new_size;
}
/* Read more of the source. */
n = fread(data + used, 1, size - used, source);
if (!n)
break;
used += n;
}
/* Read error or other wonkiness? */
if (!feof(source) || ferror(source)) {
free(data);
return NULL;
}
/* Optimize the allocation. For ease of use, we append
at least one nul byte ('\0') at end. */
{
const size_t new_size = (used | 7) + 9;
char *new_data;
new_data = realloc(data, new_size);
if (!new_data) {
if (used >= size) {
/* There is no room for the nul. We fail. */
free(data);
return NULL;
}
/* There is enough room for at least one nul,
so no reason to fail. */
} else {
data = new_data;
size = new_size;
}
}
/* Ensure the buffer is padded with nuls. */
memset(data + used, 0, size - used);
/* Save length, if requested. */
if (length)
*length = used;
return data;
}
它将所有内容从指定的文件句柄(可以是标准流,例如stdin
或通过popen()
打开的管道)读取到动态分配的缓冲区中,并附加一个空字节({{1} }),并返回指向缓冲区的指针。如果不为NULL,则读取的实际字符数(因此,不包括附加的nul字节)将存储在第二个参数指向的\0
中。
您可以使用它来读取程序(例如size_t
或图像转换器)甚至是dot -Tpng diagram.dot
输出(从特定的URL,文本或二进制文件中获取数据)输出的二进制数据。
您可以这样使用它,例如:
wget -O -
int main(void)
{
char *src;
size_t len;
src = readall(stdin, &len);
if (!src) {
fprintf(stderr, "Error reading standard input.\n");
return EXIT_FAILURE;
}
fprintf(stderr, "Read %zu chars.\n", len);
/* As an example, print it to standard output. */
if (len > 0)
fwrite(src, len, 1, stdout);
free(src);
return EXIT_SUCCESS;
}
函数有两个怪癖:它以大约131072字节的块分配内存(但如果readall()
返回短读,则可能有所不同),并用7到15个nul字节填充缓冲区。 (我之所以喜欢这样,是有原因的,但是这都是推测性的,并且是针对我倾向于使用的C库的,因此并不重要。)
尽管上面使用的方法可以正常工作,但是如果您愿意,可以更改fread()
的计算。只要确保它们都至少为size_new
。