| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 1692 人关注过本帖, 3 人收藏
标题:程序开发流程
只看楼主 加入收藏
BlueGuy
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:29
帖 子:4476
专家分:4055
注 册:2009-4-18
结帖率:94.72%
收藏(3)
已结贴  问题点数:20 回复次数:22 
程序开发流程
Here's a development process I like to use. I'll use a program that counts letters, digits, punctuation, and whitespace in a file as an example. This was an answer to a question, but I was asked to turn it into a thread for reference.

1 - Start with a skeleton program:

Code:
#include <stdio.h>


int main( void ) {
  return 0;
}

2 - The big thing for this program is the source of the input, so I open and print a test file to make
sure that everything works:

Code:
#include <stdio.h>


int main( void ) {
  FILE *fp = fopen( "test.txt", "r" );

  if ( fp ) {
    int ch;

    while ( ( ch = fgetc( fp ) ) != EOF ) {
      fputc( ch, stdout );
    }

    fclose( fp );
  } else {
    perror( "error opening the file" );
  }

  return 0;
}

3 - Okay, the file opens and the program reads it like I think I want. Now I'll count all of the
characters and compare that with the actual file to see if it's accurate:

Code:
#include <stdio.h>


int main( void ) {
  FILE *fp = fopen( "test.txt", "r" );

  if ( fp ) {
    int ch;
    int n = 0;

    while ( ( ch = fgetc( fp ) ) != EOF ) {
      ++n;
    }

    printf( "total characters: %d\n", n );
    fclose( fp );
  } else {
    perror( "error opening the file" );
  }

  return 0;
}

4 - Now I'm sure that the file is being input the way I want, so I can start counting character types
 one at a time, checking each time that the count is right on a test file:

Code:
#include <stdio.h>
#include <ctype.h>


int main( void ) {
  FILE *fp = fopen( "test.txt", "r" );

  if ( fp ) {
    int ch;
    int nalpha = 0;
    int ndigit = 0;
    int npunct = 0;
    int nspace = 0;

    while ( ( ch = fgetc( fp ) ) != EOF ) {
      if ( isalpha( ch ) ) {
        ++nalpha;
      } else if ( isdigit( ch ) ) {
        ++ndigit;
      } else if ( ispunct( ch ) ) {
        ++npunct;
      } else if ( isspace( ch ) ) {
        ++nspace;
      }
    }

    printf( "alphabetic characters: %d\n", nalpha );
    printf( "digit characters: %d\n", ndigit );
    printf( "punctuation characters: %d\n", npunct );
    printf( "whitespace characters: %d\n", nspace );
    fclose( fp );
  } else {
    perror( "error opening the file" );
  }

  return 0;
}

5 - Testing is done on producing the output, but the file is still hard coded, and I want the user to
pass a file to the program. main is getting kind of long, so I'll refactor the counting code out into afunction and test it all again to make sure it still works. Any change, even something tiny, means retesting. Refactoring doesn't change the logic at all, it just restructures the program so that it's easier to manage but still works exactly the same:

Code:
#include <stdio.h>
#include <ctype.h>


void process_file( FILE *fp );


int main( void ) {
  FILE *fp = fopen( "test.txt", "r" );

  if ( fp ) {
    process_file( fp );
    fclose( fp );
  } else {
    perror( "error opening the file" );
  }

  return 0;
}


void process_file( FILE *fp ) {
  int ch;
  int nalpha = 0;
  int ndigit = 0;
  int npunct = 0;
  int nspace = 0;

  while ( ( ch = fgetc( fp ) ) != EOF ) {
    if ( isalpha( ch ) ) {
      ++nalpha;
    } else if ( isdigit( ch ) ) {
      ++ndigit;
    } else if ( ispunct( ch ) ) {
      ++npunct;
    } else if ( isspace( ch ) ) {
      ++nspace;
    }
  }

  printf( "alphabetic characters: %d\n", nalpha );
  printf( "digit characters: %d\n", ndigit );
  printf( "punctuation characters: %d\n", npunct );
  printf( "whitespace characters: %d\n", nspace );
}

