簡體   English   中英

標准輸出緩沖問題

[英]stdout buffering problems

我已經寫了這段代碼

#include<stdio.h>
#include<assert.h>
#include<stdlib.h>

char *list[20],*story[100];

FILE*listfile;
FILE*infile;
FILE*outfile;

int check(char*string)
{
  int i=0;
  while(list[i]!=NULL)
    {
      if(strcmp(string,list[i])==0){return 1;};
      i++;
    };
  return 0;
};

void print_d(int d){ printf(" debug %d ",d);};

int main(int argc,char**argv){

  assert(argc==4);
  printf("hello \n");
  //assigning the file pointers in their respective modes
  printf("%s %s %s ",argv[1],argv[2],argv[3]);
  listfile=fopen(argv[1],"r");
  print_d(12);
  infile=fopen(argv[2],"r");
  outfile=fopen(argv[3],"w");
  print_d(0);
  int i=0; /* the infamous 'i' */

  while(1)
    {

      if(feof(listfile)!=0)
        { break;};
      list[i]=malloc(sizeof(char [15]));
      fscanf(listfile,"%s[^\n]",list[i]);
      i++;


    }
  i=0;
  print_d(1);
  while(1)
    {

      if(feof(infile)!=0)
        { break;};
      story[i]=malloc(sizeof(char [25]));
      fscanf(infile,"%s",story[i]);
      i++;

    }
  fclose(infile);
  fclose(listfile);
  i=0;

  print_d(2);
  while(1)
    {

      if(check(story[i])==1)
        { fprintf(outfile,"%s","censored");}
      else
        {
          fprintf(outfile,"%s",story[i]);
        };
    };
  print_d(3);
  fclose(outfile);
  i=0;
  while(list[i]!=NULL)
    { free(list[i]);};
  return 0;


}

隨后出現以下問題

[1]輸出是您好,然后是段錯誤

這就是事情變得有趣的地方

如果我修改

printf(“%s%s%s”,argv [1],argv [2],argv [3]);

printf(“%s%s%s \\ n”,argv [1],argv [2],argv [3]);

輸出是“ hello”,后跟文件的三個名稱,然后是段錯誤。

在用戶danfuzz指出我應該將print_d調試更改為print轉換為stderr之后(我確實這樣做了)..調試打印現在可以正常工作了。所以我想一個更好的問題是,為什么會首先發生這種情況並采取措施防止這種情況發生事情發生了嗎?

對於經驗豐富的程序員來說,這似乎是一個微不足道的問題,但是請注意,較早的版本(上面的代碼中的那個)在seg錯誤之前無法打印出任何消息,導致我斷定在/ opening的命令行部分發生了某些事情文件。

一些觀察,

您應該閱讀有關fflush(stdout) ,因為它可以幫助您進行調試,

void print_d(int d)
{
    printf(" debug %d ",d); fflush(stdout);
};

您分配給char指針數組, list[20]story[100] ,但是您有循環(由臭名昭著的“ i”索引),可以輕松地走出列表或故事的結尾。

您嘗試打開文件名argv[2]argv[3] ,一個讀為一個寫,將這些行更改為以下內容,

printf("%s %s %s ",argv[1],argv[2],argv[3]); fflush(stdout);

if( !(listfile=fopen(argv[1],"r")) )
{
    printf("cannot open %s\n",argv[1]); fflush(stdout);
    return(1);
}
print_d(1);
if( !(infile=fopen(argv[2],"r")) )
{
    printf("cannot open %s\n",argv[2]); fflush(stdout);
    return(2);
}
print_d(2);
if( !(outfh=fopen(argv[3],"w+")) ) //notice the "w+" to create missing file
{
    printf("cannot open %s\n",argv[3]); fflush(stdout);
    return(3);
}
print_d(3);

現在文件已正確打開,因此將debug print_d參數更改為增加的數字順序,以便您可以順序發現哪個,並且由於使用的是計數器,因此for(;;)循環有效,

int check(char*string)
{
    int i;
    for(i=0; list[i]!=NULL; i++)
    {
        if(strcmp(string,list[i])==0){return 1;};
    };
    return 0;
};

更改循環以成功讀取兩個文件,

for(i=0; i<20; ++i)
{
    if(feof(listfh)!=0) { break; };
    list[i]=malloc(sizeof(char [15]));
    fscanf(listfh,"%s[^\n]",list[i]);
}
fclose(listfh);
debug(4);

和,

for(i=0; i<20; ++i)
{
    if(feof(infh)!=0) { break; };
    story[i]=malloc(sizeof(char [25]));
    fscanf(infh,"%s",story[i]);
}
fclose(infh);
debug(5);

現在,只需對循環進行簡單的更改即可掃描故事,檢查審查(請檢查!),因此我們避免比較和打印空指針(您遇到的另一個問題),

for(i=0; i<100 && (story[i]); ++i)
{
    if(check(story[i])==1)
    {
        fprintf(outfh,"%s","censored"); fflush(outfh);
    }
    else
    {
        fprintf(outfh,"%s",story[i]); fflush(outfh);
    };
};

但是請注意,您確實不需要將故事讀入一個數組中,您可以一次閱讀一行,然后將這兩個循環打印在一起,就可以掃描任意大的文件,而無需分配大量空間,

for(i=0; 1; ++i)
{
    if(feof(infh)!=0) { break; };
    story[0]=malloc(sizeof(char [25]));
    fscanf(infh,"%s",story[0]);
    if(check(story[0])==1)
    {
        fprintf(outfh,"%s","censored"); fflush(outfh);
    }
    else
    {
        fprintf(outfh,"%s",story[0]); fflush(outfh);
    };
}
fclose(infh);
fclose(outfh);

您還需要確保只釋放分配的行,

for(i=0; list[i] && list<20; i++)
{
    free(list[i]);
}

這應該可以解決您的問題。


添加一個usage()函數,

void usage(char*progname)
{
    printf("need 3 files\n");
    printf("%s <restricted> <story> <censorted>\n",progname);
}

叫它

if( argc < 4 )
{
    usage(argv[0]);
    return 0;
}

無需猜測或在論壇中提問,只需運行調試器即可。 如果在Linux上運行,則gdb將帶您直接進入分段故障的位置。

假設您的應用程序名為“ foo”:

> gdb foo
# run

當它崩潰時:

# bt

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM