为什么我不能初始化指针变量并且不能使用gets?

时间:2019-11-19 12:39:12

标签: c loops for-loop fgets c-strings

我的书中有这段代码,但是很长一段时间我都试图理解它,但我没有。因此,该代码从用户处获取输入,并每行打印输出的单词以及单词的大小。它还根据该行打印输出。并且不包括任何内容。 ,!等等..  示例:

输入:

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;
}

3 个答案:

答案 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可能会对您的编译器产生影响。

另一方面,这没什么问题

   char* exclude = " .,!\t"; // I get an error message here (This entity cannot be initialized.)
就标准C而言,

但这仍然很危险,因为您正在分配exclude指向一个不能修改的值,但是该变量的类型不能表示不可修改的值。合格的编译器无论如何都应该接受代码,但是在某些情况下某些人会拒绝它。

  

此外,为什么它对我不起作用?以及我该如何解决?

该代码具有一些细微的缺陷,不仅限于我已经提到的那些缺陷,并且任何给定的编译器是否接受它都取决于编译器和编译命令。但是,我所讨论的两个问题可以通过

解决
  • 使用fgets()代替gets()。前者允许您指定目标缓冲区的大小,以免溢出:

    while (fgets(str[i], 80, stdin) >= 0)
    

    请注意,那里仍然有一些特殊之处,例如,当输入等于或超过80个字符时会发生什么情况。

  • exclude声明为指向const char的指针:

    const char *exclude = " .,!\t";