请求批评第一个程序 [英] Request critique of first program

查看:55
本文介绍了请求批评第一个程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述




我是C的新手,非常感谢以下

程序,asplit,将文件拆分为2的任何反馈新文件,在第一个文件中放置

一定数量的行,其余在

第二个文件中。


任何关于不可移植性,风格不合理,直接

错误或任何其他内容的评论都会非常感激。


使用gcc 4.1编译好。 2,和--std = c99 -pedantic -Wall,

没有警告,似乎工作。


有两个文件,一个标题和一个源文件。


##开始asplit.h ##


#ifndef ASPLIT_H_

#define ASPLIT_H_


enum e_status {SUCCESS,ERROR_FILE_INPUT,ERROR_FILE_OUTPUT_A,

ERROR_FILE_OUTPUT_B};


typedef enum e_status status;


typedef struct {

int status;

long int num_rem_lines;

} aspl it_result;


/ **

*不对称地将名为in_file的文件拆分为2个文件,out_file_a,



* out_file_b,将

中的num_lines(必须是非负)行放在第一个

*文件中,其余的放在第二个文件中。

*

*任何文件名都可以是 - ,表示在

in_file的情况下stdin,
$ b $在out_file_a或out_file_b的情况下为b *或stdout。

*

*返回指向asplit_result结构的指针(除非无法分配
) ,

*在这种情况下它返回NULL),显示成功或失败,并且



*包含在第2行中的行数文件如果成功。

*可能的状态值由

中的e_status枚举给出

*头文件。成功表示成功,并且每个3

不同的

*失败状态由其中一个枚举值表示

with

* ERROR_,表示哪个文件无法打开。

*

*如果状态为SUCCESS,则num_rem_lines值表示

*填写第一个文件后剩余的行数,

*所有这些都输入到第二个文件中。

*

*客户负责结果的内存管理

struct。

*

* /

asplit_result * asplit(const char * in_file,const char * out_file_a,

const char * out_file_b,

const long int num_lines);


#endif / * ASPLIT_H _ * /


##结束asplit.h ##


##开始asplit。 c ##


#include< stdio.h>

#include< stdlib.h>


#include< string.h>


#include< getopt.h>


#include" asplit.h"

char * copy_string(const char * const s);


int close_file(FILE * f);


FILE * open_infile(const char * fname);


FILE * open_outfile(const char * fname);


/ *调用程序的名称。 * /

char * program_name;


