【问题标题】:scanf changes values from other stringsscanf 改变其他字符串的值
【发布时间】:2015-10-02 07:28:44
【问题描述】:

我主要用 Java 开发软件,但目前我正在尝试用 C 语言做一些事情,但遇到了一个奇怪的问题。

我使用scanf() 方法更改字符串的值,但scanf() 不仅更改参数化字符串的值,它还更改其他字符串的值。

现在我的问题是:我只是被开发人员友好的 Java 宠坏了,而且我太笨了,无法正确使用它吗?我看不出我在哪里做错了。

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

int main(int argc, char *argv[])
{
   char lFileType[] = ".txt";
   char lFilePath[] = "C:\\Notenverwaltungssystem";
   char lFileFinalPath[] = "";
   char lFileName[] = "";

    printf( "lFileType before scanf: " );
    printf( "%s \n", lFileType );

    printf( "lFilePath before scanf: " );
    printf( "%s \n", lFilePath );

    printf( "lFileName before scanf: " );
    printf( "%s \n", lFileName );

    printf( "lFileFinalPath before scanf: " );
    printf( "%s \n\n", lFileFinalPath );

    printf( "Bitte geben Sie den Namen der Pruefung an: \n\n" );

    scanf( "%s", &lFileName );

    printf( "\nlFileType after scanf: " );
    printf( "%s \n", lFileType );

    printf( "lFilePath after scanf: " );
    printf( "%s \n", lFilePath );

    printf( "lFileName after scanf: " );
    printf( "%s \n", lFileName );

    printf( "lFileFinalPath after scanf: " );
    printf( "%s \n\n", lFileFinalPath );

  system("PAUSE");  
  return 0;
}

预期输出:

lFileType before scanf: .txt
lFilePath before scanf: C:\Notenverwaltungssystem
lFileName before scanf:
lFileFinalPath before scanf:
Bitte geben Sie den Namen der Pruefung an:
Test
lFileType after scanf: .txt
lFilePath after scanf: C:\Notenverwaltungssystem
lFileName after scanf: Test
lFileFinalPath after scanf:

Press any key to continue . . .

执行程序时得到的输出:

lFileType before scanf: .txt
lFilePath before scanf: C:\Notenverwaltungssystem
lFileName before scanf:
lFileFinalPath before scanf:

Bitte geben Sie den Namen der Pruefung an:
Test
lFileType after scanf: .txt
lFilePath after scanf: st
lFileName after scanf: Test
lFileFinalPath after scanf: est

Press any key to continue . . .

【问题讨论】:

  • 关于缓冲区大小有几个答案。我想补充一点,scanf( "%s", &amp;lFileName )可以改为scanf( "%s", lFileName ),因为lFileName是缓冲区的地址,不需要&amp;

标签: c arrays scanf


【解决方案1】:

当你像这样定义一个字符串时:

char lFileName[] = "";

它只分配了一个字节(用于终止'\0')。相当于这样:

char lFileName[1] = "";

如果您尝试通过scanf 将某些内容读入此字符串,那么您将遇到缓冲区溢出。

将此(和类似的定义)更改为例如

char lFileName[PATH_MAX] = "";

(请注意,您可能需要在程序开始附近使用#include &lt;limits.h&gt; 才能获得PATH_MAX 的定义)。


还有一点:将字符串传递给scanf 时,您不需要取消引用它,所以:
scanf( "%s", &lFileName );

应该是:

scanf( "%s", lFileName );

(对于简单的标量类型,例如 intfloat,您确实需要将指针传递给变量,这可能会让 C 新手感到困惑。)

【讨论】:

  • 嗯,这对我来说很新鲜......谢谢你的快速回答
【解决方案2】:

您的所有数组都定义为与提供的初始化字符串相同的大小。所以,本质上,

char lFileFinalPath[] = "";
char lFileName[] = "";

长度为 1,这是您不想要的。如果您希望数组在程序的后面部分保持不同的长度,您可能需要明确提供大小。

此外,将scanf() 输入限制为数组大小始终被认为是一种好习惯,只要有可能,例如定义为类似的数组

char lFileType[128] = {0};

您应该使用scanf() 格式

scanf("%127s", lFileType);

避免因输入较长而导致缓冲区溢出的可能性。

【讨论】:

  • 啊,我明白了...非常感谢
【解决方案3】:
char lFileName[] = ""; 

这只是分配 1 个字节的内存(对于空字符 '\0'),因为您没有指定数组的大小。 scanf 函数尝试将用户输入字符串存储在数组边界之外,从而导致运行时错误。

#define FILE_LEN  64;//select a size suitable for you.
char lFileName[FILE_LEN] = "";

另一种方法是使用 malloc() 或 calloc() 动态分配内存。

char *lFileName = NULL;
lFileName = calloc(FILE_LEN,1);

并且永远记得使用free()释放动态分配的内存。否则可能会导致内存泄漏。

free(lFileName);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-02-28
    • 2021-01-08
    • 2015-04-05
    • 1970-01-01
    • 1970-01-01
    • 2021-01-29
    • 1970-01-01
    • 2022-07-14
    相关资源
    最近更新 更多