我应该给我“固定”代码,以使其在文件中显示正确数量的可见字符(也包括空格)。正确的数字应该是977。我以前从未处理过文件,而且我不知道显示正确的数字需要做什么。
* Driver Menu System for Homework
* Andrew Potter - Mar 5, 2019 <-- Please put your name/date here
*/
#include <stdio.h>//header file for input/output -
#include <stdlib.h>
#include <ctype.h>
// since you will place all your assigned functions (programs) in this file, you do not need to include stdio.h again!
int menu(void); //prototype definition section
void hello(void);
void countall(void);
int main(void)
{
int selection = menu();
while(selection != 99) {
switch(selection) {
case 1:
hello();
break;
case 2:
countall();
break;
case 3:
break;
case 4:
break;
default:
printf("Please enter a valid selection.\n");
}
selection = menu();
}
return 0;
}
int menu(void) {
int choice;
printf("***************************\n");
printf(" 1. Hello \n");
printf(" 2. Countall\n");
printf(" 3. \n");
printf(" 4. \n");
printf("99. Exit\n");
printf("Please select number and press enter:\n");
printf("***************************\n");
scanf("%d", &choice);
getchar();
return choice;
}
void hello(void) {
printf("Hello, World!!!\n");
}
//*****Andrew 5/1/19*****
#define SLEN 81 /* from reverse.c */
/* original header: int count(argc, *argv[]) */
void countall(void)
{
int ch; // place to store each character as read
FILE *fp; // "file pointer"
long unsigned count = 0;
char file[SLEN]; /* from reverse.c */
/*Checks whether a file name was included when run from the command prompt
* The argument count includes the program file name. A count of 2 indicates
* that an additional parameter was passed
if (argc != 2)
{
printf("Usage: %s filename\n", argv[0]);
exit(EXIT_FAILURE);
}
* The following uses the second parameter as the file name
* and attempts to open the file
if ((fp = fopen(argv[1], "r")) == NULL)
{
printf("Can't open %s\n", argv[1]);
exit(EXIT_FAILURE);
} */
/*************************************
Code from reverse.c included to make the program work from within our IDE
*************************************/
puts("Enter the name of the file to be processed:");
scanf("%s", file);
if ((fp = fopen(file,"rb")) == NULL) /* read mode */
{
printf("count program can't open %s\n", file);
exit(EXIT_FAILURE);
}
/* EOF reached when C realizes it tried to reach beyond the end of the file! */
/* This is good design - see page 573 */
while ((ch = getc(fp)) != EOF)
{
if (isprint(ch)) {
count++;
}
else if (isprint(ch)) {
count++;
}
putc(ch,stdout); // same as putchar(ch);
count++;
}
fclose(fp);
printf("\nFile %s has %lu characters\n", file, count);
}
我期望使用isprint和isspace的组合可以得到正确数量的可见字符,但是我通常会得到2086。 分配方向为:“ Word识别977个字符,包括空格。您当前的countall()认为有1043个。对代码进行必要的更正以仅计算可见字符和空格!(提示:在教科书中查看567。) “在我编辑任何代码之前,计数是1043,现在是2020。我需要977。
答案 0 :(得分:2)
isprint()
返回一个布尔结果-如果字符不是“可打印的”,则返回零,否则返回非零。因此isprint(ch) != '\n'
没有任何意义。您在问题中的完整表达甚至没有意义,但是我将在最后继续进行说明。
isprint()
本身对所有可打印字符都返回true(非零),因此您不需要其他测试。此外,您无条件地在每个条件块中递增count
,因此您要对每个字符计数,而有些则要计数两次。
您只需要:
if( isprint(ch) )
{
count++;
}
putc( ch, stdout ) ;
虽然您的代码显然是不完整的片段,但不清楚您在哪里或如何阅读ch
。您那里需要getc()
或同等学历。
while( (ch = getc(fp)) != EOF )
{
if( isprint(ch) )
{
count++;
}
putc( ch, stdout ) ;
}
目前尚不清楚您是否需要计算所有空格(包括空格,制表符和换行符)还是仅计算“空格”。如果是这样,请注意isprint()
将匹配空格,但不能匹配换行符或制表符。 isspace()
与所有这些都匹配,但不应单独计入isprint()
,因为'space'既包含空白又包含可打印的集合。如果要计算换行符和制表符(可能性不大;“垂直制表符”),则:
while( (ch = getc(fp)) != EOF )
{
if( isprint(ch) || isspace(ch) )
{
count++;
}
putc( ch, stdout ) ;
}
您似乎会误解的C的另一方面是布尔表达式如何工作。要测试单个变量的多个值,您必须编写:
if( var == x || var == y || var == z )
您写了:
if( var == x || y || z )
当您大声朗读它时,这可能在英语(或其他自然语言)中有意义,但在C语言中则表示:
if( var == (x || y || z ) )
将(x || y || z )
评估为true
或false
并将其与var
进行比较。
可能值得考虑您现有解决方案的语义,以显示其实际编译的原因,但会产生它执行的错误结果。
首先,
isprint(ch) != '\n' || '\t' || '\0'
出于先前所述的原因,等效于isprint(ch) != true
。因此,您可以为不可打印的所有字符增加计数器。
然后在这里
isspace(ch) == NULL
NULL
是表示无效指针的宏,而isspace()
不返回指针。但是NULL
将隐式转换为零(或为false)。因此,在这里您可以为不是空格的所有可打印字符增加计数器。
最后,您无条件在这里计算每个字符:
putc(ch,stdout); // same as putchar(ch);
count++;
所以您的结果将是:
number-of-non-printing-characters +
number-of-printing-characters - number-of-spaces +
total-number-of-characters
我认为是(2 x file-length) - number-of-spaces
最后请注意,如果在“二进制”模式下打开CR + LF行尾(Windows上的常规文本文件)的文本文件,isspace()
将为每个换行计算两个字符。确保以“文本”模式打开(无论平台如何)。
答案 1 :(得分:1)
来自isprint()
:
可打印字符是在显示器上占据打印位置的字符(与控制字符相反,用iscntrl进行检查)。
和
如果c确实是可打印的字符,则该值不同于零(即true)。否则为零(即false)。
因此该功能应该足够了。请注意,您必须确保从is...()
个无符号值中输入所有这些<ctype.h>
函数。因此,如果您使用不确定来源的值,最好将其转换为char unsigned
。
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
int main(void)
{
char const *filename = "test.txt";
FILE *input = fopen(filename, "r");
if (!input) {
fprintf(stderr, "Couldn't open \"%s\" for reading. :(\n\n", filename);
return EXIT_FAILURE;
}
long long unsigned count = 0;
for (int ch; (ch = fgetc(input)) != EOF;) {
if (isprint(ch))
++count;
}
fclose(input);
printf("Count: %llu\n\n", count);
}
如果我不太幸运地猜出要计算哪些字符,请查看ctype.h
,那里有一张桌子。
答案 2 :(得分:0)
if ((ch == '\t') || isprint(ch))
count++;
如果您想以不同的方式处理制表符(也许要计算它们使用了多少空格):
if (ch == '\t') {
/* Do smth */
} else if (isprint(ch)) {
count++;
}
这应该足够了。