【问题标题】:Why is this string empty?为什么这个字符串是空的?
【发布时间】:2013-07-11 20:05:15
【问题描述】:

我有这个小问题,无法解决。
问题是我试图通过要求用户插入它来加载函数LOAD 中的所有四个字符串。一切似乎都很好,我没有收到任何编译器错误。但是eaf 保持。我尝试了很多方法,甚至将scanf替换为getsgets_sfgets,但没有任何改变。

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

void LOAD(char eaf[], char initials[], char finals[], char symbols[]);
int COMPARE(char s[], char eaf[]);

int main()
{
    char eaf[10],initials[1],finals[10],symbols[5];
    LOAD(eaf, initials, finals, symbols);
    return 0;
}


void LOAD(char eaf[], char initials[], char finals[], char symbols[])
{
    printf("Insert states of the optimized AFD\n");
    scanf( " %s", eaf);

    printf("Insert AFD initial state\n");
    do
    {
        scanf( " %s", initials);
    } while (COMPARE(initials, eaf));

    printf("Insert final state(s)\n");
    do
    {
        scanf( " %s",finals);
    } while (COMPARE(finals, eaf));

    printf("Insert the language symbols\n");
    scanf( " %s",symbols);
}

int COMPARE(char s[], char eaf[])
{
    int i;
    char *ptr;
    for(i; i < strlen(s); i++){
            printf("%d\n", i);
        while(ptr==NULL){
            ptr = strchr(eaf, *s);
        }
    }
    if (ptr == NULL) return 1;
    else return 0;
}

我做错了什么?这只是更大程序的一小部分,但其余部分无用,因为eaf 是空的。我认为问题出在使用scanf,但正如我所说的,其他功能也不能正常工作。我希望任何人都可以帮助我。谢谢

编辑:我检查了strlen(eaf)

【问题讨论】:

  • 您忘记在 COMPARE 中初始化 i。 (另外,不要将任何不是 #defined 宏的内容全部大写。)
  • 注意:不要在循环测试中调用strlen。这需要strlen 在每次迭代时遍历整个字符串。许多编译器可以对其进行优化,但是当它碰巧没有被优化时,性能就会像石头一样下降。在循环外计算一次长度。 (我会抱怨固定大小的缓冲区和scanf,但修复这些需要更多的工作。)
  • initials[1]scanf( " %s", initials);。您超出了数组边界,看起来initials 的 0 终止符被写入了eaf
  • 您的比较功能并不是很有用。使用gcc -Wall -Werror ... 编译您的程序。
  • while(ptr==NULL){ ptr 在 COMPARE() 中未初始化

标签: c string function


【解决方案1】:

使用“scanf”进行输入是危险的,而您已经陷入了这种危险之中。当您要求它将首字母作为字符串读取并添加终止 0 时,您允许它覆盖“eaf”的内容。

最终,字符串为空,因为您的数组尺寸错误。您为“initials”提供了一个大小为 1 的数组,它没有为尾随的 '\0' C 字符串终止符提供空间。

ideone上查看此代码的现场演示:

#include <stdio.h>

void report(char* eaf, char* initials, char* foo)
{
    printf("eaf = %p, initials = %p, foo = %p\n", eaf, initials, foo);;
    printf("*eaf = %d, *initials = %d, *foo = %d\n", eaf[0], initials[0], foo[0]);
}

void load(char eaf[], char initials[], char foo[])
{
    printf("load\n");
    report(eaf, initials, foo);

    printf("Enter EAF\n");
    scanf(" %s", eaf);
    report(eaf, initials, foo);

    printf("Enter initial state\n");
    scanf(" %s", initials);
    report(eaf, initials, foo);
}

int main(int argc, const char* argv[])
{
    char eaf[10], initials[1], foo[10];
    report(eaf, initials, foo);
    load(eaf, initials, foo);
    report(eaf, initials, foo);

    return 0;
}

您应该在调试器中浏览过这个,并观察“eaf”和“initials”的值,看看在您进行过程中发生了什么。

你必须用 C 编写这个程序吗?似乎使用 perl 或 python 等脚本语言对您来说可能更容易。

这是一个开始解决问题的有效 C 方法,请注意,我实际上并没有解决问题,但它会更容易看到它。

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

void report(char* eaf, char* initials, char* foo)
{
    printf("eaf = %p, initials = %p, foo = %p\n", eaf, initials, foo);;
    printf("*eaf = %d, *initials = %d, *foo = %d\n", eaf[0], initials[0], foo[0]);
}

void load(const char* label, const char* into, size_t intoSize)
{
    assert(intoSize > 1); // can't store a string in 1 character.
    printf("%s\n", label);

    char input[1024] = "";
    fgets(input, sizeof(input), stdin);

    size_t len = strlen(input);
    // strip trailing \n off.
    if (len > 0 && input[len - 1] == '\n') {
        input[--len] = 0;
    }

    // abort on empty input
    if (len <= 0) {
        fprintf(stderr, "Invalid input - terminated.\n");
        exit(1);
    }

    if (len >= intoSize) {
        fprintf(stderr, "Invalid input - length was %u, limit is %u\n", len, intoSize - 1);
        exit(2);
    }

    strncpy(into, input, intoSize);
}

int main(int argc, const char* argv[])
{
    char eaf[10], initials[1], foo[10];
    report(eaf, initials, foo);

    load("Insert states of the optimized AFD", eaf, sizeof(eaf));
    report(eaf, initials, foo);

    load("Insert initial AFD state", initials, sizeof(initials));
    report(eaf, initials, foo);

    printf("eaf = %s\ninitials = %s\n", eaf, initials);

    return 0;
}

ideone here观看现场演示。

【讨论】:

  • 糟糕 - 我在此处粘贴的副本中断言错误:)
  • 非常感谢!你解决了我的问题,我相信它就像你说的那样在数组维度中。我也从你的回答中得到了一些其他的建议。实际上我在 Python 中有一定的基础,在那种语言中这会容易得多,但遗憾的是我必须用 C 来编写它。再次感谢!
【解决方案2】:

scanf 中的格式字符串很可能是罪魁祸首; %s 之前有一个额外的空格

变化:

scanf( " %s", eaf);

scanf( "%s", eaf);

为你所有的scanf's。

它没有将您的输入放入eaf,因为它正在寻找格式为“blahblahblah”(注意开头的空格)而不是“blahblahblah”的字符串>"

编辑

以上无视,

空白:任何空白字符都会触发对零个或多个空白字符的扫描。空白字符的数量和类型不需要在任一方向上匹配。

另外,你应该在你的 COMPARE 函数中初始化 i(我不明白你怎么没有从你的编译器中得到一个愤怒的警告),我没有修改就运行了你的代码,strlen(eaf) 返回了正确计数(就在scanf 之后)。

【讨论】:

  • 不。 scanf 格式字符串中的空格表示“跳过任意数量的空格”。
  • @user2357112:甚至没有空格?
  • @user2357112 whitespace: Any whitespace characters trigger a scan for zero or more whitespace characters. The number and type of whitespace characters do not need to match in either direction. ...废话,你是对的;我错过了“零个或多个”部分......
  • 它没有解决主要问题,但我感谢您的努力。是的,我忘了在函数COMPARE 中初始化i。谢谢!
猜你喜欢
  • 2011-12-06
  • 2013-02-20
  • 1970-01-01
  • 2013-01-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多