void usage(int status){


if(status!= EXIT_SUCCESS)

fprintf(stderr,试试'%s -h''获取更多信息。\ n,

program_name);

else {

printf(

" \ n\

用法:%s [选项] -i IN_FILE -a OUT_FILE_A -b OUT_FILE_B -n NUM_LINES

\ n \ n \

",

program_name);

puts(" \

将IN_FILE不对称地分成2个文件,将第一个NUM_LINES

\ n \

放入OUT_FILE_A其余的进入OUT_FILE_B. \ n \

\ n \

-i输入文件,IN_FILE \ n \

-第一个输出文件的名称,OUT_FILE_A \ n \

-b第二个输出文件的名称,OUT_FILE_B \ n \

-n数量要放的线在OUT_FILE_A \ n \

\ n \

-h显示此帮助并退出\ n \

-v详细输出\ n \

");

put(&\\; \

\ n \

当IN_FILE是 - 时,使用标准输入;当OUT_FILE_A或OUTFILE_B是

- ,\ n \

使用标准输出。\ n \\ n

");

printf(

" \

\ n \

示例:\ n \ n \

%s -n 100 -i - -a output1 -b output2 \ n \

从标准输入读取,将前100行写入output1

文件和\ n \

以下所有行到output2.\\\
\\\
\

%s -n 1000 -i infile.txt -a output1.txt -b -\\\
\

从infile.txt读取,将前1000行写入

output1.txt和\ n \

以下所有行到标准输出。\ n \ n \\ n \ n

%s -n 1 -i - -a - -b -\ n $ \\

将标准输入复制到标准输出。\ n \ n \\ n \ n

\ n",

program_name,program_name ,

program_name);

put(成功时为\\\
Retetns 0,失败时为1。#n);

printf(" \\\
Report bug to cs ******* *****@protempore.net

\ n \ nn");

}

退出(状态);

}


asplit_result * asplit(const char * in_file,const char * out_file_a,

const char * out_file_b ,

const long int num_lines){


long int curr_line_num;

int curr_chr;

FILE * in_f,* out_f;

asplit_result *结果;


size_t size = sizeof(asplit_result);

result = malloc (size);

if(result == NULL){

返回NULL;

}否则{

结果 - > num_rem_lines = 0;

}


/ *如果不是 - 打开in_file,如果不能则返回失败

打开。 * /

if((in_f = open_infile(in_file))== NULL){

result-> status = ERROR_FILE_INPUT;

return结果;

}


/ *如果num_lines为0,则第一个文件中没有任何内容。* /

if( num_lines == 0){

/ *

*如果没有打开第二个文件 - ,返回

失败

*如果无法打开。

* /

if((out_f = open_outfile(out_file_b))== NULL){

close_file(in_f);

result-> status = ERROR_FILE_OUTPUT_B;

返回结果;

}

} else {

/ *

*如果num_lines大于0,则打开第一个

文件,返回

*如果无法打开则失败。

* /

if((out_f = open_outfile(out_file_a))== NULL){

close_file(in_f);

result-> status = ERROR_FILE_OUTPUT_A;

返回结果;

}

}


/ *初始l ine number为0,并在每个换行符后递增

。 * /

curr_line_num = 0;


/ *虽然输入文件仍有字符:* /

while((curr_chr = getc(in_f))!= EOF){


/ *输出char到当前输出文件。 * /

putc(curr_chr,out_f);


/ *

*如果我们读取换行符,如果我们'在第一个文件允许的时候,我们必须关闭第一个

文件,并且

*打开第二个文件,如果

无法打开则返回失败。

* /

if(curr_chr ==''\\ \\ n''&& ++ curr_line_num == num_lines){

close_file(out_f);

if((out_f = open_outfile(out_file_b))==

NULL){

close_file(in_f);

result-> status = ERROR_FILE_OUTPUT_B;

返回结果;

}

}

}

/ *如有必要,关闭输入和输出文件。 * /

close_file(in_f);

close_file(out_f);


/ *返回输出到的行数第二个档案。 * /

result-> status = 0;

result-> num_rem_lines =(curr_line_num< num_lines)? 0:

(curr_line_num - num_lines);

返回结果;


}


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


program_name = * argv;


char * input_file = NULL;

char * output_file_a = NULL;

char * output_file_b = NULL;


int num_lines = -1;

int verbose = 0;

asplit_result * result = NULL;


int ich;


while ((ich = getopt(argc,argv," hvi:a:b:n:"))!= EOF){

switch(ich){

case''h'':

用法(0);

休息;

case''我':

input_file =(char *)copy_string(optarg);

break;

case''a'':

output_file_a =( char *)copy_string(optarg);

break;

case''b'':

output_file_b =(char *)copy_string(optarg );

休息;

案例''n'':

num_lines = atoi(optarg) ;

if(num_lines< 0)

printf(" -n arg必须至少为0,而不是

休息;

case''v'':

verbose = 1;

休息;

默认:

使用(1);

休息;

}

}


/ *验证是否已提交所有必需参数。 * /

if(input_file == NULL || output_file_a == NULL || output_file_b

== NULL

|| num_lines< 0 )

用法(1);

/ *做实际拆分。 * /

result = asplit(input_file,output_file_a,output_file_b,

num_lines);


if(result == NULL) {

fprintf(stderr,错误:asplit返回NULL结果。);

退出(1);

}


/ *确定它是否成功终止,并相应处理

。 * /

开关(结果 - >状态){

案例成功:

if(verbose)

printf("输出%li行到第二个文件。\ n,

result-> num_rem_lines);

退出(0);

case ERROR_FILE_INPUT:

fprintf(stderr,无法打开输入文件:%s \ n,

input_file);

exit(1);

case ERROR_FILE_OUTPUT_A:

fprintf(stderr,无法打开输出文件:%s \ n,

output_file_a);

exit(1);

case ERROR_FILE_OUTPUT_B:

fprintf(stderr,无法打开输出文件: %s \ n",

output_file_b);

退出(1);

默认值:

fprintf (stderr,错误:意外返回值%d \ n,结果 -

Hi,

I''m new to C and would appreciate any feedback on the following
program, asplit, which splits a file into 2 new files, putting a
certain number of lines in the first file, and all the rest in the
second file.

Any comments as to non-portability, stylistic infelicities, outright
bugs or anything else would be very much appreciated.

It compiles fine using gcc 4.1.2, and --std=c99 -pedantic -Wall, with
no warnings, and seems to work.

There are two files, a header and a source file.

## Begin asplit.h ##

#ifndef ASPLIT_H_
#define ASPLIT_H_

enum e_status { SUCCESS, ERROR_FILE_INPUT, ERROR_FILE_OUTPUT_A,
ERROR_FILE_OUTPUT_B };

typedef enum e_status status;

typedef struct {
int status;
long int num_rem_lines;
} asplit_result;

/**
* Asymmetrically splits file named in_file into 2 files, out_file_a,
and
* out_file_b, putting num_lines (must be non-negative) lines in the
first
* file, and the rest in the second file.
*
* Any of the filenames may be "-", indicating stdin in the case of
in_file,
* or stdout in the case of out_file_a or out_file_b.
*
* Returns a pointer to an asplit_result struct (unless unable to
allocate,
* in which case it returns NULL), which shows success or failure and
the
* number of lines that were included in 2nd file if successful.
* Possible status values are given by the e_status enumeration in
this
* header file. Success is indicated by SUCCESS, and each of the 3
different
* failure states is indicated by one of the enum values beginning
with
* ERROR_, indicating which file was unable to be opened.
*
* If the status is SUCCESS, then the num_rem_lines value indicates
* the number of lines remaining after the first file was filled,
* all of which were entered into the second file.
*
* The client is responsible for memory management of the result
struct.
*
*/
asplit_result * asplit(const char *in_file, const char *out_file_a,
const char *out_file_b,
const long int num_lines);

#endif /*ASPLIT_H_*/

## End asplit.h ##

## Begin asplit.c ##

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

#include <string.h>

#include <getopt.h>

#include "asplit.h"

char *copy_string(const char *const s);

int close_file(FILE * f);

FILE * open_infile(const char * fname);

FILE * open_outfile(const char *fname);

/* Name under which program was invoked. */
char *program_name;

void usage(int status) {

if (status != EXIT_SUCCESS)
fprintf(stderr, "Try `%s -h'' for more information.\n",
program_name);
else {
printf(
"\n\
Usage: %s [OPTION] -i IN_FILE -a OUT_FILE_A -b OUT_FILE_B -n NUM_LINES
\n\n\
",
program_name);
puts("\
Asymmetrically split IN_FILE into 2 files, putting the first NUM_LINES
\n\
into OUT_FILE_A and the rest into OUT_FILE_B.\n\
\n\
-i input file, IN_FILE\n\
-a name of first output file, OUT_FILE_A\n\
-b name of second output file, OUT_FILE_B\n\
-n the number of lines to put in OUT_FILE_A\n\
\n\
-h display this help and exit\n\
-v verbose output\n\
");
puts("\
\n\
When IN_FILE is -, use standard input; when OUT_FILE_A or OUTFILE_B is
-,\n\
use standard output.\n\
");
printf(
"\
\n\
Examples:\n\n\
%s -n 100 -i - -a output1 -b output2\n\
Read from standard input, writing first 100 lines to output1
file and\n\
all following lines to output2.\n\n\
%s -n 1000 -i infile.txt -a output1.txt -b -\n\
Read from infile.txt, writing the first 1000 lines to
output1.txt and\n\
all following lines to standard output.\n\n\
%s -n 1 -i - -a - -b -\n\
Copy standard input to standard output.\n\n\
\n",
program_name, program_name,
program_name);
puts("\nReturns 0 on success, and 1 on failure.\n");
printf("\nReport bugs to cs************@protempore.net.
\n\n");
}
exit(status);
}

asplit_result * asplit(const char *in_file, const char *out_file_a,
const char *out_file_b,
const long int num_lines) {

long int curr_line_num;
int curr_chr;
FILE *in_f, *out_f;
asplit_result *result;

size_t size = sizeof(asplit_result);
result = malloc(size);
if (result == NULL) {
return NULL;
} else {
result->num_rem_lines = 0;
}

/* Open in_file if not "-", returning unsuccessfully if unable
to open. */
if ((in_f = open_infile(in_file)) == NULL) {
result->status = ERROR_FILE_INPUT;
return result;
}

/* If num_lines is 0, then nothing goes into the first file.*/
if (num_lines == 0) {
/*
* So open second file if not "-", returning
unsuccessfully
* if unable to open.
*/
if ((out_f = open_outfile(out_file_b)) == NULL) {
close_file(in_f);
result->status = ERROR_FILE_OUTPUT_B;
return result;
}
} else {
/*
* If num_lines is greater than 0, then open first
file, returning
* unsuccessfully if unable to open.
*/
if ((out_f = open_outfile(out_file_a)) == NULL) {
close_file(in_f);
result->status = ERROR_FILE_OUTPUT_A;
return result;
}
}

/* Initial line number is 0, and increments after each newline
is read. */
curr_line_num = 0;

/* While input file still has characters: */
while ((curr_chr = getc(in_f)) != EOF) {

/* Output char to current output file. */
putc(curr_chr, out_f);

/*
* If we read a newline, and if we''ve just hit the
maximum
* allowed in the first file, we must close the first
file, and
* open the second file, returning unsuccessfully if
unable to open.
*/
if (curr_chr == ''\n''&& ++curr_line_num == num_lines) {
close_file(out_f);
if ((out_f = open_outfile(out_file_b)) ==
NULL) {
close_file(in_f);
result->status = ERROR_FILE_OUTPUT_B;
return result;
}
}
}
/* Close input and output files if necessary. */
close_file(in_f);
close_file(out_f);

/* Return the number of lines output to the second file. */
result->status = 0;
result->num_rem_lines = (curr_line_num < num_lines) ? 0 :
(curr_line_num - num_lines);
return result;

}

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

program_name = *argv;

char *input_file = NULL;
char *output_file_a = NULL;
char *output_file_b = NULL;

int num_lines = -1;
int verbose = 0;
asplit_result *result = NULL;

int ich;

while ((ich = getopt(argc, argv, "hvi:a:b:n:")) != EOF) {
switch (ich) {
case ''h'':
usage(0);
break;
case ''i'':
input_file = (char *) copy_string(optarg);
break;
case ''a'':
output_file_a = (char *) copy_string(optarg);
break;
case ''b'':
output_file_b = (char *) copy_string(optarg);
break;
case ''n'':
num_lines = atoi(optarg);
if (num_lines < 0)
printf("-n arg must be at least 0, not
%d.\n", num_lines);
break;
case ''v'':
verbose = 1;
break;
default:
usage(1);
break;
}
}

/* Verify that all required arguments were submitted. */
if (input_file == NULL|| output_file_a == NULL|| output_file_b
== NULL
|| num_lines < 0)
usage(1);
/* Do the actual split. */
result = asplit(input_file, output_file_a, output_file_b,
num_lines);

if (result == NULL) {
fprintf(stderr, "Error: asplit returned NULL result.");
exit(1);
}

/* Determine whether it terminated successfully, and handle
accordingly. */
switch (result->status) {
case SUCCESS:
if (verbose)
printf("Output %li lines to 2nd file.\n",
result->num_rem_lines);
exit(0);
case ERROR_FILE_INPUT:
fprintf(stderr, "Unable to open input file: %s\n",
input_file);
exit(1);
case ERROR_FILE_OUTPUT_A:
fprintf(stderr, "Unable to open output file: %s\n",
output_file_a);
exit(1);
case ERROR_FILE_OUTPUT_B:
fprintf(stderr, "Unable to open output file: %s\n",
output_file_b);
exit(1);
default:
fprintf(stderr, "Error: unexpected return value %d\n", result-


> status);
>status);



退出(1);

}


}

/ **

*创建给定指针引用的字符串的副本,

返回

*指向新创建的副本,如果无法malloc,则为NULL

内存

*副本或原始指针为null或字符串为空。

*

*客户负责新字符串的内存管理。

* /

char * copy_string(const char * str_orig) {$ / $

char * str_copy = NULL;


if(str_orig!= NULL&& * str_orig!= 0){<

size_t size = strlen(str_orig)+ 1;


str_copy = malloc(size);


if(str_copy != NULL)

memcpy(str_copy,str_orig,size);

}


返回str_copy;


}


/ **

*关闭给定文件指针引用的文件,如果它不是


之一
*标准系统文件。

*

*如果文件实际关闭则返回0,如果未关闭则返回1

* /

int close_file(FILE * f){

if(f!= stdin&& f!= stdout&& f!= stderr){

fclose(f);

返回0;

}

返回1;

}


/ **

*打开给定指针引用的输入文件(模式''r'') ,

*返回指向FILE的指针。如果fname是 - ,则返回stdin。

* /

FILE * open_infile(const char * const fname){

return strcmp(fname," - ")== 0? stdin:fopen(fname," r");

}


/ **

*打开输出文件(模式''w'')由给定指针引用,

*返回指向FILE的指针。如果fname是 - ,则返回stdout。

* /

FILE * open_outfile(const char * const fname){

return strcmp(fname," - ")== 0? stdout:fopen(fname," w");

}


##结束asplit.c ##


我已经浏览了常见问题解答,发现了一些需要改进的事情,

我已经做过了,但是我们还会感激任何额外的反馈。


干杯,


calvin

exit(1);
}

}

/**
* Create a copy of the string referenced by the given pointer,
returning
* a pointer to the newly created copy, or NULL if unable to malloc
memory
* for the copy or original pointer was null or the string was empty.
*
* The client is responsible for memory management of the new string.
*/
char *copy_string(const char *str_orig) {

char *str_copy = NULL;

if (str_orig != NULL && *str_orig != 0) {
size_t size = strlen(str_orig) + 1;

str_copy = malloc(size);

if (str_copy != NULL)
memcpy(str_copy, str_orig, size);
}

return str_copy;

}

/**
* Close the file referenced by the given file pointer if it is not
one of
* the standard system files.
*
* Returns 0 if the file was actually closed, and 1 if not closed
*/
int close_file(FILE * f) {
if (f != stdin&& f != stdout&& f != stderr) {
fclose(f);
return 0;
}
return 1;
}

/**
* Open the input file (mode ''r'') referenced by the given pointer,
* returning a pointer to the FILE. If fname is "-", return stdin.
*/
FILE * open_infile(const char *const fname) {
return strcmp(fname, "-") == 0 ? stdin : fopen(fname, "r");
}

/**
* Open the output file (mode ''w'') referenced by the given pointer,
* returning a pointer to the FILE. If fname is "-", return stdout.
*/
FILE * open_outfile(const char *const fname) {
return strcmp(fname, "-") == 0 ? stdout : fopen(fname, "w");
}

## End asplit.c ##

I did browse the FAQ already and found a couple of things to improve,
which I already did, but any additional feedback would be appreciated.

Cheers,

calvin

推荐答案

哎哟,我希望谷歌小组有一个预览。我立即看到我已经混合了标签和空格,因此代码看起来很糟糕。我很抱歉没有

首先捕获它。

Ouch, I wish google groups had a preview. I see immediately that I''ve
mixed tabs and spaces, so the code looks awful. My apologies for not
catching that first.


这是源文件,所有选项卡都更改为空格,所以我希望它现在干净利落地兑现

#include< stdio.h>

#include< stdlib.h>


#include< string.h>


#include< getopt.h>


#include" asplit.h"

char * copy_string(const char * const s);


int close_file(FILE * f );


FILE * open_infile(const char * fname);


FILE * open_outfile(const char * fname);


/ *调用程序的名称。 * /

char * program_name;


void usage(int status){


if(status!= EXIT_SUCCESS)

fprintf(stderr,试试'%s -h''获取更多信息。\ n,

program_name);

else {

printf(" \ n\

用法:%s [选项] -i IN_FILE -a OUT_FILE_A -b OUT_FILE_B -n NUM_LINES

\ nn \ n \

",program_name);

puts(&\\; \

不对称地将IN_FILE拆分为2个文件,将第一个NUM_LINES

\ n \

放入OUT_FILE_A,其余放入OUT_FILE_B. \ n \

\ n \

-i输入文件,IN_FILE \ n \

- 第一个输出文件的名称,OUT_FILE_A \ n \\ n br />
-b第二个输出文件的名称,OUT_FILE_B \ n \

-n要放入OUT_FILE_A \ n的行数\\ / $
\ n \

-h显示此帮助并退出\ n \

-v verbose output\\\
\\ \\

");

put(&\\; \

\ n \

当IN_FILE是 - ,使用标准输入;当OUT_FILE_A或OUTFILE_B是

- ,\ n \

使用标准输出。\ n \\ n

");

printf(" \

\ n \

示例:\ n\\\
\

%s -n 100 -i - -a output1 -b output2 \ n \

从标准输入读取,将前100行写入output1

文件和$ \\ n
以下所有行都输出。\ n \\ n \\ n \\ n \\ n \\ n \\ n \\ n

%s -n 1000 -i infile.txt -a output1.txt -b -\\\
\

从infile.txt读取,将前1000行写入

output1.txt和\ n \

以下所有行到标准输出。\ n \ n \\ n \\ n \\ n \\ n

%s -n 1 -i - -a - -b -\\\
\

将标准输入复制到标准输出。\ n \ n \\ n \\ n \\ n>
\ n",program_name,program_name,program_name);

puts(" \\\
Returns 0表示成功,1表示失败。\ n");

printf(" \ nnRe将错误移至 cs************@protempore.net 。$ \\ nn \\ nn;);

}

退出(状态);

}


asplit_result * asplit(const char * in_file,const char * out_file_a,

const char * out_file_b,const long int

num_lines){


long int curr_line_num;

int curr_chr;

FILE * in_f,* out_f;

asplit_result * result;


size_t size = sizeof(asplit_result);

result = malloc(size);

if(result == NULL){

返回NULL;

} else {

result-> num_rem_lines = 0;

}


/ *如果没有打开in_file - ,如果无法打开
则返回失败。 * /

if((in_f = open_infile(in_file))== NULL){

result-> status = ERROR_FILE_INPUT;

return结果;

}


/ *如果num_lines为0,则第一个文件中没有任何内容。* /

if( num_lines == 0){

/ *

*如果没有打开第二个文件 - ,则返回失败

*如果无法打开。

* /

if((out_f = open_outfile(out_file_b))== NULL){

close_file(in_f);

result-> status = ERROR_FILE_OUTPUT_B;

返回结果;

}

}其他{

/ *

*如果num_lines大于0,则打开第一个文件,

返回

*如果无法打开则失败。

* /

if((out_f = open_outfile(out_file_a))== NULL){

close_file(in_f);

result-> status = ERROR_FILE_OUTPUT_A;

返回结果;

}

}


/ *初始行号是0,并在每个换行符后递增

char。 * /

curr_line_num = 0;


/ *虽然输入文件仍有字符:* /

while((curr_chr = getc(in_f))!= EOF){


/ *输出char到当前输出文件。 * /

putc(curr_chr,out_f);


/ *

*如果我们读取换行符,如果我们' '刚刚达到最大值

*允许在第一个文件中,我们必须关闭第一个文件,



*打开第二个文件如果无法打开
,则返回失败。

* /

if(curr_chr ==''\ n''&& ++ curr_line_num == num_lines){

close_file(out_f);

if((out_f = open_outfile(out_file_b))== NULL){

close_file(in_f);

result-> status = ERROR_FILE_OUTPUT_B;

返回结果;

}

}

}

/ *如有必要,关闭输入和输出文件。 * /

close_file(in_f);

close_file(out_f);


/ *返回输出到的行数第二个档案。 * /

result-> status = 0;

if(curr_line_num< num_lines)

result-> num_rem_lines = 0;

else

result-> num_rem_lines = curr_line_num - num_lines;


返回结果;


}


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


program_name = * argv;


char * input_file = NULL;

char * output_file_a = NULL;

char * output_file_b = NULL;


int num_lines = -1;

int verbose = 0;

asplit_result * result = NULL;


int ich ;(&ich = getopt(argc,argv," hvi:a:b:n:"))!= EOF){

开关(ich){

case''h'':

用法(0);

休息;

case''我'':

input_file =(char *)copy_string(optarg);

break;

case''a '':

output_file_a =(char *)copy_string(optarg);

break;

case''b'':

output_file_b =(char *)copy_string(optarg);

break;

case' 'n'':

num_lines = atoi(optarg);

if(num_lines< 0)

printf(" -n arg必须至少为0,而不是%d。\ n",

num_lines);

break;

case''v'':

verbose = 1;

break;

默认值:

使用(1);

休息;

}

}


/ *验证是否已提交所有必需参数。 * /

if(input_file == NULL || output_file_a == NULL || output_file_b

== NULL

|| num_lines< 0 )

用法(1);

/ *做实际拆分。 * /

result = asplit(input_file,output_file_a,output_file_b,

num_lines);


if(result == NULL) {

fprintf(stderr,错误:asplit返回NULL结果。);

退出(1);

}


/ *确定它是否成功终止,并相应处理

。* /

switch(result-> status){

案例成功:

if(verbose)

printf(" Output%li lines to 2nd file.\ n,result-
Here is the source file with all tabs changed to spaces, so I hope it
renders cleanly now:

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

#include <string.h>

#include <getopt.h>

#include "asplit.h"

char *copy_string(const char *const s);

int close_file(FILE * f);

FILE * open_infile(const char * fname);

FILE * open_outfile(const char *fname);

/* Name under which program was invoked. */
char *program_name;

void usage(int status) {

if (status != EXIT_SUCCESS)
fprintf(stderr, "Try `%s -h'' for more information.\n",
program_name);
else {
printf("\n\
Usage: %s [OPTION] -i IN_FILE -a OUT_FILE_A -b OUT_FILE_B -n NUM_LINES
\n\n\
", program_name);
puts("\
Asymmetrically split IN_FILE into 2 files, putting the first NUM_LINES
\n\
into OUT_FILE_A and the rest into OUT_FILE_B.\n\
\n\
-i input file, IN_FILE\n\
-a name of first output file, OUT_FILE_A\n\
-b name of second output file, OUT_FILE_B\n\
-n the number of lines to put in OUT_FILE_A\n\
\n\
-h display this help and exit\n\
-v verbose output\n\
");
puts("\
\n\
When IN_FILE is -, use standard input; when OUT_FILE_A or OUTFILE_B is
-,\n\
use standard output.\n\
");
printf("\
\n\
Examples:\n\n\
%s -n 100 -i - -a output1 -b output2\n\
Read from standard input, writing first 100 lines to output1
file and\n\
all following lines to output2.\n\n\
%s -n 1000 -i infile.txt -a output1.txt -b -\n\
Read from infile.txt, writing the first 1000 lines to
output1.txt and\n\
all following lines to standard output.\n\n\
%s -n 1 -i - -a - -b -\n\
Copy standard input to standard output.\n\n\
\n", program_name, program_name, program_name);
puts("\nReturns 0 on success, and 1 on failure.\n");
printf("\nReport bugs to cs************@protempore.net.\n\n");
}
exit(status);
}

asplit_result * asplit(const char *in_file, const char *out_file_a,
const char *out_file_b, const long int
num_lines) {

long int curr_line_num;
int curr_chr;
FILE *in_f, *out_f;
asplit_result *result;

size_t size = sizeof(asplit_result);
result = malloc(size);
if (result == NULL) {
return NULL;
} else {
result->num_rem_lines = 0;
}

/* Open in_file if not "-", returning unsuccessfully if unable to
open. */
if ((in_f = open_infile(in_file)) == NULL) {
result->status = ERROR_FILE_INPUT;
return result;
}

/* If num_lines is 0, then nothing goes into the first file.*/
if (num_lines == 0) {
/*
* So open second file if not "-", returning unsuccessfully
* if unable to open.
*/
if ((out_f = open_outfile(out_file_b)) == NULL) {
close_file(in_f);
result->status = ERROR_FILE_OUTPUT_B;
return result;
}
} else {
/*
* If num_lines is greater than 0, then open first file,
returning
* unsuccessfully if unable to open.
*/
if ((out_f = open_outfile(out_file_a)) == NULL) {
close_file(in_f);
result->status = ERROR_FILE_OUTPUT_A;
return result;
}
}

/* Initial line number is 0, and increments after each newline
char. */
curr_line_num = 0;

/* While input file still has characters: */
while ((curr_chr = getc(in_f)) != EOF) {

/* Output char to current output file. */
putc(curr_chr, out_f);

/*
* If we read a newline, and if we''ve just hit the maximum
* allowed in the first file, we must close the first file,
and
* open the second file, returning unsuccessfully if unable to
open.
*/
if (curr_chr == ''\n''&& ++curr_line_num == num_lines) {
close_file(out_f);
if ((out_f = open_outfile(out_file_b)) == NULL) {
close_file(in_f);
result->status = ERROR_FILE_OUTPUT_B;
return result;
}
}
}
/* Close input and output files if necessary. */
close_file(in_f);
close_file(out_f);

/* Return the number of lines output to the second file. */
result->status = 0;
if (curr_line_num < num_lines)
result->num_rem_lines = 0;
else
result->num_rem_lines = curr_line_num - num_lines;

return result;

}

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

program_name = *argv;

char *input_file = NULL;
char *output_file_a = NULL;
char *output_file_b = NULL;

int num_lines = -1;
int verbose = 0;
asplit_result *result = NULL;

int ich;

while ((ich = getopt(argc, argv, "hvi:a:b:n:")) != EOF) {
switch (ich) {
case ''h'':
usage(0);
break;
case ''i'':
input_file = (char *) copy_string(optarg);
break;
case ''a'':
output_file_a = (char *) copy_string(optarg);
break;
case ''b'':
output_file_b = (char *) copy_string(optarg);
break;
case ''n'':
num_lines = atoi(optarg);
if (num_lines < 0)
printf("-n arg must be at least 0, not %d.\n",
num_lines);
break;
case ''v'':
verbose = 1;
break;
default:
usage(1);
break;
}
}

/* Verify that all required arguments were submitted. */
if (input_file == NULL || output_file_a == NULL || output_file_b
== NULL
|| num_lines < 0)
usage(1);
/* Do the actual split. */
result = asplit(input_file, output_file_a, output_file_b,
num_lines);

if (result == NULL) {
fprintf(stderr, "Error: asplit returned NULL result.");
exit(1);
}

/* Determine whether it terminated successfully, and handle
accordingly.*/
switch (result->status) {
case SUCCESS:
if (verbose)
printf("Output %li lines to 2nd file.\n", result-

> num_rem_lines);
>num_rem_lines);



exit(0);

case ERROR_FILE_INPUT:

fprintf(stderr,无法打开输入file:%s \ n",

input_file);

exit(1);

case ERROR_FILE_OUTPUT_A:

fprintf(stderr,无法打开输出文件:%s \ n,

output_file_a);

退出(1);

case ERROR_FILE_OUTPUT_B:

fprintf(stderr,无法打开输出文件:%s \ n,

output_file_b);

退出(1);

默认值:

fprintf(stderr,错误:意外返回值:%d \ n,

结果 - >状态);

退出(1);

}


}


/ **

*创建给定指针引用的字符串的副本,

返回

*指针到新创建的副本,如果无法malloc,则为NULL

内存

*副本或原始指针为null或字符串为空。 />
*

*客户负责新字符串的内存管理。

* /

char * copy_string( const char * str_orig){


char * str_copy = NULL;


if(str_orig!= NULL&& * str_orig!= 0){

size_t size = strlen(str_orig)+ 1;


str_copy = malloc(size);


if(str_copy!= NULL)

memcpy(str_copy,str_orig,size);

}


返回str_copy;


}


/ **

*关闭给定文件指针引用的文件如果不是

其中一个

*标准系统文件。

*

*如果是,则返回0文件实际上是关闭的,如果没有关闭则为1

* /

int close_file(FILE * f){

if(f!= stdin& ;& f!= stdout&& f!= stderr){

fclose(f);

返回0;

}

返回1;

}


/ **

*打开输入文件(模式' 'r'')由给定指针引用,

*返回指向FILE的指针。如果fname是 - ,则返回stdin。

* /

FILE * open_infile(const char * const fname){

return strcmp(fname," - ")== 0? stdin:fopen(fname," r");

}


/ **

*打开输出文件(模式''w'')由给定指针引用,

*返回指向FILE的指针。如果fname是 - ,则返回stdout。

* /

FILE * open_outfile(const char * const fname){

return strcmp(fname," - ")== 0? stdout:fopen(fname," w");

}

exit(0);
case ERROR_FILE_INPUT:
fprintf(stderr, "Unable to open input file: %s\n",
input_file);
exit(1);
case ERROR_FILE_OUTPUT_A:
fprintf(stderr, "Unable to open output file: %s\n",
output_file_a);
exit(1);
case ERROR_FILE_OUTPUT_B:
fprintf(stderr, "Unable to open output file: %s\n",
output_file_b);
exit(1);
default:
fprintf(stderr, "Error: unexpected return value: %d\n",
result->status);
exit(1);
}

}

/**
* Create a copy of the string referenced by the given pointer,
returning
* a pointer to the newly created copy, or NULL if unable to malloc
memory
* for the copy or original pointer was null or the string was empty.
*
* The client is responsible for memory management of the new string.
*/
char *copy_string(const char *str_orig) {

char *str_copy = NULL;

if (str_orig != NULL && *str_orig != 0) {
size_t size = strlen(str_orig) + 1;

str_copy = malloc(size);

if (str_copy != NULL)
memcpy(str_copy, str_orig, size);
}

return str_copy;

}

/**
* Close the file referenced by the given file pointer if it is not
one of
* the standard system files.
*
* Returns 0 if the file was actually closed, and 1 if not closed
*/
int close_file(FILE * f) {
if (f != stdin&& f != stdout&& f != stderr) {
fclose(f);
return 0;
}
return 1;
}

/**
* Open the input file (mode ''r'') referenced by the given pointer,
* returning a pointer to the FILE. If fname is "-", return stdin.
*/
FILE * open_infile(const char *const fname) {
return strcmp(fname, "-") == 0 ? stdin : fopen(fname, "r");
}

/**
* Open the output file (mode ''w'') referenced by the given pointer,
* returning a pointer to the FILE. If fname is "-", return stdout.
*/
FILE * open_outfile(const char *const fname) {
return strcmp(fname, "-") == 0 ? stdout : fopen(fname, "w");
}


9月2日下午1点24分,cs < niv ... @ gmail.comwrote:
On Sep 2, 1:24 pm, cs <niv...@gmail.comwrote:

我是C的新手,非常感谢

以下的任何反馈程序,asplit,它将文件分成2个新的

文件,在第一个文件中放置一定数量的行,

以及第二个文件中的所有其余行。 br />

任何关于非便携性,风格不合理,

直接错误或其他任何内容的评论都会非常感谢

赞赏。


使用gcc 4.1.2编译好,而-std = c99 -pedantic

-Wall,没有任何警告,似乎有效。


有两个文件,一个标题和一个源文件。


##开始asplit.h ##


#ifndef ASPLIT_H_

#define ASPLIT_H_
I''m new to C and would appreciate any feedback on the
following program, asplit, which splits a file into 2 new
files, putting a certain number of lines in the first file,
and all the rest in the second file.

Any comments as to non-portability, stylistic infelicities,
outright bugs or anything else would be very much
appreciated.

It compiles fine using gcc 4.1.2, and --std=c99 -pedantic
-Wall, with no warnings, and seems to work.

There are two files, a header and a source file.

## Begin asplit.h ##

#ifndef ASPLIT_H_
#define ASPLIT_H_



我更喜欢...


#ifndef h_asplit_h

#define h_as plit_h

I prefer...

#ifndef h_asplit_h
#define h_asplit_h


enum e_status {SUCCESS,ERROR_FILE_INPUT,ERROR_FILE_OUTPUT_A,

ERROR_FILE_OUTPUT_B};
enum e_status { SUCCESS, ERROR_FILE_INPUT, ERROR_FILE_OUTPUT_A,
ERROR_FILE_OUTPUT_B };



如果包含

< errno.his,则保留以E开头的大写标识符。所以你对这些名字的坚定性。

Capitalised identifiers that begin with E are reserved if
<errno.his included. So you are robustness with those names.


typedef enum e_status status;


typedef struct {

int status;

long int num_rem_lines;

} asplit_result;
typedef enum e_status status;

typedef struct {
int status;
long int num_rem_lines;
} asplit_result;



< snip>

<snip>


asplit_result * asplit(const char * in_file,const char
asplit_result * asplit(const char *in_file, const char



你可以按原样返回一个结构你不需要动态地给b $ b分配它,从而在呼叫者身上放置一个burdon来免费

吧。


在任何情况下,更常见的是返回一个简单的int并让

调用者将指针作为输出参数传递...


int asplit(const char * in_file,

const char * out_file_a,

const char * out_file_b,

long num_lines,

long * rem_lines);


当它只是一个状态时动态分配一个对象是非常罕见的

返回。

You can return a struct as is. You don''t need to dynamically
allocate it, thereby placing a burdon on the caller to free
it.

In any case, it''s more usual to return a simple int and let
the caller pass in a pointer as an output parameter...

int asplit( const char *in_file,
const char *out_file_a,
const char *out_file_b,
long num_lines,
long *rem_lines );

It''s very unusual to dynamically allocate an object to
return when it''s just a status.


* out_file_a,const char * out_file_b,const long int

num_lines);
*out_file_a, const char *out_file_b, const long int
num_lines);



没有必要将num_lines声明为const。

There''s no point declaring num_lines to be a const.


#endif / * ASPLIT_H_ * /


##结束asplit.h ##


##开始asplit.c ##


#include< stdio.h>

#include< stdlib.h>

#include< string.h>


#include< getopt.h>
#endif /*ASPLIT_H_*/

## End asplit.h ##

## Begin asplit.c ##

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

#include <getopt.h>



这不是C标准头。 [可能是POSIX,我不能回复。)

This is not a C standard header. [It may be POSIX, I can''t
recall.]


#include" asplit.h"


char * copy_string(const char * const s);

int close_file(FILE * f);

FILE * open_infile(const char * fname);

FILE * open_outfile(const char * fname);


/ *调用程序的名称。 * /

char * program_name;
#include "asplit.h"

char *copy_string(const char *const s);
int close_file(FILE * f);
FILE * open_infile(const char * fname);
FILE * open_outfile(const char *fname);

/* Name under which program was invoked. */
char *program_name;



除非您打算更改指向的字符串,否则

您应该使用const char *。

Unless you intent to change the string that''s pointed to,
you should make that const char *.


void usage(int status){
void usage(int status) {



我更喜欢......


无效使用(FILE * fp)

{

fprintf(fp,...);

fprintf(fp,... );

fprintf(fp,...);

...

退出(fp == stderr?EXIT_FAILURE:EXIT_SUCCESS);

}


当用户调用程序时,允许usage()向

标准输出提供相同的用法消息请求

寻求帮助(在这种情况下,消息应该写成

到stdout,而不是stderr。)YMMV。


< ;剪断>

I prefer...

void usage(FILE *fp)
{
fprintf(fp, ...);
fprintf(fp, ...);
fprintf(fp, ...);
...
exit(fp == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
}

That allows usage() to give the same usage message to
stdout when the user invokes the program only to ask
for help (in which case the message should be written
to stdout, not stderr.) YMMV.

<snip>


printf(

" \ n
printf(
"\n



这通常不好使用行拼接的样式

分解字符串文字。[换行符串转换

将代码移植到其他系统时可以转换行拼接

你应该只使用普通字符串

字面连接...

World \ n);


请注意字符串文字有一个长度限制。

[我不记得了,某事像509个字符。]


cosnt char * out_file_a,

< snip>

It''s generally not good style to use line splicing to
break up string literals. [Translations of line breaks
when porting code to other systems can turn line splices
into syntax errors.] You should just use ordinary string
literal concatination...

printf( "Hello"
" World\n" );

Note that there is a length limit on string literals.
[I can''t recall it, something like 509 characters.]

cosnt char *out_file_a,
<snip>


input_file =(char *)copy_string(optarg);
input_file = (char *) copy_string(optarg);



由于copy_string被声明为

已经返回char *,因此强制转换是多余的。如果你需要为一个作业投一个

的返回值,它可以是一个符号在

你做错了什么。因此,这样的演员经常被视为立即可疑。


无论如何,我不知道为什么你不只是解析

argv自己。


< snip>

The cast is redundant since copy_string is declared as
returning a char * already. If you need to cast a
return value for an assignment, it can be a sign that
you''re doing something wrong. Hence, such a cast is
often viewed as immediately suspicious.

In any case, I''m not sure why you don''t just parse
argv yourself.

<snip>


>

exit(1);
>
exit(1);



1不是传递给退出的可移植值。使用0,

EXIT_SUCCESS或EXIT_FAILURE。


< snip>

1 is not a portable value to pass to exit. Use 0,
EXIT_SUCCESS or EXIT_FAILURE.

<snip>


int close_file(FILE * f){

if(f!= stdin&& f!= stdout&& f! = stderr){

fclose(f);
int close_file(FILE * f) {
if (f != stdin&& f != stdout&& f != stderr) {
fclose(f);



您应该检查fclose的状态。如果实现(或操作系统)无法刷新缓冲区,则输出文件可能会失败。

You should check the status of fclose. It can fail for
output files if the implementation (or the os) can''t
flush the buffer.


返回0;

}

返回1;

}
return 0;
}
return 1;
}



-

彼得

--
Peter


这篇关于请求批评第一个程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