6 - Now I can add the argument stuff for taking a file as a command line parameter without cluttering
main up too much. I make sure my tests touch every code path, so I'll fake error and stuff to make surethat the error cases work like I want:

Code:
#include <stdio.h>
#include <ctype.h>


void process_file( FILE *fp );


int main( int argc, char *argv[] ) {
  if ( argc > 1 ) {
    FILE *fp = fopen( argv[1], "r" );

    if ( fp ) {
      process_file( fp );
      fclose( fp );
    } else {
      perror( "error opening the file" );
    }
  } else {
    fprintf( stderr, "usage: prog <filename>\n" );
  }

  return 0;
}


void process_file( FILE *fp ) {
  int ch;
  int nalpha = 0;
  int ndigit = 0;
  int npunct = 0;
  int nspace = 0;

  while ( ( ch = fgetc( fp ) ) != EOF ) {
    if ( isalpha( ch ) ) {
      ++nalpha;
    } else if ( isdigit( ch ) ) {
      ++ndigit;
    } else if ( ispunct( ch ) ) {
      ++npunct;
    } else if ( isspace( ch ) ) {
      ++nspace;
    }
  }

  printf( "alphabetic characters: %d\n", nalpha );
  printf( "digit characters: %d\n", ndigit );
  printf( "punctuation characters: %d\n", npunct );
  printf( "whitespace characters: %d\n", nspace );
}

7 - Now I can really crank down on the stability of the code by adding defensive cases:

Code:
#include <stdio.h>
#include <ctype.h>


int process_file( FILE *fp );


int main( int argc, char *argv[] ) {
  if ( argc > 1 ) {
    FILE *fp = fopen( argv[1], "r" );

    if ( fp ) {
      if ( !process_file( fp ) ) {
        perror( "error reading from the file" );
      }

      fclose( fp );
    } else {
      perror( "error opening the file" );
    }
  } else {
    fprintf( stderr, "usage: prog <filename>\n" );
  }

  return 0;
}


int process_file( FILE *fp ) {
  int ch;
  int nalpha = 0;
  int ndigit = 0;
  int npunct = 0;
  int nspace = 0;
  int rc = 0;

  if ( fp != NULL ) {
    while ( ( ch = fgetc( fp ) ) != EOF ) {
      if ( isalpha( ch ) ) {
        ++nalpha;
      } else if ( isdigit( ch ) ) {
        ++ndigit;
      } else if ( ispunct( ch ) ) {
        ++npunct;
      } else if ( isspace( ch ) ) {
        ++nspace;
      }
    }

    if ( !ferror( fp ) ) {
      printf( "alphabetic characters: %d\n", nalpha );
      printf( "digit characters: %d\n", ndigit );
      printf( "punctuation characters: %d\n", npunct );
      printf( "whitespace characters: %d\n", nspace );
      rc = 1;
    }
  }

  return rc;
}

8 - Now the code is solid, but there aren't any comments, so I'll go through it and add comments to
places that might be confusing and then call it a day. There aren't many because this is a pretty simple program:

Code:
/*
  File - prog.c
  Author - D. Burke (Noir)
  
  Count alphabetic, digit, punctuation, and
  whitespace characters in a user supplied file
*/
#include <stdio.h>
#include <ctype.h>


int process_file( FILE *fp );


int main( int argc, char *argv[] ) {
  if ( argc > 1 ) {
    FILE *fp = fopen( argv[1], "r" );

    if ( fp ) {
      if ( !process_file( fp ) ) {
        // failure means a stream error or bad file
        perror( "error reading from the file" );
      }

      fclose( fp );
    } else {
      perror( "error opening the file" );
    }
  } else {
    fprintf( stderr, "usage: prog <filename>\n" );
  }

  return 0;
}


int process_file( FILE *fp ) {
  int ch;
  int nalpha = 0;
  int ndigit = 0;
  int npunct = 0;
  int nspace = 0;

  // assume failure
  int rc = 0;

  if ( fp != NULL ) {
    while ( ( ch = fgetc( fp ) ) != EOF ) {
      if ( isalpha( ch ) ) {
        ++nalpha;
      } else if ( isdigit( ch ) ) {
        ++ndigit;
      } else if ( ispunct( ch ) ) {
        ++npunct;
      } else if ( isspace( ch ) ) {
        ++nspace;
      }
    }

    if ( !ferror( fp ) ) {
      // only produce output if there are no errors
      printf( "alphabetic characters: %d\n", nalpha );
      printf( "digit characters: %d\n", ndigit );
      printf( "punctuation characters: %d\n", npunct );
      printf( "whitespace characters: %d\n", nspace );
      rc = 1;
    }
  }

  return rc;
}

