C 现有数据正在丢失
我正在学习c语言。下面的程序将命令的输出获取到变量并打印它。但是当重新分配内存以扩展内存时,我丢失了旧数据 你能告诉我我在这里遗漏了什么吗C 现有数据正在丢失,c,gnu,C,Gnu,我正在学习c语言。下面的程序将命令的输出获取到变量并打印它。但是当重新分配内存以扩展内存时,我丢失了旧数据 你能告诉我我在这里遗漏了什么吗 #include<stdio.h> #include<stdlib.h> #include<string.h> int main(){ FILE *fp; char r[1024]; fp=popen("/bin/ls /etc/","r"); if(fp==NULL){ perror("Failed to
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(){
FILE *fp;
char r[1024];
fp=popen("/bin/ls /etc/","r");
if(fp==NULL){
perror("Failed to run the command");
exit(-1);
}
int totallengthread=0,alloc_size=1024;
char *buffer = (char*) malloc(alloc_size*sizeof(char));
memset(buffer,0,sizeof(buffer));
int lenofbuff=0;
while(fgets(r,1023,fp)!=NULL){
concat(buffer,r);
lenofbuff=strlen(buffer);
totallengthread+=lenofbuff;
if(totallengthread>=alloc_size){
alloc_size+=1024;
realloc(buffer,alloc_size);
}
}
pclose(fp);
printf("this is the out put =>%s",buffer);
free(buffer);
return 0;
}
void concat(char *dest, const char *source){
char *d=dest;
char *s=source;
while (*d != '\0') {
d++;
}
while(*s!='\0')
{
*d++=*s++;
}
*d='\0';
}
#包括
#包括
#包括
int main(){
文件*fp;
charr[1024];
fp=popen(“/bin/ls/etc/”,“r”);
如果(fp==NULL){
perror(“未能运行命令”);
出口(-1);
}
int totalengthread=0,alloc_size=1024;
char*buffer=(char*)malloc(alloc_size*sizeof(char));
memset(buffer,0,sizeof(buffer));
int lenofbuff=0;
while(fgets(r,1023,fp)!=NULL){
concat(缓冲液,r);
lenofbuff=strlen(缓冲区);
totallengthread+=lenofbuff;
如果(TotalEngThread>=所有尺寸){
alloc_大小+=1024;
realloc(缓冲区、分配大小);
}
}
pclose(fp);
printf(“这是输出=>%s”,缓冲区);
自由(缓冲);
返回0;
}
void concat(char*dest,const char*source){
char*d=dest;
char*s=源;
而(*d!='\0'){
d++;
}
而(*s!='\0')
{
*d++=*s++;
}
*d='\0';
}
realloc()
是通用内存重新分配的构建块
代码需要使用来自realloc()
的返回值,因为这是成功时指向重新分配数据的指针
void * tptr = realloc(buffer, alloc_size);
// Detect out-of-memory
if (tptr == NULL && alloc_size > 0) {
// Handle it in some way
fprintf(stderr, "Memory allocation failure\n");
exit(EXIT_FAILURE);
}
buffer = tptr;
注意:存在各种其他非分配代码问题。我认为这更接近您想要的。请参见代码中的注释
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void concat(char *dest, const char *source){
char *d=dest;
char *s=source;
while (*d != '\0'){
d++;
}
while(*s!='\0'){
*d++=*s++;
}
*d='\0';
}
int main(){
FILE *fp;
char r[1024];
fp=popen("/bin/ls /etc/","r");
if(fp==NULL){
perror("Failed to run the command");
exit(-1);
}
int totallengthread=0,alloc_size=1024;
char *buffer = malloc(alloc_size*sizeof*buffer); //This is nicer because is type independent
memset(buffer,'\0',sizeof*buffer); //I believe this is what you wanted.
int lenofbuff=0;
while(fgets(r,sizeof r,fp)){ // as @chux said this avoids hardcoding 1024-1. You also don't need to compare to NULL.
concat(buffer,r);
lenofbuff=strlen(buffer);
totallengthread+=lenofbuff;
if(totallengthread>=alloc_size){
alloc_size+=1024;
buffer = realloc(buffer,alloc_size); //you need to use the return of realloc
}
}
pclose(fp);
printf("this is the out put =>%s",buffer);
free(buffer);
return 0;
}
相当于
memset(buffer,0,sizeof*buffer);
正如@thebusybee提到的,这只是将数组的第一个元素设置为空字符,如果您打算填充整个数组,那么您应该这样做
memset(缓冲区,0,缓冲区的分配大小)
或者仅仅是替换
char *buffer = malloc(alloc_size*sizeof*buffer);
memset(buffer,0,alloc_size*sizeof*buffer);
为了
这一行:
memset(buffer,0,sizeof(buffer))
并不像您想象的那样。(这也是不必要的。)您应该在concat(buffer,r)之前检查缓冲区大小(并重新分配)
而不是fgets
和后续的strlen
,您应该使用fread
读取数据并使用返回值。阅读函数的文档肯定会有帮助:man realloc
或查找@willampersell-使用fread()而不是fgets()的问题
是指fread()
不注意线路,除非输入恰好来自终端或管道。如果要求fread()
从磁盘文件中读取1023个字符,它会这样做,除非在此之前有EOF。使用POSIX返回长度,包括空字节,这也是fgets()
的一个问题;它有着微妙不同的缺点(单行线太大了,不太舒服)。memset()
仍然是错误的,因为sizeof*buffer
等于sizeof buffer[0]
等于sizeof(char)
是1。它必须是memset(buffer,'\0',allocsize*sizeof buffer[0])
。malloc()
和memset(…,0,…)
的组合可以替换为calloc()
,顺便说一句。@thebusybee我同意这是将整个分配内存设置为0的正确方法,但这是假设OP想要将整个内存而不是第一个字符设置为'\0'
很好。我被“代码> MeMSET())/<代码>所误导,我从来没有考虑过用它来设置一个元素。我会使用buffer[0]='\0'代码>当然。while(fgets(r,1023,fp)!=NULL){
以一种正常的方式关闭。建议while(fgets(r,sizeof r,fp)!=NULL){
或者干脆while(fgets(r,sizeof r,fp)){
@chux True,硬编码的1023不是很好。我只是试图解决与OP的问题最密切相关的问题,但确实我可以补充一下。
char *buffer = malloc(alloc_size*sizeof*buffer);
memset(buffer,0,alloc_size*sizeof*buffer);
char *buffer = calloc(alloc_size,sizeof*buffer);