我的书中有这段代码,但是很长一段时间我都试图理解它,但我没有。因此,该代码从用户处获取输入,并每行打印输出的单词以及单词的大小。它还根据该行打印输出。并且不包括任何内容。 ,!等等.. 示例:
输入:
Hello, I am new here.
trying to learn.
输出:
Words typed on line number 1:
Hello(5)
I(1)
am(2)
new(3)
here(4)
Words typed on line number 2:
trying(6)
to(2)
learn(5)
此外,该代码可在我的朋友计算机上使用,但不能在我的计算机上使用。我不断收到错误消息,如下所示。你能给我解释一下吗?另外,为什么它对我不起作用?以及如何解决?我尝试使用fgets,但是没有用。
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
int main()
{
char str[10][81];
char* ptoken, * ptr;
int i = 0, maxstr = 0;
char* exclude = " .,!\t"; // I get an error message here (This entity cannot be initialized.)
printf("Enter the text you want on multiple lines\n");
printf("after you enter every thing pres ctrl+z and Enter \n\n");
while (gets(str[i])) // I get an error message here (The identifier gets cant be found).
{
str[i++];
maxstr++;
}
for (i = 0; i < maxstr; i++) {
printf("\n<< Words typed on line number %d> \n", i + 1);
ptr = str[i];
ptoken = strtok(ptr, exclude);
while (ptoken != NULL) {
printf("strlen(%s) = %d\n", ptoken, strlen(ptoken));
ptoken = strtok(NULL, exclude);
}
}
return 0;
}
答案 0 :(得分:2)
char* exclude = " .,!\t"; // I get an error message here (This entity cannot be initialized.)
尝试修改字符串文字会产生未定义的行为。 const
可以防止您无意间这样做(即,除非您通过强制转换删除了const
限定符,否则尝试通过指针编写的代码将无法编译。
char const *exclude =" .,!\t";
while (gets(str[i])) // I get an error message here (The identifier gets cant be found).
不赞成使用gets,因为它很危险,它可能导致缓冲区溢出。
代替使用fgets
while (fgets(str[i],sizeof(str),stdin))
需要注意的地方
printf("strlen(%s) = %d\n", ptoken, strlen(ptoken));
长期使用%ld
的strlen()返回类型
printf("strlen(%s) = %ld\n", ptoken, strlen(ptoken));
答案 1 :(得分:1)
似乎您正在将该程序编译为C ++程序。如果是这样,那么您需要编写示例
const char *exclude = " .,!\t";
^^^^^
函数gets
不是标准的C或C ++函数。而是函数fgets
。
在此while循环中
while (gets(str[i])) // I get an error message here (The identifier gets cant be found).
{
str[i++];
maxstr++;
}
这些声明
str[i++];
maxstr++;
没有道理。
像这样重写循环
for ( ; maxstr < 10 && fgets( str[maxstr], sizeof( str[maxstr] ), stdin ) != NULL; maxstr++ )
{
str[maxstr][ strcspn( str[maxstr], "\n" )] = '\0';
}
我认为这条线
str[maxstr][ strcspn( str[maxstr], "\n" )] = '\0';
需要说明。函数fgets
可以将换行符'\n'
附加到输入的字符串中。要删除它(更精确地用字符来代替以零结尾的字符'\0'
),可以使用字符串函数strcspn
来查找换行符的位置。之后,替换完成。
替换这两个语句
ptr = str[i];
ptoken = strtok(ptr, exclude);
为
ptoken = strtok( str[i], exclude);
那是变量ptr
是多余的。
并且不要使用例如10的幻数。请改用命名常量。
答案 2 :(得分:1)
我不断收到错误消息,如下所示。你能给我解释一下吗?
不完全是。详细信息在某种程度上取决于您的编译器。
但是,关于
while (gets(str[i])) // I get an error message here (The identifier gets cant be found).
,问题肯定出在功能gets()
上。永远不要使用这个无法治愈的有缺陷的功能,并且意识到这一点,在2011版标准中从C语言中删除了该功能。至少在某些情况下,大多数编译器仍然接受它,但是有些人拒绝它。在这方面,是否定义了宏_CRT_SECURE_NO_WARNINGS
可能会对您的编译器产生影响。
另一方面,这没什么问题
就标准C而言,char* exclude = " .,!\t"; // I get an error message here (This entity cannot be initialized.)
但这仍然很危险,因为您正在分配exclude
指向一个不能修改的值,但是该变量的类型不能表示不可修改的值。合格的编译器无论如何都应该接受代码,但是在某些情况下某些人会拒绝它。
此外,为什么它对我不起作用?以及我该如何解决?
该代码具有一些细微的缺陷,不仅限于我已经提到的那些缺陷,并且任何给定的编译器是否接受它都取决于编译器和编译命令。但是,我所讨论的两个问题可以通过
解决使用fgets()
代替gets()
。前者允许您指定目标缓冲区的大小,以免溢出:
while (fgets(str[i], 80, stdin) >= 0)
请注意,那里仍然有一些特殊之处,例如,当输入等于或超过80个字符时会发生什么情况。
将exclude
声明为指向const char
的指针:
const char *exclude = " .,!\t";