That's how you should do it too. Start with a skeleton and build the program up bit by bit, making sureto test after every change. It's okay to change the requirements for testing like when I counted all the characters in the file or just printed the file out. It's okay to backtrack and change your mind on stuff too like when I decided to factor the counting code into a function. It's not as much building a program from a blueprint as it is evolving a program from an idea. You get to change your mind and make it better along the way even after you've finished doing it another way.
收到的鲜花
  • Devil_W2011-05-30 13:19 送鲜花  -3朵   附言:你这写的是个P啊,没做过项目还tmd写的跟真 ...
搜索更多相关主题的帖子: test return 程序开发 everything 
2011-05-27 10:08
木头lbj
Rank: 7Rank: 7Rank: 7
来 自:黄山
等 级:黑侠
威 望:1
帖 子:269
专家分:527
注 册:2010-11-6
收藏
得分:1 
拿走了  谢谢啊

。。。!!!)))000
2011-05-27 10:19
hellovfp
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:禁止访问
威 望:30
帖 子:2976
专家分:7697
注 册:2009-7-21
收藏
得分:1 
but , it is a single process, how to do the more?

我们都在路上。。。。。
2011-05-27 10:22
BlueGuy
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:29
帖 子:4476
专家分:4055
注 册:2009-4-18
收藏
得分:0 
我最近在写一个工程量稍大一点的简单游戏,估计半年可以完成,
本想找一些志同道合的图形爱好者一起完成,可是因为大家的编程风格不尽相同,
还有就是某些人竟然还再用那种最原始的图形库,唉,悲剧,不说了...。
所以这个工程只能由我自己慢慢来了。

[ 本帖最后由 BlueGuy 于 2011-5-27 12:10 编辑 ]

我就是真命天子,顺我者生,逆我者死!
2011-05-27 11:44
qq1023569223
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:湖南科技大学
等 级:贵宾
威 望:26
帖 子:2753
专家分:13404
注 册:2010-12-22
收藏
得分:1 
I hate English!

   唯实惟新 至诚致志
2011-05-27 13:43
liangjinchao
Rank: 7Rank: 7Rank: 7
等 级:黑侠
帖 子:376
专家分:697
注 册:2010-11-8
收藏
得分:1 
看到这篇文章,我只是想起了我的英语!

因为有了因为,所以有了所以,既然已成既然,何必再说何必
2011-05-27 14:50
起点de崛起
Rank: 1
来 自:神州
等 级:新手上路
帖 子:5
专家分:1
注 册:2011-5-27
收藏
得分:1 
兄弟 有中文吗?   我有点看不懂      怎么样才能搞明白

虚心诚学
2011-05-27 15:40
烟雾中的迷茫
Rank: 9Rank: 9Rank: 9
等 级:蜘蛛侠
帖 子:621
专家分:1069
注 册:2011-2-9
收藏
得分:1 
yes,these code is a little difficult for me to understand in some way,but i believe i will catch up with  you later,because i like challenge,i think you too; that's right?  so,i  really want to get you advice when i was get into troubles and communicate with you.finally, Best wishes to you!
2011-05-27 16:43
gupiao175
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:40
帖 子:1787
专家分:7527
注 册:2007-6-27
收藏
得分:1 
楼主想写什么游戏?

那个英文我真看不太懂!

Q:1428196631,百度:开发地 即可找到我,有事请留言!
2011-05-27 21:48
yang0401
Rank: 2
等 级:论坛游民
帖 子:84
专家分:57
注 册:2011-5-23
收藏
得分:1 
初学者问下这里面好像多次出现了int main()          c语言不是规定一个程序只能有且只有一个主函数吗???????不懂中!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!1
2011-05-28 02:36
快速回复:程序开发流程
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.024270 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved