#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
typedef int bool;
#define true 1
#define false 0
#define A 65
#define Z 90
#define a 97
#define z 122
#define NEWLINE 10
int main(int argc, char* argv[])
{
int noArgReverse();
int argReverse(int i, char* c[]);
if (argc == 1){
if (noArgReverse() == 0)
return 0;
else
return 1;
}
if (argc > 1){
if (argReverse(argc, argv) == 0)
return 0;
else
return 1;
}
else{
fprintf(stderr, "unknown error detected.\n");
return 1;
}
}
int noArgReverse()
{
char charInput[10000];
int pointerArray[5000];
int pointerCount = 0;
bool wordStart = false;
int indexer;
int lineLength;
int parser;
char currInput;
pointerArray[0] = 0; // first word would start at 0 be default
while (currInput != EOF){
lineLength = 0;
indexer = 0;
pointerCount = 0;
while ((currInput = getc(stdin)) != NEWLINE){
/*
* I am implementing a 10,000 char limit, as this seems an
* unreasonable length.
*/
if (lineLength == 9999){
fprintf(stderr, "Line length exceeded 10,000 chars. "
"This line and, if in the middle of a word,"
"will be split.\n");
break;
}
if (!wordStart){
if ((currInput >= A && currInput <= Z) || (currInput >= a && currInput <= z)){
wordStart = true;
}
}
while (wordStart){
charInput[lineLength++] = currInput;
currInput = getc(stdin);
//if the word has ended
if ((currInput < A || currInput > Z) && (currInput < a || currInput > z)){
wordStart = false;
charInput[lineLength++] = '\0';
if (pointerCount != 0){ // at least one word has been added
++indexer;
pointerArray[indexer] = pointerCount;
pointerCount = lineLength;
}
else //first word of the line to be added
pointerCount = lineLength;
}
}
}
while (indexer >= 0){
parser = pointerArray[indexer--];
while (charInput[parser] != '\0')
fprintf (stdout, "%c", charInput[parser++]);
fprintf (stdout, " ");
}
fprintf (stdout, "\r\n");
if (lineLength == 0){
currInput = EOF;
}
}
return 0;
}
int argReverse (int argc, char* argv[])
{
char charInput[10000];
int pointerArray[5000];
int pointerCount = 0;
bool wordStart = false;
int indexer;
int lineLength;
int parser;
char currInput;
FILE *currentFile;
while (argc > 0){
currentFile = fopen(argv[argc--], "r");
while ((currInput = getc(currentFile)) != EOF){
lineLength = 0;
indexer = 0;
pointerCount = 0;
while (currInput != NEWLINE){
/*
* I am implementing a 10,000 char limit, as this seems an
* unreasonable length for a single line.
*/
if (lineLength == 9999){
fprintf(stderr, "Line length exceeded 10,000 chars. "
"This line and, if in the middle of a word, the word, "
"will be split.\n");
break;
}
if (!wordStart){
if ((currInput >= A && currInput <= Z) || (currInput >= a && currInput <= z)){
wordStart = true;
}
}
while (wordStart){
charInput[lineLength++] = currInput;
currInput = getc(currentFile);
//if the word has ended
if ((currInput < A || currInput > Z) && (currInput < a || currInput > z)){
wordStart = false;
charInput[lineLength++] = '\0';
if (pointerCount != 0){ // at least one word has been added
++indexer;
pointerArray[indexer] = pointerCount;
pointerCount = lineLength;
}
else //first word of the line to be added
pointerCount = lineLength;
}
}
}
}
fclose(currentFile);
}
return 0;
}
所以对于我的第一个函数,我收到一个错误,我似乎无法在调试时找到底部,或者说,我不知道如何解决。该函数应该从stdin
获取输入,并以相反的顺序打印单词(字符应保持顺序,因此“这是一个句子”应该是“句子a是这个”)。很简单。但是,当我提供样本输入时,我得到的输出都是错误的。
输入
This is sample
input for testing
输出:
testing for input sample is This
This
输入有一个返回,但输出在行之间有额外的返回,并且不会分割行。
所以,它不应该在它应该的时候打印换行符,而是在它结束时再次打印第一个输入的单词。
我遇到的第二个问题是第二组代码argReverse
函数。打开文件后,在这种情况下我使用test.txt,这是一个简单的文本文件,有几行短语和空行,第一次使用getc
会返回一个分段错误。我读到这是一个权限或失败的文件打开,但我不知道该怎么做才能解决这个问题。我试图先打开最后一个文件并从那里开始工作,显然,这应该可以处理多个文件,但我甚至无法打开一个文件。我不知道该怎么做才能解决这个问题。我尝试移动getc
循环之外的while
,同样的问题。我猜我打开文件时做错了,但我不知道它是什么。
答案 0 :(得分:2)
关于风格的说明:
bool
类型,true
和false
在<stdbool.h>
中定义。
使用'A' 'Z' 'a' 'z' '\n'
之类的字符常量而不是硬编码的数字,和/或使用来自isalpha
的{{1}}等字符分类函数。
“反向”函数在结束时返回0,所以返回任何内容都没有意义。它们应该被声明为返回<ctype.h>
。如果他们确实返回了有用的东西,我会从void
返回该值(消除main
语句)。例如,
if
将大型数组放在堆栈上通常是一个坏主意。 (大是主观的,但我使用2K字节作为经验法则。)对于非重入函数,您可以将数组声明为if ( argc == 1 )
return noArgReverse();
以使它们脱离堆栈。对于可重入函数,您可以static
数组,最后malloc
。
设计说明:
free
函数将读取一行并将其放入缓冲区。无需一次阅读一个角色。
处理命令行参数时,规范循环为
fgets
你的seg-fault的原因是你正在使用int main( int argc, char *argv[] )
{
for ( int i = 1; i < argc; i++ )
printf( "argv[%d] is \"%s\"\n", i, argv[i] );
}
,C规范保证argv[argc]
。因此,您将NULL
传递给NULL
。此外,您应始终检查fopen
的返回值,因为fopen
如果无法打开文件,则会返回fopen
。
到目前为止,代码中最大的设计问题是重复。你有两个几乎完全相同的功能,这是调试和维护的噩梦,因为每次更改都需要进行两次,并进行两次测试。解决方案是定义一个NULL
函数,它将文件指针作为输入。 reverse
函数应该负责打开/关闭文件,或者在没有任何参数时传递main
。
示例代码:
stdin